From acad1755c117e9d6dbf1a1d819032ca08452f9c6 Mon Sep 17 00:00:00 2001 From: Richard Peters Date: Mon, 11 Sep 2023 08:27:17 +0200 Subject: [PATCH 1/5] feat: add tools/st_table_generator --- CMakeLists.txt | 2 + hal_st/stm32fxxx/CMakeLists.txt | 2 +- hal_st/stm32fxxx/DefaultClockNucleoG070RB.cpp | 2 +- hal_st/stm32fxxx/DefaultClockNucleoG070RB.hpp | 2 +- hal_st/stm32fxxx/PeripheralTableG0xx.xml | 22 ++ infra/CMakeLists.txt | 1 + infra/xml/CMakeLists.txt | 29 +++ infra/xml/XmlNavigator.cpp | 121 ++++++++++ infra/xml/XmlNavigator.hpp | 157 +++++++++++++ infra/xml/test/CMakeLists.txt | 12 + infra/xml/test/TestXmlNavigator.cpp | 80 +++++++ st/CMakeLists.txt | 11 + st/ldscripts/sections.ld | 2 + tools/CMakeLists.txt | 1 + tools/st_table_generator/CMakeLists.txt | 11 + tools/st_table_generator/Main.cpp | 216 ++++++++++++++++++ 16 files changed, 668 insertions(+), 3 deletions(-) create mode 100644 hal_st/stm32fxxx/PeripheralTableG0xx.xml create mode 100644 infra/CMakeLists.txt create mode 100644 infra/xml/CMakeLists.txt create mode 100644 infra/xml/XmlNavigator.cpp create mode 100644 infra/xml/XmlNavigator.hpp create mode 100644 infra/xml/test/CMakeLists.txt create mode 100644 infra/xml/test/TestXmlNavigator.cpp create mode 100644 tools/CMakeLists.txt create mode 100644 tools/st_table_generator/CMakeLists.txt create mode 100644 tools/st_table_generator/Main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bd83d04..769fd646 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,8 @@ else() set(HALST_EXCLUDE_FROM_ALL "EXCLUDE_FROM_ALL") endif() +add_subdirectory(infra) +add_subdirectory(tools) add_subdirectory(st) add_subdirectory(hal_st) add_subdirectory(hal_st_lwip) diff --git a/hal_st/stm32fxxx/CMakeLists.txt b/hal_st/stm32fxxx/CMakeLists.txt index f97a81e8..8d97f927 100644 --- a/hal_st/stm32fxxx/CMakeLists.txt +++ b/hal_st/stm32fxxx/CMakeLists.txt @@ -124,7 +124,7 @@ if (TARGET_MCU_VENDOR STREQUAL st) generate_xslt(hal_st.stm32fxxx generated/stm32fxxx/PinoutTableDefault.cpp GeneratePinoutTableCpp.xsl "${CMAKE_CURRENT_BINARY_DIR}/generated/stm32fxxx/PinoutTableDefaultStructure.xml") generate_xslt(hal_st.stm32fxxx generated/stm32fxxx/PinoutTableDefault.hpp GeneratePinoutTableHpp.xsl "${CMAKE_CURRENT_BINARY_DIR}/generated/stm32fxxx/PinoutTableDefaultStructure.xml") - generate_xslt(hal_st.stm32fxxx generated/stm32fxxx/PeripheralTableStructure.xml GeneratePeripheralTableStructure.xsl $,PeripheralTableWbxx.xml,PeripheralTableFxxx.xml> + generate_xslt(hal_st.stm32fxxx generated/stm32fxxx/PeripheralTableStructure.xml GeneratePeripheralTableStructure.xsl $,PeripheralTableWbxx.xml,$,PeripheralTableG0xx.xml,PeripheralTableFxxx.xml>> --stringparam mcu-document ${mcu_xml}) generate_xslt(hal_st.stm32fxxx generated/stm32fxxx/PeripheralTable.cpp GeneratePeripheralTableCpp.xsl "${CMAKE_CURRENT_BINARY_DIR}/generated/stm32fxxx/PeripheralTableStructure.xml") generate_xslt(hal_st.stm32fxxx generated/stm32fxxx/PeripheralTable.hpp GeneratePeripheralTableHpp.xsl "${CMAKE_CURRENT_BINARY_DIR}/generated/stm32fxxx/PeripheralTableStructure.xml") diff --git a/hal_st/stm32fxxx/DefaultClockNucleoG070RB.cpp b/hal_st/stm32fxxx/DefaultClockNucleoG070RB.cpp index 45189f33..f06aec4f 100644 --- a/hal_st/stm32fxxx/DefaultClockNucleoG070RB.cpp +++ b/hal_st/stm32fxxx/DefaultClockNucleoG070RB.cpp @@ -12,7 +12,7 @@ * VDD(V) = 3.3 * Main regulator output voltage = Scale1 mode */ -void ConfigureDefaultClockNucleo070RB() +void ConfigureDefaultClockNucleoG070RB() { RCC_OscInitTypeDef RCC_OscInitStruct = { 0 }; RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 }; diff --git a/hal_st/stm32fxxx/DefaultClockNucleoG070RB.hpp b/hal_st/stm32fxxx/DefaultClockNucleoG070RB.hpp index 8d80a348..08b72501 100644 --- a/hal_st/stm32fxxx/DefaultClockNucleoG070RB.hpp +++ b/hal_st/stm32fxxx/DefaultClockNucleoG070RB.hpp @@ -1,6 +1,6 @@ #ifndef HAL_ST_DEFAULT_CLOCK_HPP #define HAL_ST_DEFAULT_CLOCK_HPP -void ConfigureDefaultClockNucleo070RB(); +void ConfigureDefaultClockNucleoG070RB(); #endif diff --git a/hal_st/stm32fxxx/PeripheralTableG0xx.xml b/hal_st/stm32fxxx/PeripheralTableG0xx.xml new file mode 100644 index 00000000..c6448ac5 --- /dev/null +++ b/hal_st/stm32fxxx/PeripheralTableG0xx.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/infra/CMakeLists.txt b/infra/CMakeLists.txt new file mode 100644 index 00000000..13df52af --- /dev/null +++ b/infra/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(xml) diff --git a/infra/xml/CMakeLists.txt b/infra/xml/CMakeLists.txt new file mode 100644 index 00000000..3cb181b4 --- /dev/null +++ b/infra/xml/CMakeLists.txt @@ -0,0 +1,29 @@ +if (EMIL_HOST_BUILD) + FetchContent_Declare( + pugixml + GIT_REPOSITORY https://github.com/zeux/pugixml + GIT_TAG a0e064336317c9347a91224112af9933598714e9 # v1.13 + ) + + FetchContent_MakeAvailable(pugixml) +endif() + +add_library(infra.xml ${HALST_EXCLUDE_FROM_ALL} STATIC) + +target_include_directories(infra.xml PUBLIC + "$" +) + +target_link_libraries(infra.xml PUBLIC + infra.stream + pugixml +) + +if (EMIL_HOST_BUILD) + target_sources(infra.xml PRIVATE + XmlNavigator.cpp + XmlNavigator.hpp + ) +endif() + +add_subdirectory(test) diff --git a/infra/xml/XmlNavigator.cpp b/infra/xml/XmlNavigator.cpp new file mode 100644 index 00000000..ee001c44 --- /dev/null +++ b/infra/xml/XmlNavigator.cpp @@ -0,0 +1,121 @@ +#include "infra/xml/XmlNavigator.hpp" +#include + +namespace infra +{ + XmlNodeNavigator::XmlNodeNavigator(const std::string& contents) + { + document = pugi::xml_document(); + pugi::xml_parse_result result = document.load_string(contents.c_str()); + if (!result) + throw std::runtime_error("Document failed to load"); + + node = document; + } + + XmlNodeNavigator::XmlNodeNavigator(const pugi::xml_node& node) + : node(node) + {} + + XmlNodeNavigator XmlNodeNavigator::operator/(XmlNodeNavigatorToken token) const + { + auto child = node.child(token.name.c_str()); + if (child == pugi::xml_node()) + throw std::runtime_error(("Child " + token.name + " not found").c_str()); + + return { child }; + } + + std::string XmlNodeNavigator::operator/(XmlStringAttributeNavigatorToken token) const + { + for (auto attribute: node.attributes()) + if (attribute.name() == token.name) + return attribute.value(); + + throw std::runtime_error(("Attribute " + token.name + " not found").c_str()); + } + + infra::Optional XmlNodeNavigator::operator/(XmlOptionalStringAttributeNavigatorToken token) const + { + for (auto attribute = node.attributes_begin(); attribute != node.attributes_end(); attribute = ++attribute) + if (attribute->name() == token.name) + return infra::MakeOptional(std::string(attribute->value())); + + return infra::none; + } + + int32_t XmlNodeNavigator::operator/(XmlIntegerAttributeNavigatorToken token) const + { + for (auto attribute: node.attributes()) + if (attribute.name() == token.name) + return attribute.as_int(); + + throw std::runtime_error(("Attribute " + token.name + " not found").c_str()); + } + + infra::Optional XmlNodeNavigator::operator/(XmlOptionalIntegerAttributeNavigatorToken token) const + { + for (auto attribute: node.attributes()) + if (attribute.name() == token.name) + return infra::MakeOptional(attribute.as_int()); + + return infra::none; + } + + // bool XmlNodeNavigator::operator/(XmlBoolNavigatorToken token) const + //{ + // auto member = object.GetOptionalBoolean(token.name); + // if (member == infra::none) + // throw std::runtime_error(("Boolean " + token.name + " not found").c_str()); + + // return *member; + //} + + //XmlOptionalObjectNavigator::XmlOptionalObjectNavigator(infra::XmlObject& object) + // : navigator(infra::inPlace, object) + //{} + + //XmlOptionalObjectNavigator::XmlOptionalObjectNavigator(const XmlNodeNavigator& navigator) + // : navigator(infra::inPlace, navigator) + //{} + + //XmlOptionalObjectNavigator XmlOptionalObjectNavigator::operator/(XmlNodeNavigatorToken token) const + //{ + // if (navigator != infra::none) + // return *navigator / token; + // else + // return {}; + //} + + //infra::Optional XmlOptionalObjectNavigator::operator/(XmlStringAttributeNavigatorToken token) const + //{ + // if (navigator != infra::none) + // return infra::MakeOptional(*navigator / token); + // else + // return {}; + //} + + //infra::Optional XmlOptionalObjectNavigator::operator/(XmlOptionalStringAttributeNavigatorToken token) const + //{ + // if (navigator != infra::none) + // return *navigator / token; + // else + // return {}; + //} + + //infra::Optional XmlOptionalObjectNavigator::operator/(XmlIntegerAttributeNavigatorToken token) const + //{ + // if (navigator != infra::none) + // return infra::MakeOptional(*navigator / token); + // else + // return {}; + //} + + //infra::Optional XmlOptionalObjectNavigator::operator/(XmlBoolNavigatorToken token) const + //{ + // if (navigator != infra::none) + // return infra::MakeOptional(*navigator / token); + // else + // return {}; + //} +} diff --git a/infra/xml/XmlNavigator.hpp b/infra/xml/XmlNavigator.hpp new file mode 100644 index 00000000..62f6d30c --- /dev/null +++ b/infra/xml/XmlNavigator.hpp @@ -0,0 +1,157 @@ +#ifndef XML_OBJECT_NAVIGATOR_HPP +#define XML_OBJECT_NAVIGATOR_HPP + +#include "pugixml.hpp" +#include "infra/util/Optional.hpp" +#include + +namespace infra +{ + class XmlNodeNavigator; + //class XmlOptionalObjectNavigator; + + struct XmlNodeNavigatorToken + { + std::string name; + }; + + struct XmlStringAttributeNavigatorToken + { + std::string name; + }; + + struct XmlOptionalStringAttributeNavigatorToken + { + std::string name; + }; + + struct XmlIntegerAttributeNavigatorToken + { + std::string name; + }; + + struct XmlOptionalIntegerAttributeNavigatorToken + { + std::string name; + }; + + template + struct XmlTransformObjectNavigatorToken + { + std::string name; + std::function transformation; + }; + + template + struct XmlTransformArrayNavigatorToken + { + std::string name; + std::function transformation; + }; + + //template + //struct XmlTransformOptionalObjectNavigatorToken + //{ + // std::string name; + // std::function transformation; + //}; + + class XmlNodeNavigator + { + public: + explicit XmlNodeNavigator(const std::string& contents); + XmlNodeNavigator(const pugi::xml_node& node); + + XmlNodeNavigator operator/(XmlNodeNavigatorToken token) const; + std::string operator/(XmlStringAttributeNavigatorToken token) const; + infra::Optional operator/(XmlOptionalStringAttributeNavigatorToken token) const; + int32_t operator/(XmlIntegerAttributeNavigatorToken token) const; + infra::Optional operator/(XmlOptionalIntegerAttributeNavigatorToken token) const; + + template + Result operator/(XmlTransformObjectNavigatorToken token) const; + // template + // infra::Optional operator/(XmlTransformOptionalObjectNavigatorToken token) const; + template + std::vector operator/(XmlTransformArrayNavigatorToken token) const; + + protected: + pugi::xml_document document; + pugi::xml_node node; + }; + + //class XmlOptionalObjectNavigator + //{ + //public: + // XmlOptionalObjectNavigator() = default; + // XmlOptionalObjectNavigator(infra::XmlObject& object); + // XmlOptionalObjectNavigator(const XmlNodeNavigator& navigator); + + // XmlOptionalObjectNavigator operator/(XmlNodeNavigatorToken token) const; + // infra::Optional operator/(XmlStringAttributeNavigatorToken token) const; + // infra::Optional operator/(XmlOptionalStringAttributeNavigatorToken token) const; + // infra::Optional operator/(XmlIntegerAttributeNavigatorToken token) const; + + // template + // infra::Optional operator/(XmlTransformObjectNavigatorToken token) const; + // template + // infra::Optional operator/(XmlTransformOptionalObjectNavigatorToken token) const; + + //protected: + // infra::Optional navigator; + //}; + + + //// Implementation //// + + template + Result XmlNodeNavigator::operator/(XmlTransformObjectNavigatorToken token) const + { + auto child = node.child(token.name.c_str()); + if (child == pugi::xml_node()) + throw std::runtime_error(("Child " + token.name + " not found").c_str()); + + return token.transformation(child); + } + + //template + //infra::Optional XmlNodeNavigator::operator/(XmlTransformOptionalObjectNavigatorToken token) const + //{ + // auto subObject = object.GetOptionalObject(token.name); + // if (subObject == infra::none) + // return {}; + + // return infra::MakeOptional(token.transformation(*subObject)); + //} + + template + std::vector XmlNodeNavigator::operator/(XmlTransformArrayNavigatorToken token) const + { + std::vector result; + + for (auto child: node.children(token.name.c_str())) + result.push_back(token.transformation(child)); + + return result; + } + + // template + //infra::Optional XmlOptionalObjectNavigator::operator/(XmlTransformObjectNavigatorToken token) const + //{ + // if (navigator != infra::none) + // return infra::MakeOptional(*navigator / token); + // else + // return {}; + //} + + //template + //infra::Optional XmlOptionalObjectNavigator::operator/(XmlTransformOptionalObjectNavigatorToken token) const + //{ + // if (navigator != infra::none) + // return *navigator / token; + // else + // return {}; + //} +} + +#endif diff --git a/infra/xml/test/CMakeLists.txt b/infra/xml/test/CMakeLists.txt new file mode 100644 index 00000000..5811208f --- /dev/null +++ b/infra/xml/test/CMakeLists.txt @@ -0,0 +1,12 @@ +add_executable(infra.xml_test) +emil_build_for(infra.xml_test BOOL HALST_BUILD_TESTS) +emil_add_test(infra.xml_test) + +target_link_libraries(infra.xml_test PUBLIC + gmock_main + infra.xml +) + +target_sources(infra.xml_test PRIVATE + TestXmlNavigator.cpp +) diff --git a/infra/xml/test/TestXmlNavigator.cpp b/infra/xml/test/TestXmlNavigator.cpp new file mode 100644 index 00000000..52b2f2a0 --- /dev/null +++ b/infra/xml/test/TestXmlNavigator.cpp @@ -0,0 +1,80 @@ +#include "infra/xml/XmlNavigator.hpp" +#include "gtest/gtest.h" + +namespace +{ + infra::XmlNodeNavigatorToken doc{ "doc" }; + infra::XmlNodeNavigatorToken node{ "node" }; + infra::XmlStringAttributeNavigatorToken str{ "str" }; + infra::XmlOptionalStringAttributeNavigatorToken optionalStr{ "str" }; + infra::XmlOptionalStringAttributeNavigatorToken optionalStr2{ "str2" }; + infra::XmlIntegerAttributeNavigatorToken integer{ "int" }; + infra::XmlOptionalIntegerAttributeNavigatorToken optionalInt{ "int" }; + infra::XmlOptionalIntegerAttributeNavigatorToken optionalInt2{ "int2" }; +} + +TEST(XmlNavigator, access_node) +{ + auto document = R"()"; + infra::XmlNodeNavigator navigator{ document }; + navigator / node; +} + +TEST(XmlNavigator, access_string_attribute) +{ + auto document = R"()"; + infra::XmlNodeNavigator navigator{ document }; + EXPECT_EQ("text", navigator / node / str); + EXPECT_EQ("text", *(navigator / node / optionalStr)); + EXPECT_EQ(infra::none, navigator / node / optionalStr2); +} + +TEST(XmlNavigator, access_integer_attribute) +{ + auto document = R"()"; + infra::XmlNodeNavigator navigator{ document }; + EXPECT_EQ(5, navigator / node / integer); + EXPECT_EQ(5, *(navigator / node / optionalInt)); + EXPECT_EQ(infra::none, navigator / node / optionalInt2); +} + +TEST(XmlNavigator, transform_object) +{ + struct Data + { + std::string str; + }; + + infra::XmlTransformObjectNavigatorToken node{ "node", [](const infra::XmlNodeNavigator& navigator) + { + Data result = { navigator / str }; + return result; + } }; + + auto document = R"()"; + infra::XmlNodeNavigator navigator{ document }; + EXPECT_EQ("text", (navigator / node).str); +} + +TEST(XmlNavigator, transform_array) +{ + struct Data + { + std::string str; + + bool operator==(const Data& other) const + { + return str == other.str; + } + }; + + infra::XmlTransformArrayNavigatorToken node{ "node", [](const infra::XmlNodeNavigator& navigator) + { + Data result = { navigator / str }; + return result; + } }; + + auto document = R"()"; + infra::XmlNodeNavigator navigator{ document }; + EXPECT_EQ((std::vector{ { "text1" }, { "text2" }, { "text3" } }), navigator / doc / node); +} diff --git a/st/CMakeLists.txt b/st/CMakeLists.txt index 42dfaba9..80b64190 100644 --- a/st/CMakeLists.txt +++ b/st/CMakeLists.txt @@ -27,7 +27,18 @@ target_compile_definitions(st.hal_driver_stm32g0xx PUBLIC USE_HAL_DRIVER=1 STM32G0=1 DEVICE_HEADER="stm32g0xx.h" + $<$:STM32G030xx=1> + $<$:STM32G031xx=1> + $<$:STM32G041xx=1> + $<$:STM32G050xx=1> + $<$:STM32G051xx=1> + $<$:STM32G061xx=1> $<$:STM32G070xx=1> + $<$:STM32G071xx=1> + $<$:STM32G081xx=1> + $<$:STM32G0B0xx=1> + $<$:STM32G0B1xx=1> + $<$:STM32G0C1xx=1> ) add_hal_driver(st.hal_driver_stm32g4xx STM32G4xx_HAL_Driver CMSIS_STM32G4xx) diff --git a/st/ldscripts/sections.ld b/st/ldscripts/sections.ld index ab4b1195..e7ec0bb9 100644 --- a/st/ldscripts/sections.ld +++ b/st/ldscripts/sections.ld @@ -22,6 +22,8 @@ SECTIONS KEEP(*(.isr_vector)) *(.after_vectors .after_vectors.*) + *(.text.Reset_Handler) + *(.text.Default_Handler) } >FLASH .inits : ALIGN(4) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 00000000..0a293e27 --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(st_table_generator) diff --git a/tools/st_table_generator/CMakeLists.txt b/tools/st_table_generator/CMakeLists.txt new file mode 100644 index 00000000..37f64b83 --- /dev/null +++ b/tools/st_table_generator/CMakeLists.txt @@ -0,0 +1,11 @@ +add_executable(tools.st_table_generator) +emil_build_for(tools.st_table_generator HOST All) + +target_sources(tools.st_table_generator PRIVATE Main.cpp) + +target_link_libraries(tools.st_table_generator PRIVATE + args + hal.generic + infra.syntax + infra.xml +) diff --git a/tools/st_table_generator/Main.cpp b/tools/st_table_generator/Main.cpp new file mode 100644 index 00000000..0832448b --- /dev/null +++ b/tools/st_table_generator/Main.cpp @@ -0,0 +1,216 @@ +#include "args.hxx" +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/plugin.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream_impl.h" +#include "google/protobuf/stubs/strutil.h" +#include "hal/generic/FileSystemGeneric.hpp" +#include "infra/xml/XmlNavigator.hpp" +#include "infra/syntax/CppFormatter.hpp" + +template +std::vector Compact(const std::vector>& v) +{ + std::vector result; + + for (auto& x : v) + if (x != infra::none) + result.push_back(*x); + + return result; +} + +struct PeripheralCandidate +{ + std::string name; + std::string type; + std::vector ipNames; + infra::Optional prefix; + infra::Optional base; +}; + +struct Peripheral +{ + std::string name; + int position; + infra::Optional clockEnable; + infra::Optional base; +}; + +struct PeripheralGroup +{ + std::string groupName; + std::vector peripherals; +}; + +class TableGenerator +{ +public: + TableGenerator(hal::FileSystem& fileSystem, const std::filesystem::path& inputPath, const std::vector& candidates); + + void Write(const std::filesystem::path& outputDirectory); + +private: + void ReadCandidates(const std::vector& candidates); + void ReadCandidate(const PeripheralCandidate& candidate); + + static std::string Concatenate(const std::vector& lines); + +private: + std::filesystem::path inputDirectory; + std::string input; + infra::XmlNodeNavigator navigator; + std::vector candidates; + std::vector peripheralGroups; +}; + +TableGenerator::TableGenerator(hal::FileSystem& fileSystem, const std::filesystem::path& inputPath, const std::vector& candidates) + : inputDirectory(inputPath.parent_path()) + , input(Concatenate(fileSystem.ReadFile(inputPath))) + , navigator(input) +{ + ReadCandidates(candidates); +} + +void TableGenerator::Write(const std::filesystem::path& outputDirectory) +{ + for (const auto& peripheralGroup : peripheralGroups) + { + std::cout << "Group: " << peripheralGroup.groupName << std::endl; + for (const auto& peripheral : peripheralGroup.peripherals) + { + std::cout << " Peripheral " << peripheral.name << " pos " << peripheral.position; + if (peripheral.clockEnable != infra::none) + std::cout << " Clock Enable: " << *peripheral.clockEnable; + std::cout << std::endl; + } + } + + std::unique_ptr stream = std::make_unique(&std::cout); + google::protobuf::io::Printer printer(stream.get(), '$', nullptr); + application::Entities formatter(true); + + auto includesByHeader = std::make_shared(); + includesByHeader->Path("infra/util/MemoryRange.hpp"); + includesByHeader->PathMacro("DEVICE_HEADER"); + formatter.Add(includesByHeader); + + auto includesBySource = std::make_shared(); + includesBySource->Path("generated/stm32fxxx/PeripheralTable.hpp"); + includesBySource->PathSystem(""); + includesBySource->PathSystem(""); + formatter.Add(includesBySource); + + auto halNamespace = std::make_shared("hal"); + + for (const auto& group : peripheralGroups) + { + if (group.peripherals.empty()) + { + + } + } + + std::cout << "============================" << std::endl; + formatter.PrintHeader(printer); + std::cout << "============================" << std::endl; + formatter.PrintSource(printer, ""); + std::cout << "============================" << std::endl; +} + +void TableGenerator::ReadCandidates(const std::vector& candidates) +{ + for (const auto& candidate : candidates) + ReadCandidate(candidate); +} + +void TableGenerator::ReadCandidate(const PeripheralCandidate& candidate) +{ + const infra::XmlNodeNavigatorToken mcu{ "Mcu" }; + const infra::XmlTransformArrayNavigatorToken> ip{ "IP", [this, &candidate](const infra::XmlNodeNavigator& navigator) + { + static const infra::XmlStringAttributeNavigatorToken name{ "Name" }; + static const infra::XmlStringAttributeNavigatorToken instance_name{ "InstanceName" }; + static const infra::XmlOptionalStringAttributeNavigatorToken clock_enable_mode{ "ClockEnableMode" }; + + auto ipName = navigator / name; + for (auto& candidateIpName : candidate.ipNames) + if (ipName == candidateIpName) + { + Peripheral result; + + result.name = navigator / instance_name; + + if (candidate.prefix != infra::none) + result.position = std::stoi(result.name.substr(candidate.prefix->size())); + else if (result.name == ipName) + result.position = 1; + else + result.position = std::stoi(result.name.substr(ipName.size())); + + auto clockEnable = navigator / clock_enable_mode; + if (clockEnable != infra::none) + result.clockEnable = clockEnable; + + result.base = candidate.base; + + return infra::MakeOptional(result); + } + + return infra::Optional(); + } }; + + peripheralGroups.push_back(PeripheralGroup{ candidate.name, Compact(navigator / mcu / ip) }); +} + +std::string TableGenerator::Concatenate(const std::vector& lines) +{ + std::string result; + + for (const auto& line : lines) + result += line; + + return result; +} + +int main(int argc, const char* argv[], const char* env[]) +{ + args::ArgumentParser parser("Generate tables for ST microcontrollers"); + args::Group positionals(parser, "Positional arguments:"); + args::Positional inputArgument(positionals, "input", "input xml file", args::Options::Required); + args::Positional directoryArgument(positionals, "directory", "directory for generated files", args::Options::Required); + args::HelpFlag help(parser, "help", "display this help menu.", { 'h', "help" }); + + try + { + parser.ParseCLI(argc, argv); + + hal::FileSystemGeneric fileSystem; + + std::vector candidates{ + PeripheralCandidate{ "Uart", "USART_TypeDef*", { "UART", "USART" }, infra::none }, + PeripheralCandidate{ "Spi", "SPI_TypeDef*", { "SPI" }, infra::none }, + PeripheralCandidate{ "Timer", "TIM_TypeDef*", { "TIM1_8", "TIM6_7", "TIM1_8F7", "TIM6_7F7", "TIM1_8F37", "TIM6_7F37", "TIM1_8F77", "TIM6_7F77" }, infra::MakeOptional("TIM") }, + PeripheralCandidate{ "Adc", "ADC_TypeDef*", { "ADC" }, infra::none }, + PeripheralCandidate{ "Rtc", "RTC_TypeDef*", { "RTC" }, infra::none }, + }; + + TableGenerator tableGenerator(fileSystem, std::filesystem::path(args::get(inputArgument)), candidates); + + const auto outputDirectory = args::get(directoryArgument); + tableGenerator.Write(outputDirectory); + } + catch (const args::Help&) + { + std::cout << parser; + return 1; + } + //catch (const std::exception& ex) + //{ + // std::cout << ex.what() << std::endl; + // return 1; + //} + + return 0; +} From 0b1b96df7ccd856b6eb67e7e6f8d9d2c862ee3b3 Mon Sep 17 00:00:00 2001 From: Richard Peters Date: Tue, 12 Sep 2023 08:53:36 +0200 Subject: [PATCH 2/5] Move infra/xml/XmlNavigator to amp-embedded-infralib --- CMakeLists.txt | 1 - infra/CMakeLists.txt | 1 - infra/xml/CMakeLists.txt | 29 ----- infra/xml/XmlNavigator.cpp | 121 ------------------ infra/xml/XmlNavigator.hpp | 157 ------------------------ infra/xml/test/CMakeLists.txt | 12 -- infra/xml/test/TestXmlNavigator.cpp | 80 ------------ tools/st_table_generator/CMakeLists.txt | 1 - tools/st_table_generator/Main.cpp | 2 +- 9 files changed, 1 insertion(+), 403 deletions(-) delete mode 100644 infra/CMakeLists.txt delete mode 100644 infra/xml/CMakeLists.txt delete mode 100644 infra/xml/XmlNavigator.cpp delete mode 100644 infra/xml/XmlNavigator.hpp delete mode 100644 infra/xml/test/CMakeLists.txt delete mode 100644 infra/xml/test/TestXmlNavigator.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 742d9500..189ec908 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,6 @@ else() set(HALST_EXCLUDE_FROM_ALL "EXCLUDE_FROM_ALL") endif() -add_subdirectory(infra) add_subdirectory(tools) add_subdirectory(st) add_subdirectory(hal_st) diff --git a/infra/CMakeLists.txt b/infra/CMakeLists.txt deleted file mode 100644 index 13df52af..00000000 --- a/infra/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(xml) diff --git a/infra/xml/CMakeLists.txt b/infra/xml/CMakeLists.txt deleted file mode 100644 index 3cb181b4..00000000 --- a/infra/xml/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -if (EMIL_HOST_BUILD) - FetchContent_Declare( - pugixml - GIT_REPOSITORY https://github.com/zeux/pugixml - GIT_TAG a0e064336317c9347a91224112af9933598714e9 # v1.13 - ) - - FetchContent_MakeAvailable(pugixml) -endif() - -add_library(infra.xml ${HALST_EXCLUDE_FROM_ALL} STATIC) - -target_include_directories(infra.xml PUBLIC - "$" -) - -target_link_libraries(infra.xml PUBLIC - infra.stream - pugixml -) - -if (EMIL_HOST_BUILD) - target_sources(infra.xml PRIVATE - XmlNavigator.cpp - XmlNavigator.hpp - ) -endif() - -add_subdirectory(test) diff --git a/infra/xml/XmlNavigator.cpp b/infra/xml/XmlNavigator.cpp deleted file mode 100644 index ee001c44..00000000 --- a/infra/xml/XmlNavigator.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include "infra/xml/XmlNavigator.hpp" -#include - -namespace infra -{ - XmlNodeNavigator::XmlNodeNavigator(const std::string& contents) - { - document = pugi::xml_document(); - pugi::xml_parse_result result = document.load_string(contents.c_str()); - if (!result) - throw std::runtime_error("Document failed to load"); - - node = document; - } - - XmlNodeNavigator::XmlNodeNavigator(const pugi::xml_node& node) - : node(node) - {} - - XmlNodeNavigator XmlNodeNavigator::operator/(XmlNodeNavigatorToken token) const - { - auto child = node.child(token.name.c_str()); - if (child == pugi::xml_node()) - throw std::runtime_error(("Child " + token.name + " not found").c_str()); - - return { child }; - } - - std::string XmlNodeNavigator::operator/(XmlStringAttributeNavigatorToken token) const - { - for (auto attribute: node.attributes()) - if (attribute.name() == token.name) - return attribute.value(); - - throw std::runtime_error(("Attribute " + token.name + " not found").c_str()); - } - - infra::Optional XmlNodeNavigator::operator/(XmlOptionalStringAttributeNavigatorToken token) const - { - for (auto attribute = node.attributes_begin(); attribute != node.attributes_end(); attribute = ++attribute) - if (attribute->name() == token.name) - return infra::MakeOptional(std::string(attribute->value())); - - return infra::none; - } - - int32_t XmlNodeNavigator::operator/(XmlIntegerAttributeNavigatorToken token) const - { - for (auto attribute: node.attributes()) - if (attribute.name() == token.name) - return attribute.as_int(); - - throw std::runtime_error(("Attribute " + token.name + " not found").c_str()); - } - - infra::Optional XmlNodeNavigator::operator/(XmlOptionalIntegerAttributeNavigatorToken token) const - { - for (auto attribute: node.attributes()) - if (attribute.name() == token.name) - return infra::MakeOptional(attribute.as_int()); - - return infra::none; - } - - // bool XmlNodeNavigator::operator/(XmlBoolNavigatorToken token) const - //{ - // auto member = object.GetOptionalBoolean(token.name); - // if (member == infra::none) - // throw std::runtime_error(("Boolean " + token.name + " not found").c_str()); - - // return *member; - //} - - //XmlOptionalObjectNavigator::XmlOptionalObjectNavigator(infra::XmlObject& object) - // : navigator(infra::inPlace, object) - //{} - - //XmlOptionalObjectNavigator::XmlOptionalObjectNavigator(const XmlNodeNavigator& navigator) - // : navigator(infra::inPlace, navigator) - //{} - - //XmlOptionalObjectNavigator XmlOptionalObjectNavigator::operator/(XmlNodeNavigatorToken token) const - //{ - // if (navigator != infra::none) - // return *navigator / token; - // else - // return {}; - //} - - //infra::Optional XmlOptionalObjectNavigator::operator/(XmlStringAttributeNavigatorToken token) const - //{ - // if (navigator != infra::none) - // return infra::MakeOptional(*navigator / token); - // else - // return {}; - //} - - //infra::Optional XmlOptionalObjectNavigator::operator/(XmlOptionalStringAttributeNavigatorToken token) const - //{ - // if (navigator != infra::none) - // return *navigator / token; - // else - // return {}; - //} - - //infra::Optional XmlOptionalObjectNavigator::operator/(XmlIntegerAttributeNavigatorToken token) const - //{ - // if (navigator != infra::none) - // return infra::MakeOptional(*navigator / token); - // else - // return {}; - //} - - //infra::Optional XmlOptionalObjectNavigator::operator/(XmlBoolNavigatorToken token) const - //{ - // if (navigator != infra::none) - // return infra::MakeOptional(*navigator / token); - // else - // return {}; - //} -} diff --git a/infra/xml/XmlNavigator.hpp b/infra/xml/XmlNavigator.hpp deleted file mode 100644 index 62f6d30c..00000000 --- a/infra/xml/XmlNavigator.hpp +++ /dev/null @@ -1,157 +0,0 @@ -#ifndef XML_OBJECT_NAVIGATOR_HPP -#define XML_OBJECT_NAVIGATOR_HPP - -#include "pugixml.hpp" -#include "infra/util/Optional.hpp" -#include - -namespace infra -{ - class XmlNodeNavigator; - //class XmlOptionalObjectNavigator; - - struct XmlNodeNavigatorToken - { - std::string name; - }; - - struct XmlStringAttributeNavigatorToken - { - std::string name; - }; - - struct XmlOptionalStringAttributeNavigatorToken - { - std::string name; - }; - - struct XmlIntegerAttributeNavigatorToken - { - std::string name; - }; - - struct XmlOptionalIntegerAttributeNavigatorToken - { - std::string name; - }; - - template - struct XmlTransformObjectNavigatorToken - { - std::string name; - std::function transformation; - }; - - template - struct XmlTransformArrayNavigatorToken - { - std::string name; - std::function transformation; - }; - - //template - //struct XmlTransformOptionalObjectNavigatorToken - //{ - // std::string name; - // std::function transformation; - //}; - - class XmlNodeNavigator - { - public: - explicit XmlNodeNavigator(const std::string& contents); - XmlNodeNavigator(const pugi::xml_node& node); - - XmlNodeNavigator operator/(XmlNodeNavigatorToken token) const; - std::string operator/(XmlStringAttributeNavigatorToken token) const; - infra::Optional operator/(XmlOptionalStringAttributeNavigatorToken token) const; - int32_t operator/(XmlIntegerAttributeNavigatorToken token) const; - infra::Optional operator/(XmlOptionalIntegerAttributeNavigatorToken token) const; - - template - Result operator/(XmlTransformObjectNavigatorToken token) const; - // template - // infra::Optional operator/(XmlTransformOptionalObjectNavigatorToken token) const; - template - std::vector operator/(XmlTransformArrayNavigatorToken token) const; - - protected: - pugi::xml_document document; - pugi::xml_node node; - }; - - //class XmlOptionalObjectNavigator - //{ - //public: - // XmlOptionalObjectNavigator() = default; - // XmlOptionalObjectNavigator(infra::XmlObject& object); - // XmlOptionalObjectNavigator(const XmlNodeNavigator& navigator); - - // XmlOptionalObjectNavigator operator/(XmlNodeNavigatorToken token) const; - // infra::Optional operator/(XmlStringAttributeNavigatorToken token) const; - // infra::Optional operator/(XmlOptionalStringAttributeNavigatorToken token) const; - // infra::Optional operator/(XmlIntegerAttributeNavigatorToken token) const; - - // template - // infra::Optional operator/(XmlTransformObjectNavigatorToken token) const; - // template - // infra::Optional operator/(XmlTransformOptionalObjectNavigatorToken token) const; - - //protected: - // infra::Optional navigator; - //}; - - - //// Implementation //// - - template - Result XmlNodeNavigator::operator/(XmlTransformObjectNavigatorToken token) const - { - auto child = node.child(token.name.c_str()); - if (child == pugi::xml_node()) - throw std::runtime_error(("Child " + token.name + " not found").c_str()); - - return token.transformation(child); - } - - //template - //infra::Optional XmlNodeNavigator::operator/(XmlTransformOptionalObjectNavigatorToken token) const - //{ - // auto subObject = object.GetOptionalObject(token.name); - // if (subObject == infra::none) - // return {}; - - // return infra::MakeOptional(token.transformation(*subObject)); - //} - - template - std::vector XmlNodeNavigator::operator/(XmlTransformArrayNavigatorToken token) const - { - std::vector result; - - for (auto child: node.children(token.name.c_str())) - result.push_back(token.transformation(child)); - - return result; - } - - // template - //infra::Optional XmlOptionalObjectNavigator::operator/(XmlTransformObjectNavigatorToken token) const - //{ - // if (navigator != infra::none) - // return infra::MakeOptional(*navigator / token); - // else - // return {}; - //} - - //template - //infra::Optional XmlOptionalObjectNavigator::operator/(XmlTransformOptionalObjectNavigatorToken token) const - //{ - // if (navigator != infra::none) - // return *navigator / token; - // else - // return {}; - //} -} - -#endif diff --git a/infra/xml/test/CMakeLists.txt b/infra/xml/test/CMakeLists.txt deleted file mode 100644 index 5811208f..00000000 --- a/infra/xml/test/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -add_executable(infra.xml_test) -emil_build_for(infra.xml_test BOOL HALST_BUILD_TESTS) -emil_add_test(infra.xml_test) - -target_link_libraries(infra.xml_test PUBLIC - gmock_main - infra.xml -) - -target_sources(infra.xml_test PRIVATE - TestXmlNavigator.cpp -) diff --git a/infra/xml/test/TestXmlNavigator.cpp b/infra/xml/test/TestXmlNavigator.cpp deleted file mode 100644 index 52b2f2a0..00000000 --- a/infra/xml/test/TestXmlNavigator.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "infra/xml/XmlNavigator.hpp" -#include "gtest/gtest.h" - -namespace -{ - infra::XmlNodeNavigatorToken doc{ "doc" }; - infra::XmlNodeNavigatorToken node{ "node" }; - infra::XmlStringAttributeNavigatorToken str{ "str" }; - infra::XmlOptionalStringAttributeNavigatorToken optionalStr{ "str" }; - infra::XmlOptionalStringAttributeNavigatorToken optionalStr2{ "str2" }; - infra::XmlIntegerAttributeNavigatorToken integer{ "int" }; - infra::XmlOptionalIntegerAttributeNavigatorToken optionalInt{ "int" }; - infra::XmlOptionalIntegerAttributeNavigatorToken optionalInt2{ "int2" }; -} - -TEST(XmlNavigator, access_node) -{ - auto document = R"()"; - infra::XmlNodeNavigator navigator{ document }; - navigator / node; -} - -TEST(XmlNavigator, access_string_attribute) -{ - auto document = R"()"; - infra::XmlNodeNavigator navigator{ document }; - EXPECT_EQ("text", navigator / node / str); - EXPECT_EQ("text", *(navigator / node / optionalStr)); - EXPECT_EQ(infra::none, navigator / node / optionalStr2); -} - -TEST(XmlNavigator, access_integer_attribute) -{ - auto document = R"()"; - infra::XmlNodeNavigator navigator{ document }; - EXPECT_EQ(5, navigator / node / integer); - EXPECT_EQ(5, *(navigator / node / optionalInt)); - EXPECT_EQ(infra::none, navigator / node / optionalInt2); -} - -TEST(XmlNavigator, transform_object) -{ - struct Data - { - std::string str; - }; - - infra::XmlTransformObjectNavigatorToken node{ "node", [](const infra::XmlNodeNavigator& navigator) - { - Data result = { navigator / str }; - return result; - } }; - - auto document = R"()"; - infra::XmlNodeNavigator navigator{ document }; - EXPECT_EQ("text", (navigator / node).str); -} - -TEST(XmlNavigator, transform_array) -{ - struct Data - { - std::string str; - - bool operator==(const Data& other) const - { - return str == other.str; - } - }; - - infra::XmlTransformArrayNavigatorToken node{ "node", [](const infra::XmlNodeNavigator& navigator) - { - Data result = { navigator / str }; - return result; - } }; - - auto document = R"()"; - infra::XmlNodeNavigator navigator{ document }; - EXPECT_EQ((std::vector{ { "text1" }, { "text2" }, { "text3" } }), navigator / doc / node); -} diff --git a/tools/st_table_generator/CMakeLists.txt b/tools/st_table_generator/CMakeLists.txt index 37f64b83..361484b0 100644 --- a/tools/st_table_generator/CMakeLists.txt +++ b/tools/st_table_generator/CMakeLists.txt @@ -7,5 +7,4 @@ target_link_libraries(tools.st_table_generator PRIVATE args hal.generic infra.syntax - infra.xml ) diff --git a/tools/st_table_generator/Main.cpp b/tools/st_table_generator/Main.cpp index 0832448b..f9396c3c 100644 --- a/tools/st_table_generator/Main.cpp +++ b/tools/st_table_generator/Main.cpp @@ -6,8 +6,8 @@ #include "google/protobuf/io/zero_copy_stream_impl.h" #include "google/protobuf/stubs/strutil.h" #include "hal/generic/FileSystemGeneric.hpp" -#include "infra/xml/XmlNavigator.hpp" #include "infra/syntax/CppFormatter.hpp" +#include "infra/syntax/XmlNavigator.hpp" template std::vector Compact(const std::vector>& v) From 3445893ad59e9a33a4383c4f97809583d3d3b9cb Mon Sep 17 00:00:00 2001 From: Richard Peters Date: Wed, 11 Oct 2023 07:45:24 +0200 Subject: [PATCH 3/5] tools/st_table_generator/Main: small steps --- tools/st_table_generator/Main.cpp | 32 +++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/tools/st_table_generator/Main.cpp b/tools/st_table_generator/Main.cpp index f9396c3c..0f692aef 100644 --- a/tools/st_table_generator/Main.cpp +++ b/tools/st_table_generator/Main.cpp @@ -41,6 +41,7 @@ struct Peripheral struct PeripheralGroup { std::string groupName; + std::string type; std::vector peripherals; }; @@ -73,6 +74,13 @@ TableGenerator::TableGenerator(hal::FileSystem& fileSystem, const std::filesyste ReadCandidates(candidates); } +std::string ToUpper(const std::string& s) +{ + std::string result(s.size(), ' '); + std::transform(s.begin(), s.end(), result.begin(), ::toupper); + return result; +} + void TableGenerator::Write(const std::filesystem::path& outputDirectory) { for (const auto& peripheralGroup : peripheralGroups) @@ -89,7 +97,7 @@ void TableGenerator::Write(const std::filesystem::path& outputDirectory) std::unique_ptr stream = std::make_unique(&std::cout); google::protobuf::io::Printer printer(stream.get(), '$', nullptr); - application::Entities formatter(true); + application::IncludeGuard formatter("include_guard_hpp"); auto includesByHeader = std::make_shared(); includesByHeader->Path("infra/util/MemoryRange.hpp"); @@ -98,25 +106,33 @@ void TableGenerator::Write(const std::filesystem::path& outputDirectory) auto includesBySource = std::make_shared(); includesBySource->Path("generated/stm32fxxx/PeripheralTable.hpp"); - includesBySource->PathSystem(""); - includesBySource->PathSystem(""); + includesBySource->PathSystem("array"); + includesBySource->PathSystem("cstdlib"); formatter.Add(includesBySource); auto halNamespace = std::make_shared("hal"); + formatter.Add(halNamespace); for (const auto& group : peripheralGroups) { + auto definitionName = "HAS_PERIPHERAL_" + ToUpper(group.groupName); + auto variableName = "peripheral" + group.groupName; + if (group.peripherals.empty()) + halNamespace->Add(std::make_shared(definitionName)); + else { - + halNamespace->Add(std::make_shared(definitionName)); + halNamespace->Add(std::make_shared(variableName + "Array", "constexpr std::array", "{{ }}")); + halNamespace->Add(std::make_shared(variableName, "const infra::MemoryRange<" + group.type + "* const>", "infra::ReinterpretCastMemoryRange<" + group.type + "* const>(infra::MakeRange(" + variableName + "Array)")); } } - std::cout << "============================" << std::endl; + printer.Print("============================"); formatter.PrintHeader(printer); - std::cout << "============================" << std::endl; + printer.Print("============================"); formatter.PrintSource(printer, ""); - std::cout << "============================" << std::endl; + printer.Print("============================"); } void TableGenerator::ReadCandidates(const std::vector& candidates) @@ -161,7 +177,7 @@ void TableGenerator::ReadCandidate(const PeripheralCandidate& candidate) return infra::Optional(); } }; - peripheralGroups.push_back(PeripheralGroup{ candidate.name, Compact(navigator / mcu / ip) }); + peripheralGroups.push_back(PeripheralGroup{ candidate.name, candidate.type, Compact(navigator / mcu / ip) }); } std::string TableGenerator::Concatenate(const std::vector& lines) From 63281485e8fa8433c83765d1369e84406e946f9e Mon Sep 17 00:00:00 2001 From: Richard Peters Date: Mon, 20 Nov 2023 15:13:19 +0100 Subject: [PATCH 4/5] Generate arrays and functions --- tools/st_table_generator/CMakeLists.txt | 1 + tools/st_table_generator/Main.cpp | 112 +++++++++++++++++++++--- 2 files changed, 100 insertions(+), 13 deletions(-) diff --git a/tools/st_table_generator/CMakeLists.txt b/tools/st_table_generator/CMakeLists.txt index 361484b0..599117df 100644 --- a/tools/st_table_generator/CMakeLists.txt +++ b/tools/st_table_generator/CMakeLists.txt @@ -1,5 +1,6 @@ add_executable(tools.st_table_generator) emil_build_for(tools.st_table_generator HOST All) +emil_install(tools.st_table_generator EXPORT halstTargets DESTINATION bin) target_sources(tools.st_table_generator PRIVATE Main.cpp) diff --git a/tools/st_table_generator/Main.cpp b/tools/st_table_generator/Main.cpp index 0f692aef..b3de85da 100644 --- a/tools/st_table_generator/Main.cpp +++ b/tools/st_table_generator/Main.cpp @@ -8,6 +8,9 @@ #include "hal/generic/FileSystemGeneric.hpp" #include "infra/syntax/CppFormatter.hpp" #include "infra/syntax/XmlNavigator.hpp" +#include +#include +#include template std::vector Compact(const std::vector>& v) @@ -56,6 +59,12 @@ class TableGenerator void ReadCandidates(const std::vector& candidates); void ReadCandidate(const PeripheralCandidate& candidate); + std::string MakeArrayType(const std::string& type, int size) const; + std::string PeripheralInitializer(const std::vector& peripherals) const; + std::string IrqInitializer(const std::vector& peripherals) const; + std::string EnableClockBody(const std::vector& peripherals) const; + std::string DisableClockBody(const std::vector& peripherals) const; + static std::string Concatenate(const std::vector& lines); private: @@ -95,8 +104,6 @@ void TableGenerator::Write(const std::filesystem::path& outputDirectory) } } - std::unique_ptr stream = std::make_unique(&std::cout); - google::protobuf::io::Printer printer(stream.get(), '$', nullptr); application::IncludeGuard formatter("include_guard_hpp"); auto includesByHeader = std::make_shared(); @@ -123,16 +130,28 @@ void TableGenerator::Write(const std::filesystem::path& outputDirectory) else { halNamespace->Add(std::make_shared(definitionName)); - halNamespace->Add(std::make_shared(variableName + "Array", "constexpr std::array", "{{ }}")); + halNamespace->Add(std::make_shared(variableName + "Array", MakeArrayType("unsigned_int", group.peripherals.size()), PeripheralInitializer(group.peripherals))); halNamespace->Add(std::make_shared(variableName, "const infra::MemoryRange<" + group.type + "* const>", "infra::ReinterpretCastMemoryRange<" + group.type + "* const>(infra::MakeRange(" + variableName + "Array)")); + halNamespace->Add(std::make_shared(variableName + "IrqArray", MakeArrayType("IRQn_Type const", group.peripherals.size()), IrqInitializer(group.peripherals))); + halNamespace->Add(std::make_shared(variableName + "Irq", "const infra::MemoryRange", "infra::MakeRange(" + variableName + "IrqArray")); + auto EnableClock = std::make_shared("EnableClock" + group.groupName, EnableClockBody(group.peripherals), "void", 0); + EnableClock->Parameter("std::size_t index"); + halNamespace->Add(EnableClock); + auto DisableClock = std::make_shared("DisableClock" + group.groupName, DisableClockBody(group.peripherals), "void", 0); + DisableClock->Parameter("std::size_t index"); + halNamespace->Add(DisableClock); } } - printer.Print("============================"); - formatter.PrintHeader(printer); - printer.Print("============================"); - formatter.PrintSource(printer, ""); - printer.Print("============================"); + std::ofstream header(outputDirectory / "PeripheralTable.chpp"); + std::unique_ptr headerStream = std::make_unique(&header); + google::protobuf::io::Printer headerPrinter(headerStream.get(), '$', nullptr); + formatter.PrintHeader(headerPrinter); + + std::ofstream source(outputDirectory / "PeripheralTable.cpp"); + std::unique_ptr sourceStream = std::make_unique(&source); + google::protobuf::io::Printer sourcePrinter(sourceStream.get(), '$', nullptr); + formatter.PrintSource(sourcePrinter, ""); } void TableGenerator::ReadCandidates(const std::vector& candidates) @@ -180,6 +199,73 @@ void TableGenerator::ReadCandidate(const PeripheralCandidate& candidate) peripheralGroups.push_back(PeripheralGroup{ candidate.name, candidate.type, Compact(navigator / mcu / ip) }); } +std::string TableGenerator::MakeArrayType(const std::string& type, int size) const +{ + std::ostringstream stream; + + stream << "constexpr std::array<" << type << ", " << size << ">"; + + return stream.str(); +} + +std::string TableGenerator::PeripheralInitializer(const std::vector& peripherals) const +{ + std::ostringstream stream; + + stream << "\n {{\n"; + for (auto& p : peripherals) + stream << " " << p.name << ",\n"; + stream << " }}"; + + return stream.str(); +} + +std::string TableGenerator::IrqInitializer(const std::vector& peripherals) const +{ + std::ostringstream stream; + + stream << "\n {{\n"; + for (auto& p : peripherals) + stream << " " << p.name << "_IRQn,\n"; + stream << " }}"; + + return stream.str(); +} + +std::string TableGenerator::EnableClockBody(const std::vector& peripherals) const +{ + std::ostringstream stream; + + stream << "switch (index)\n{\n"; + + for (auto& p : peripherals) + if (p.clockEnable) + stream << " case " << std::distance(peripherals.data(), &p) << ": " << *p.clockEnable << "(); break;\n"; + else + stream << " case " << std::distance(peripherals.data(), &p) << ": __HAL_RCC_" << p.name << "_CLK_ENABLE(); break;\n"; + + stream << " default:\n std::abort();\n}"; + + return stream.str(); +} + +std::string TableGenerator::DisableClockBody(const std::vector& peripherals) const +{ + std::ostringstream stream; + + stream << "switch (index)\n{\n"; + + for (auto& p : peripherals) + if (p.clockEnable) + stream << " case " << std::distance(peripherals.data(), &p) << ": " << p.clockEnable->substr(0, p.clockEnable->size() - 6) << "DISABLE(); break;\n"; + else + stream << " case " << std::distance(peripherals.data(), &p) << ": __HAL_RCC_" << p.name << "_CLK_DISABLE(); break;\n"; + + stream << " default:\n std::abort();\n}"; + + return stream.str(); +} + std::string TableGenerator::Concatenate(const std::vector& lines) { std::string result; @@ -222,11 +308,11 @@ int main(int argc, const char* argv[], const char* env[]) std::cout << parser; return 1; } - //catch (const std::exception& ex) - //{ - // std::cout << ex.what() << std::endl; - // return 1; - //} + catch (const std::exception& ex) + { + std::cout << ex.what() << std::endl; + return 1; + } return 0; } From 600edce221316ba9f90db3e81da99bf643c8fa81 Mon Sep 17 00:00:00 2001 From: Richard Peters Date: Thu, 23 Nov 2023 11:30:29 +0100 Subject: [PATCH 5/5] Use table generator in hal_st.stm32fxxx --- .github/workflows/release-please.yml | 27 +++++++++ CMakeLists.txt | 28 +++++++++ cmake/Config.cmake.in | 5 ++ hal_st/stm32fxxx/CMakeLists.txt | 12 ++-- hal_st/stm32fxxx/table_generator.cmake | 75 +++++++++++++++++++++++++ tools/st_table_generator/CMakeLists.txt | 19 ++++--- tools/st_table_generator/Main.cpp | 71 +++++++++++++++++------ 7 files changed, 204 insertions(+), 33 deletions(-) create mode 100644 cmake/Config.cmake.in create mode 100644 hal_st/stm32fxxx/table_generator.cmake diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index c1fa02e0..9a14f0fa 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -33,3 +33,30 @@ jobs: command: manifest #token: ${{ steps.token.outputs.token }} token: ${{ secrets.AUTOMATIC_RELEASE_TOKEN }} + build_upload_packages: + name: Build & Upload Packages + needs: release_please + if: ${{ needs.release_please.outputs.releases_created }} + permissions: + contents: write + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + persist-credentials: false + - uses: hendrikmuhs/ccache-action@6d1841ec156c39a52b1b23a810da917ab98da1f4 # v1.2.10 + with: + key: ${{ github.job }}-${{ matrix.os }} + variant: sccache + - uses: lukka/run-cmake@2ce8982be71b8e9a3c4d5e432135035afd1e76a7 # v10.7 + with: + configurePreset: "host-single-MinSizeRel" + buildPreset: "release-package" + configurePresetAdditionalArgs: "['-DCMAKE_C_COMPILER_LAUNCHER=sccache', '-DCMAKE_CXX_COMPILER_LAUNCHER=sccache']" + - run: gh release upload ${{ needs.release_please.outputs.tag_name }} build/**/hal_st-*.zip --clobber + shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CMakeLists.txt b/CMakeLists.txt index dec80dd7..f8dab87c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,6 @@ cmake_minimum_required(VERSION 3.24) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") +list(APPEND CMAKE_PREFIX_PATH "${CMAKE_INSTALL_PREFIX}") if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) set(HALST_STANDALONE On) @@ -54,6 +56,32 @@ if (HALST_STANDALONE) emil_folderize_all_targets() endif() +if (EMIL_HOST_BUILD) + install(EXPORT halstTargets + FILE hal_stTargets.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/hal_st + ) + + write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake" + COMPATIBILITY SameMajorVersion + # When cross-compiling for a 32-bit architecture and re-using host tooling from a 64-bit architecture + # ARCH_INDEPENDENT is necessary here. See: https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html. + ARCH_INDEPENDENT + ) + + configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Config.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + ) + + install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + ) +endif() + set(CPACK_GENERATOR "ZIP;TGZ") set(CPACK_SOURCE_IGNORE_FILES ".vs/;.git/;build/") set(CPACK_PACKAGE_NAME "${PROJECT_NAME}") diff --git a/cmake/Config.cmake.in b/cmake/Config.cmake.in new file mode 100644 index 00000000..3394a994 --- /dev/null +++ b/cmake/Config.cmake.in @@ -0,0 +1,5 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/hal_stTargets.cmake") + +check_required_components(TableGenerator) diff --git a/hal_st/stm32fxxx/CMakeLists.txt b/hal_st/stm32fxxx/CMakeLists.txt index 2f53984f..304eb585 100644 --- a/hal_st/stm32fxxx/CMakeLists.txt +++ b/hal_st/stm32fxxx/CMakeLists.txt @@ -1,3 +1,5 @@ +include(table_generator.cmake) + add_library(hal_st.stm32fxxx STATIC) emil_build_for(hal_st.stm32fxxx TARGET_MCU_VENDOR st PREREQUISITE_BOOL HALST_STANDALONE) @@ -123,17 +125,11 @@ if (TARGET_MCU_VENDOR STREQUAL st) generate_xslt(hal_st.stm32fxxx generated/stm32fxxx/PinoutTableDefault.cpp GeneratePinoutTableCpp.xsl "${CMAKE_CURRENT_BINARY_DIR}/generated/stm32fxxx/PinoutTableDefaultStructure.xml") generate_xslt(hal_st.stm32fxxx generated/stm32fxxx/PinoutTableDefault.hpp GeneratePinoutTableHpp.xsl "${CMAKE_CURRENT_BINARY_DIR}/generated/stm32fxxx/PinoutTableDefaultStructure.xml") - generate_xslt(hal_st.stm32fxxx generated/stm32fxxx/PeripheralTableStructure.xml GeneratePeripheralTableStructure.xsl $,PeripheralTableWbxx.xml,$,PeripheralTableG0xx.xml,PeripheralTableFxxx.xml>> - --stringparam mcu-document ${mcu_xml}) - generate_xslt(hal_st.stm32fxxx generated/stm32fxxx/PeripheralTable.cpp GeneratePeripheralTableCpp.xsl "${CMAKE_CURRENT_BINARY_DIR}/generated/stm32fxxx/PeripheralTableStructure.xml") - generate_xslt(hal_st.stm32fxxx generated/stm32fxxx/PeripheralTable.hpp GeneratePeripheralTableHpp.xsl "${CMAKE_CURRENT_BINARY_DIR}/generated/stm32fxxx/PeripheralTableStructure.xml") - target_sources(hal_st.stm32fxxx PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/generated/stm32fxxx/PinoutTableDefaultStructure.xml" "${CMAKE_CURRENT_BINARY_DIR}/generated/stm32fxxx/PinoutTableDefault.cpp" "${CMAKE_CURRENT_BINARY_DIR}/generated/stm32fxxx/PinoutTableDefault.hpp" - "${CMAKE_CURRENT_BINARY_DIR}/generated/stm32fxxx/PeripheralTableStructure.xml" - "${CMAKE_CURRENT_BINARY_DIR}/generated/stm32fxxx/PeripheralTable.cpp" - "${CMAKE_CURRENT_BINARY_DIR}/generated/stm32fxxx/PeripheralTable.hpp" ) + + st_table_generator(hal_st.stm32fxxx ${mcu_xml}) endif() diff --git a/hal_st/stm32fxxx/table_generator.cmake b/hal_st/stm32fxxx/table_generator.cmake new file mode 100644 index 00000000..c79a3928 --- /dev/null +++ b/hal_st/stm32fxxx/table_generator.cmake @@ -0,0 +1,75 @@ +function(hal_st_fetch_table_generator) + # This function will first try to use `find_package` to import + # amp-hal-st table generators. If there is an installed version + # of amp-hal-st present those table generators will be used. + # Otherwise the latest hal-st release will be downloaded and those + # table generators will be used instead. + # + # (See: https://cmake.org/cmake/help/latest/module/FetchContent.html#commands) + + if (EMIL_HOST_BUILD AND NOT CMAKE_CROSSCOMPILING) + # In a host build where we are not cross-compiling we use the built table generators + return() + endif() + + FetchContent_GetProperties(table_generator) + if (table_generator_POPULATED) + return() + endif() + + set(hal_st_version "2.1.0") # x-release-please-version + + if (CMAKE_HOST_WIN32) + set(os_postfix "win64") + set(host_executable_postfix ".exe") + elseif (CMAKE_HOST_APPLE) + set(os_postfix "Darwin") + elseif (CMAKE_HOST_UNIX) + set(os_postfix "Linux") + else() + message(FATAL_ERROR "No suitable table generators found for ${CMAKE_HOST_SYSTEM_NAME} (${CMAKE_HOST_SYSTEM_PROCESSOR})") + endif() + + FetchContent_Declare(table_generator + URL https://github.com/philips-software/amp-hal-st/releases/download/v${hal_st_version}/hal_st-${hal_st_version}-${os_postfix}.zip + FIND_PACKAGE_ARGS NAMES hal_st GLOBAL + ) + FetchContent_MakeAvailable(table_generator) + + if (NOT ${table_generators_FOUND}) + if (NOT TARGET tools.st_table_generator) + add_executable(tools.st_table_generator IMPORTED GLOBAL) + set_target_properties(tools.st_table_generator PROPERTIES + IMPORTED_LOCATION "${table_generators_SOURCE_DIR}/bin/tools.st_table_generator${host_executable_postfix}" + ) + endif() + else() + message(STATUS "Using table generator from installed location") + endif() +endfunction() + +function(st_table_generator target mcu_xml) + hal_st_fetch_table_generator() + + cmake_path(SET generated_dir_tables "generated/stm32fxxx") + cmake_path(ABSOLUTE_PATH generated_dir_tables BASE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} NORMALIZE OUTPUT_VARIABLE generated_dir_tables) + + set(generated_files "${generated_dir_tables}/PeripheralTable.cpp" "${generated_dir_tables}/PeripheralTable.hpp") + + add_custom_command( + OUTPUT ${generated_files} + COMMAND ${CMAKE_COMMAND} -E make_directory ${generated_dir_tables} + COMMAND tools.st_table_generator "${mcu_xml}" ${generated_dir_tables} + MAIN_DEPENDENCY "${mcu_xml}" + DEPENDS tools.st_table_generator + ) + + target_sources(${target} PRIVATE + ${generated_files} + ) + + target_include_directories(${target} PUBLIC + "$" + "$" + ) +endfunction() diff --git a/tools/st_table_generator/CMakeLists.txt b/tools/st_table_generator/CMakeLists.txt index 599117df..d19a4fca 100644 --- a/tools/st_table_generator/CMakeLists.txt +++ b/tools/st_table_generator/CMakeLists.txt @@ -1,11 +1,12 @@ -add_executable(tools.st_table_generator) -emil_build_for(tools.st_table_generator HOST All) -emil_install(tools.st_table_generator EXPORT halstTargets DESTINATION bin) +if (NOT CMAKE_CROSSCOMPILING) + add_executable(tools.st_table_generator) + install(TARGETS tools.st_table_generator EXPORT halstTargets DESTINATION bin) -target_sources(tools.st_table_generator PRIVATE Main.cpp) + target_sources(tools.st_table_generator PRIVATE Main.cpp) -target_link_libraries(tools.st_table_generator PRIVATE - args - hal.generic - infra.syntax -) + target_link_libraries(tools.st_table_generator PRIVATE + args + hal.generic + infra.syntax + ) +endif() diff --git a/tools/st_table_generator/Main.cpp b/tools/st_table_generator/Main.cpp index b3de85da..252466ce 100644 --- a/tools/st_table_generator/Main.cpp +++ b/tools/st_table_generator/Main.cpp @@ -28,6 +28,7 @@ struct PeripheralCandidate { std::string name; std::string type; + bool interrupt; std::vector ipNames; infra::Optional prefix; infra::Optional base; @@ -45,6 +46,7 @@ struct PeripheralGroup { std::string groupName; std::string type; + bool interrupt; std::vector peripherals; }; @@ -64,6 +66,8 @@ class TableGenerator std::string IrqInitializer(const std::vector& peripherals) const; std::string EnableClockBody(const std::vector& peripherals) const; std::string DisableClockBody(const std::vector& peripherals) const; + std::string ReplaceAll(std::string_view names, std::string_view from, std::string_view to) const; + std::string InvokeAll(std::string_view names) const; static std::string Concatenate(const std::vector& lines); @@ -130,10 +134,15 @@ void TableGenerator::Write(const std::filesystem::path& outputDirectory) else { halNamespace->Add(std::make_shared(definitionName)); - halNamespace->Add(std::make_shared(variableName + "Array", MakeArrayType("unsigned_int", group.peripherals.size()), PeripheralInitializer(group.peripherals))); - halNamespace->Add(std::make_shared(variableName, "const infra::MemoryRange<" + group.type + "* const>", "infra::ReinterpretCastMemoryRange<" + group.type + "* const>(infra::MakeRange(" + variableName + "Array)")); - halNamespace->Add(std::make_shared(variableName + "IrqArray", MakeArrayType("IRQn_Type const", group.peripherals.size()), IrqInitializer(group.peripherals))); - halNamespace->Add(std::make_shared(variableName + "Irq", "const infra::MemoryRange", "infra::MakeRange(" + variableName + "IrqArray")); + halNamespace->Add(std::make_shared(variableName + "Array", MakeArrayType("unsigned int", group.peripherals.size()), PeripheralInitializer(group.peripherals))); + halNamespace->Add(std::make_shared(variableName, "const infra::MemoryRange<" + group.type + " const>", "infra::ReinterpretCastMemoryRange<" + group.type + " const>(infra::MakeRange(" + variableName + "Array))")); + + if (group.interrupt) + { + halNamespace->Add(std::make_shared(variableName + "IrqArray", MakeArrayType("IRQn_Type const", group.peripherals.size()), IrqInitializer(group.peripherals))); + halNamespace->Add(std::make_shared(variableName + "Irq", "const infra::MemoryRange", "infra::MakeRange(" + variableName + "IrqArray)")); + } + auto EnableClock = std::make_shared("EnableClock" + group.groupName, EnableClockBody(group.peripherals), "void", 0); EnableClock->Parameter("std::size_t index"); halNamespace->Add(EnableClock); @@ -143,7 +152,7 @@ void TableGenerator::Write(const std::filesystem::path& outputDirectory) } } - std::ofstream header(outputDirectory / "PeripheralTable.chpp"); + std::ofstream header(outputDirectory / "PeripheralTable.hpp"); std::unique_ptr headerStream = std::make_unique(&header); google::protobuf::io::Printer headerPrinter(headerStream.get(), '$', nullptr); formatter.PrintHeader(headerPrinter); @@ -196,7 +205,7 @@ void TableGenerator::ReadCandidate(const PeripheralCandidate& candidate) return infra::Optional(); } }; - peripheralGroups.push_back(PeripheralGroup{ candidate.name, candidate.type, Compact(navigator / mcu / ip) }); + peripheralGroups.push_back(PeripheralGroup{ candidate.name, candidate.type, candidate.interrupt, Compact(navigator / mcu / ip) }); } std::string TableGenerator::MakeArrayType(const std::string& type, int size) const @@ -214,7 +223,7 @@ std::string TableGenerator::PeripheralInitializer(const std::vector& stream << "\n {{\n"; for (auto& p : peripherals) - stream << " " << p.name << ",\n"; + stream << " " << p.name << "_BASE,\n"; stream << " }}"; return stream.str(); @@ -240,11 +249,11 @@ std::string TableGenerator::EnableClockBody(const std::vector& perip for (auto& p : peripherals) if (p.clockEnable) - stream << " case " << std::distance(peripherals.data(), &p) << ": " << *p.clockEnable << "(); break;\n"; + stream << " case " << std::distance(peripherals.data(), &p) << ": " << InvokeAll(*p.clockEnable) << " break;\n"; else stream << " case " << std::distance(peripherals.data(), &p) << ": __HAL_RCC_" << p.name << "_CLK_ENABLE(); break;\n"; - stream << " default:\n std::abort();\n}"; + stream << " default:\n std::abort();\n}\n"; return stream.str(); } @@ -257,15 +266,45 @@ std::string TableGenerator::DisableClockBody(const std::vector& peri for (auto& p : peripherals) if (p.clockEnable) - stream << " case " << std::distance(peripherals.data(), &p) << ": " << p.clockEnable->substr(0, p.clockEnable->size() - 6) << "DISABLE(); break;\n"; + stream << " case " << std::distance(peripherals.data(), &p) << ": " << ReplaceAll(InvokeAll(*p.clockEnable), "ENABLE", "DISABLE") << " break;\n"; else stream << " case " << std::distance(peripherals.data(), &p) << ": __HAL_RCC_" << p.name << "_CLK_DISABLE(); break;\n"; - stream << " default:\n std::abort();\n}"; + stream << " default:\n std::abort();\n}\n"; return stream.str(); } +std::string TableGenerator::ReplaceAll(std::string_view names, std::string_view from, std::string_view to) const +{ + std::string result(names); + + for (auto pos = result.find(from); pos != std::string::npos; pos = result.find(from)) + result.replace(pos, from.size(), to); + + return result; +} + +std::string TableGenerator::InvokeAll(std::string_view names) const +{ + std::string result; + + while (true) + { + auto pos = names.find(';'); + + result.append(names.substr(0, pos)); + result.append("(); "); + + if (pos == std::string::npos) + break; + + names = names.substr(pos + 1); + } + + return result; +} + std::string TableGenerator::Concatenate(const std::vector& lines) { std::string result; @@ -291,11 +330,11 @@ int main(int argc, const char* argv[], const char* env[]) hal::FileSystemGeneric fileSystem; std::vector candidates{ - PeripheralCandidate{ "Uart", "USART_TypeDef*", { "UART", "USART" }, infra::none }, - PeripheralCandidate{ "Spi", "SPI_TypeDef*", { "SPI" }, infra::none }, - PeripheralCandidate{ "Timer", "TIM_TypeDef*", { "TIM1_8", "TIM6_7", "TIM1_8F7", "TIM6_7F7", "TIM1_8F37", "TIM6_7F37", "TIM1_8F77", "TIM6_7F77" }, infra::MakeOptional("TIM") }, - PeripheralCandidate{ "Adc", "ADC_TypeDef*", { "ADC" }, infra::none }, - PeripheralCandidate{ "Rtc", "RTC_TypeDef*", { "RTC" }, infra::none }, + PeripheralCandidate{ "Uart", "USART_TypeDef*", true, { "UART", "USART" }, infra::none }, + PeripheralCandidate{ "Spi", "SPI_TypeDef*", true, { "SPI" }, infra::none }, + PeripheralCandidate{ "Timer", "TIM_TypeDef*", true, { "TIM1_8", "TIM6_7", "TIM1_8F7", "TIM6_7F7", "TIM1_8F37", "TIM6_7F37", "TIM1_8F77", "TIM6_7F77" }, infra::MakeOptional("TIM") }, + PeripheralCandidate{ "Adc", "ADC_TypeDef*", true, { "ADC" }, infra::none }, + PeripheralCandidate{ "Rtc", "RTC_TypeDef*", false, { "RTC" }, infra::none }, }; TableGenerator tableGenerator(fileSystem, std::filesystem::path(args::get(inputArgument)), candidates);