diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 493b6553..6be426d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [windows-latest, windows-2019, macos-latest] + os: [windows-latest, macos-latest] steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: @@ -73,12 +73,21 @@ jobs: strategy: matrix: configuration: ["RelWithDebInfo"] - gcc: [ "10.3-2021.10" ] - target: ["stm32wb55", "stm32g070", "stm32g431", "stm32f407", "stm32f429", "stm32f746", "stm32f767", "stm32wba52", "stm32h563", "stm32h573"] + gcc: ["10.3-2021.10"] + target: + [ + "stm32wb55", + "stm32wba52", + "stm32g070", + "stm32g431", + "stm32f407", + "stm32f429", + "stm32f746", + "stm32f767", + "stm32h563", + "stm32h573" + ] include: - - gcc: "7-2018-q2" - configuration: "RelWithDebInfo" - target: "stm32f767" - gcc: "8-2019-q3" configuration: "RelWithDebInfo" target: "stm32f767" @@ -87,6 +96,8 @@ jobs: target: "stm32f767" steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + persist-credentials: false - name: Install GNU Arm Embedded Toolchain ${{ matrix.gcc }} uses: carlosperate/arm-none-eabi-gcc-action@0cc83a7330501be1848887e2966aaceb49a4bb12 # v1.9.1 with: diff --git a/CMakeLists.txt b/CMakeLists.txt index ace11bb9..1110b428 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ endif() project(hal_st LANGUAGES C CXX ASM VERSION 3.0.0) # x-release-please-version -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED On) set_directory_properties(PROPERTY USE_FOLDERS ON) @@ -40,10 +40,25 @@ else() set(HALST_EXCLUDE_FROM_ALL "EXCLUDE_FROM_ALL") endif() +if (EMIL_HOST_BUILD) + include(FetchContent) + + FetchContent_Declare( + cucumber-cpp-runner + GIT_REPOSITORY https://github.com/philips-software/amp-cucumber-cpp-runner.git + GIT_TAG f3ef05b18363c2199e0978341b96cb2443a2b8f5 # unreleased + ) + + FetchContent_MakeAvailable(cucumber-cpp-runner) + +endif() + add_subdirectory(st) add_subdirectory(hal_st) add_subdirectory(hal_st_lwip) -add_subdirectory(integration_test) +if (HALST_STANDALONE) + add_subdirectory(integration_test) +endif() add_subdirectory(services) add_subdirectory(examples) diff --git a/hal_st/stm32fxxx/DefaultClockNucleoF767ZI.cpp b/hal_st/stm32fxxx/DefaultClockNucleoF767ZI.cpp index 6988c4e3..5598b9c1 100644 --- a/hal_st/stm32fxxx/DefaultClockNucleoF767ZI.cpp +++ b/hal_st/stm32fxxx/DefaultClockNucleoF767ZI.cpp @@ -1,7 +1,6 @@ #include DEVICE_HEADER #include "hal_st/stm32fxxx/DefaultClockNucleoF767ZI.hpp" - /* The system Clock is configured as follows: * System Clock source = PLL (HSE) * SYSCLK(Hz) = 216000000 @@ -32,11 +31,11 @@ void ConfigureDefaultClockNucleo767ZI() RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; - RCC_OscInitStruct.PLL.PLLM = 4; // Divides the 8MHz HSI to 2MHz - RCC_OscInitStruct.PLL.PLLN = 216; // Multiplies the 2MHz to 432MHz - RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // Divides the 432MHz to 216MHz for SYSCLK - RCC_OscInitStruct.PLL.PLLQ = 9; // Divides the 432MHz to 48MHz for USB and SDMMC and RNG - RCC_OscInitStruct.PLL.PLLR = 7; // Divides the 432MHz to 62MHz for DSI (No clue what a good frequency would be here...) + RCC_OscInitStruct.PLL.PLLM = 4; // Divides the 8MHz HSI to 2MHz + RCC_OscInitStruct.PLL.PLLN = 216; // Multiplies the 2MHz to 432MHz + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // Divides the 432MHz to 216MHz for SYSCLK + RCC_OscInitStruct.PLL.PLLQ = 9; // Divides the 432MHz to 48MHz for USB and SDMMC and RNG + RCC_OscInitStruct.PLL.PLLR = 7; // Divides the 432MHz to 62MHz for DSI (No clue what a good frequency would be here...) HAL_RCC_OscConfig(&RCC_OscInitStruct); HAL_PWREx_EnableOverDrive(); diff --git a/integration_test/CMakeLists.txt b/integration_test/CMakeLists.txt index bdd05027..4373ce9d 100644 --- a/integration_test/CMakeLists.txt +++ b/integration_test/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(logic) add_subdirectory(tested) add_subdirectory(tester) +add_subdirectory(runner) diff --git a/integration_test/logic/CMakeLists.txt b/integration_test/logic/CMakeLists.txt index 6cd1c391..29cc26b7 100644 --- a/integration_test/logic/CMakeLists.txt +++ b/integration_test/logic/CMakeLists.txt @@ -15,6 +15,8 @@ target_sources(integration_test.logic PRIVATE Tested.hpp Tester.cpp Tester.hpp + Uart.cpp + Uart.hpp ) target_link_libraries(integration_test.logic PUBLIC diff --git a/integration_test/logic/Gpio.cpp b/integration_test/logic/Gpio.cpp index 5648c3b0..f7af13d7 100644 --- a/integration_test/logic/Gpio.cpp +++ b/integration_test/logic/Gpio.cpp @@ -19,21 +19,19 @@ namespace application in.DisableInterrupt(); } - void GpioBase::SetGpio(bool state, uint32_t pin) + void GpioBase::SetGpio(bool state) { out.Set(state); } void GpioBase::InChanged() { - if (!sending) + if (!std::exchange(sending, true)) RequestSend([this]() { sending = false; - TestedGpioChanged(in.Get(), 0); + GpioChanged(in.Get()); }); - - sending = true; } GpioTester::GpioTester(services::Echo& echo, hal::GpioPin& inPin, hal::GpioPin& outPin) @@ -41,20 +39,30 @@ namespace application , testing::GpioTester(echo) {} - void GpioTester::SetGpio(bool state, uint32_t pin) + void GpioTester::SetGpio(bool state) { - GpioBase::SetGpio(state, pin); + GpioBase::SetGpio(state); MethodDone(); } + void GpioTester::GpioChanged(bool state) + { + TesterGpioChanged(state); + } + GpioTested::GpioTested(services::Echo& echo, hal::GpioPin& inPin, hal::GpioPin& outPin) : GpioBase(echo, inPin, outPin) , testing::GpioTested(echo) {} - void GpioTested::SetGpio(bool state, uint32_t pin) + void GpioTested::SetGpio(bool state) { - GpioBase::SetGpio(state, pin); + GpioBase::SetGpio(state); MethodDone(); } + + void GpioTested::GpioChanged(bool state) + { + TestedGpioChanged(state); + } } diff --git a/integration_test/logic/Gpio.hpp b/integration_test/logic/Gpio.hpp index 4c7537ec..59c5cee0 100644 --- a/integration_test/logic/Gpio.hpp +++ b/integration_test/logic/Gpio.hpp @@ -13,7 +13,10 @@ namespace application GpioBase(services::Echo& echo, hal::GpioPin& inPin, hal::GpioPin& outPin); ~GpioBase(); - void SetGpio(bool state, uint32_t pin); + void SetGpio(bool state); + + protected: + virtual void GpioChanged(bool state) = 0; private: void InChanged(); @@ -32,7 +35,10 @@ namespace application GpioTester(services::Echo& echo, hal::GpioPin& inPin, hal::GpioPin& outPin); // Implementation of GpioTester - void SetGpio(bool state, uint32_t pin) override; + void SetGpio(bool state) override; + + protected: + virtual void GpioChanged(bool state) override; }; class GpioTested @@ -43,7 +49,10 @@ namespace application GpioTested(services::Echo& echo, hal::GpioPin& inPin, hal::GpioPin& outPin); // Implementation of GpioTested - void SetGpio(bool state, uint32_t pin) override; + void SetGpio(bool state) override; + + protected: + virtual void GpioChanged(bool state) override; }; } diff --git a/integration_test/logic/Peripheral.cpp b/integration_test/logic/Peripheral.cpp index 070c1578..bef39f28 100644 --- a/integration_test/logic/Peripheral.cpp +++ b/integration_test/logic/Peripheral.cpp @@ -27,4 +27,9 @@ namespace application return false; }); } + + void Peripherals::Reset() + { + currentPeripheral = nullptr; + } } diff --git a/integration_test/logic/Peripheral.hpp b/integration_test/logic/Peripheral.hpp index 13df7191..948f5ba7 100644 --- a/integration_test/logic/Peripheral.hpp +++ b/integration_test/logic/Peripheral.hpp @@ -29,37 +29,38 @@ namespace application virtual services::Echo& GetEcho() const = 0; void EnablePeripheral(testing::Peripheral type); + void Reset(); private: infra::SharedPtr currentPeripheral; }; - template - class Perpipheral + template + class Peripheral : public PeripheralBase { public: - Perpipheral(Peripherals& subject, testing::Peripheral type); + Peripheral(Peripherals& subject, testing::Peripheral type, Args&&... args); infra::SharedPtr Construct() override; private: - services::Echo& echo; + std::tuple args; infra::SharedOptional constructed; }; //// Implementation //// - template - Perpipheral::Perpipheral(Peripherals& subject, testing::Peripheral type) + template + Peripheral::Peripheral(Peripherals& subject, testing::Peripheral type, Args&&... args) : PeripheralBase(subject, type) - , echo(subject.GetEcho()) + , args(subject.GetEcho(), std::forward(args)...) {} - template - infra::SharedPtr Perpipheral::Construct() + template + infra::SharedPtr Peripheral::Construct() { - return constructed.Emplace(echo); + return std::apply(&infra::SharedOptional::template Emplace, std::tuple_cat(std::tuple&>(constructed), args)); } } diff --git a/integration_test/logic/Tested.cpp b/integration_test/logic/Tested.cpp index 5ed71657..699a3a5f 100644 --- a/integration_test/logic/Tested.cpp +++ b/integration_test/logic/Tested.cpp @@ -4,8 +4,18 @@ namespace application { Tested::Tested(services::Echo& echo) : testing::Tested(echo) + , testedObserver(echo) {} + void Tested::Ping() + { + testedObserver.RequestSend([this]() + { + testedObserver.Pong(); + MethodDone(); + }); + } + void Tested::EnablePeripheral(testing::Peripheral type) { Peripherals::EnablePeripheral(type); diff --git a/integration_test/logic/Tested.hpp b/integration_test/logic/Tested.hpp index 8a0de162..61744c1c 100644 --- a/integration_test/logic/Tested.hpp +++ b/integration_test/logic/Tested.hpp @@ -16,10 +16,35 @@ namespace application Tested(services::Echo& echo); // Implementation of Tested + void Ping() override; void EnablePeripheral(testing::Peripheral type) override; // Implementation of Peripherals services::Echo& GetEcho() const override; + + private: + testing::TestedObserverProxy testedObserver; + }; + + class TestedObserver + : public testing::TestedObserver + { + public: + using testing::TestedObserver::TestedObserver; + + void Pong() override + { + pongReceived = true; + MethodDone(); + } + + bool ReceivedPong() + { + return std::exchange(pongReceived, false); + } + + private: + bool pongReceived = false; }; } diff --git a/integration_test/logic/Tester.cpp b/integration_test/logic/Tester.cpp index 40cf7233..f401086b 100644 --- a/integration_test/logic/Tester.cpp +++ b/integration_test/logic/Tester.cpp @@ -2,8 +2,9 @@ namespace application { - Tester::Tester(services::Echo& echo, hal::GpioPin& resetTesterPin) + Tester::Tester(services::Echo& echo, hal::GpioPin& resetTesterPin, services::EchoOnSesame& echoToTested) : testing::Tester(echo) + , echoToTested(echoToTested) , resetTester(resetTesterPin, true) {} @@ -11,7 +12,10 @@ namespace application { resetTester.Set(false); - resetTimer.Start(std::chrono::milliseconds(3000), [this]() + Peripherals::Reset(); + echoToTested.Reset(); + + resetTimer.Start(std::chrono::milliseconds(10), [this]() { resetTester.Set(true); MethodDone(); diff --git a/integration_test/logic/Tester.hpp b/integration_test/logic/Tester.hpp index eb3494b4..8ce40a78 100644 --- a/integration_test/logic/Tester.hpp +++ b/integration_test/logic/Tester.hpp @@ -5,6 +5,7 @@ #include "hal/interfaces/Gpio.hpp" #include "infra/timer/Timer.hpp" #include "integration_test/logic/Peripheral.hpp" +#include "services/util/EchoOnSesame.hpp" namespace application { @@ -13,7 +14,7 @@ namespace application , public Peripherals { public: - Tester(services::Echo& echo, hal::GpioPin& resetTesterPin); + Tester(services::Echo& echo, hal::GpioPin& resetTesterPin, services::EchoOnSesame& echoToTested); // Implementation of Tester void Reset() override; @@ -23,10 +24,9 @@ namespace application services::Echo& GetEcho() const override; private: + services::EchoOnSesame& echoToTested; hal::OutputPin resetTester; infra::TimerSingleShot resetTimer; - - infra::SharedPtr currentPeripheral; }; } diff --git a/integration_test/logic/Testing.proto b/integration_test/logic/Testing.proto index 0995d036..5cecadb1 100644 --- a/integration_test/logic/Testing.proto +++ b/integration_test/logic/Testing.proto @@ -7,12 +7,18 @@ package testing; message GpioState { bool state = 1; - uint32 pin = 2; +} + +message Data +{ + bytes data = 1 [(bytes_size) = 32]; } enum Peripheral { gpio = 0; + uart = 1; + uartDuplexDma = 2; } message PeripheralType @@ -32,27 +38,57 @@ service Tested { option (service_id) = 2; + rpc Ping(Nothing) returns (Nothing) { option (method_id) = 1; } rpc EnablePeripheral(PeripheralType) returns (Nothing) { option (method_id) = 2; } } -service GpioTester +service TestedObserver { option (service_id) = 3; + rpc Pong(Nothing) returns (Nothing) { option (method_id) = 1; } +} + +service GpioTester +{ + option (service_id) = 4; + rpc SetGpio(GpioState) returns (Nothing) { option (method_id) = 1; } } service GpioTested { - option (service_id) = 4; + option (service_id) = 5; rpc SetGpio(GpioState) returns (Nothing) { option (method_id) = 1; } } service GpioObserver { - option (service_id) = 5; + option (service_id) = 6; rpc TesterGpioChanged(GpioState) returns (Nothing) { option (method_id) = 1; } rpc TestedGpioChanged(GpioState) returns (Nothing) { option (method_id) = 2; } } + +service UartTester +{ + option (service_id) = 7; + + rpc SendData(Data) returns (Nothing) { option (method_id) = 1; } +} + +service UartTested +{ + option (service_id) = 8; + + rpc SendData(Data) returns (Nothing) { option (method_id) = 1; } +} + +service UartObserver +{ + option (service_id) = 9; + + rpc TesterReceivedData(Data) returns (Nothing) { option (method_id) = 1; } + rpc TestedReceivedData(Data) returns (Nothing) { option (method_id) = 2; } +} diff --git a/integration_test/logic/Uart.cpp b/integration_test/logic/Uart.cpp new file mode 100644 index 00000000..6d78cb50 --- /dev/null +++ b/integration_test/logic/Uart.cpp @@ -0,0 +1,70 @@ +#include "integration_test/logic/Uart.hpp" + +namespace application +{ + UartBase::UartBase(services::Echo& echo, hal::BufferedSerialCommunication& uart) + : testing::UartObserverProxy(echo) + , hal::BufferedSerialCommunicationObserver(uart) + {} + + void UartBase::SendData(const infra::ConstByteRange& data, const infra::Function& onDone) + { + Subject().SendData(data, onDone); + } + + void UartBase::DataReceived() + { + auto& reader = Subject().Reader(); + while (!reader.Empty()) + { + auto range = infra::Head(reader.ExtractContiguousRange(std::numeric_limits::max()), receivedData.max_size() - receivedData.size()); + receivedData.insert(receivedData.end(), range.begin(), range.end()); + } + + Subject().AckReceived(); + + if (!std::exchange(sending, true)) + RequestSend([this]() + { + sending = false; + ReceivedData(infra::MakeRange(receivedData)); + receivedData.clear(); + }); + } + + UartTester::UartTester(services::Echo& echo, hal::BufferedSerialCommunication& uart) + : UartBase(echo, uart) + , testing::UartTester(echo) + {} + + void UartTester::SendData(infra::ConstByteRange data) + { + UartBase::SendData(data, [this]() + { + MethodDone(); + }); + } + + void UartTester::ReceivedData(infra::ConstByteRange data) + { + TesterReceivedData(data); + } + + UartTested::UartTested(services::Echo& echo, hal::BufferedSerialCommunication& uart) + : UartBase(echo, uart) + , testing::UartTested(echo) + {} + + void UartTested::SendData(infra::ConstByteRange data) + { + UartBase::SendData(data, [this]() + { + MethodDone(); + }); + } + + void UartTested::ReceivedData(infra::ConstByteRange data) + { + TestedReceivedData(data); + } +} diff --git a/integration_test/logic/Uart.hpp b/integration_test/logic/Uart.hpp new file mode 100644 index 00000000..442dd1b8 --- /dev/null +++ b/integration_test/logic/Uart.hpp @@ -0,0 +1,59 @@ +#ifndef HAL_ST_INTEGRATION_TEST_UART_HPP +#define HAL_ST_INTEGRATION_TEST_UART_HPP + +#include "generated/echo/Testing.pb.hpp" +#include "hal/interfaces/SerialCommunication.hpp" + +namespace application +{ + class UartBase + : public testing::UartObserverProxy + , private hal::BufferedSerialCommunicationObserver + { + public: + UartBase(services::Echo& echo, hal::BufferedSerialCommunication& uart); + + void SendData(const infra::ConstByteRange& data, const infra::Function& onDone); + + protected: + virtual void ReceivedData(infra::ConstByteRange data) = 0; + + private: + // Implementation of BufferedSerialCommunicationObserver + void DataReceived() override; + + private: + bool sending = false; + infra::BoundedVector::WithMaxSize<32> receivedData; + }; + + class UartTester + : public UartBase + , public testing::UartTester + { + public: + UartTester(services::Echo& echo, hal::BufferedSerialCommunication& uart); + + // Implementation of UartTester + void SendData(infra::ConstByteRange data) override; + + protected: + virtual void ReceivedData(infra::ConstByteRange data) override; + }; + + class UartTested + : public UartBase + , public testing::UartTested + { + public: + UartTested(services::Echo& echo, hal::BufferedSerialCommunication& uart); + + // Implementation of UartTested + void SendData(infra::ConstByteRange data) override; + + protected: + virtual void ReceivedData(infra::ConstByteRange data) override; + }; +} + +#endif diff --git a/integration_test/pcb/integration_test_board/eagle.epf b/integration_test/pcb/integration_test_board/eagle.epf new file mode 100644 index 00000000..adc7dcd3 --- /dev/null +++ b/integration_test/pcb/integration_test_board/eagle.epf @@ -0,0 +1,25 @@ +[Eagle] +Version="06 03 00" +Platform="Windows" +Serial="62191E841E-LSR-WLM-1EL" +Globals="Globals" +Desktop="Desktop" + +[Globals] +AutoSaveProject=1 +UsedLibrary="C:/Users/richa/Documents/eagle/lbr/Richard/diode.lbr" +UsedLibrary="C:/Users/richa/Documents/eagle/lbr/Richard/header.lbr" +UsedLibrary="C:/Users/richa/Documents/eagle/lbr/Richard/ic.lbr" +UsedLibrary="C:/Users/richa/Documents/eagle/lbr/Richard/passive.lbr" +UsedLibrary="C:/Users/richa/Documents/eagle/lbr/Richard/supply.lbr" +UsedLibrary="C:/Users/richa/Documents/eagle/lbr/Richard/transistor.lbr" + +[Win_1] +Type="Control Panel" +Loc="616 301 1215 700" +State=1 +Number=0 + +[Desktop] +Screen="1920 1080" +Window="Win_1" diff --git a/integration_test/pcb/integration_test_board/integration_test_board 1.0.zip b/integration_test/pcb/integration_test_board/integration_test_board 1.0.zip new file mode 100644 index 00000000..a8276252 Binary files /dev/null and b/integration_test/pcb/integration_test_board/integration_test_board 1.0.zip differ diff --git a/integration_test/pcb/integration_test_board/integration_test_board.brd b/integration_test/pcb/integration_test_board/integration_test_board.brd new file mode 100644 index 00000000..eacba24d --- /dev/null +++ b/integration_test/pcb/integration_test_board/integration_test_board.brd @@ -0,0 +1,1225 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +TESTER +TESTED +amp-hal-st Integration Test Board 1.0 + + + + + + + + + +JP3 + + + + + +JP3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>Name + + + + + + + + + + + + + + + + + + + + + + + + + +<b>Mini Melf Diode</b> + + + + + + + +>NAME +>VALUE + + + + + + + +1uF 5.3 4.1<br> +4.7uF 5.3<br> +10uF 5.3 6.5<br> +22uF 5.3<br> +47uF 6.5<br> +100uF 6.5 8.2<br> +220uF 10.3<br> +330uF 8.3<br> +470uF 8.3<br> +680uF 10.2<br> +1000uF 10.2<br> +2200uF 16.2<br> + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + +<b>JLCPCB design rules (2 layers)</b> +<ul> +<li>Board thickness: 1.6mm</li> +<li>Copper weight: 1oz (35um)</li> +<li>Note: annular ring aren't minimal</li> +</ul> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/integration_test/pcb/integration_test_board/integration_test_board.sch b/integration_test/pcb/integration_test_board/integration_test_board.sch new file mode 100644 index 00000000..0b37e963 --- /dev/null +++ b/integration_test/pcb/integration_test_board/integration_test_board.sch @@ -0,0 +1,2047 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>Name + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>Name +>Value + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + +>NAME +>VALUE + + + + +<b>Mini Melf Diode</b> + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1uF 5.3 4.1<br> +4.7uF 5.3<br> +10uF 5.3 6.5<br> +22uF 5.3<br> +47uF 6.5<br> +100uF 6.5 8.2<br> +220uF 10.3<br> +330uF 8.3<br> +470uF 8.3<br> +680uF 10.2<br> +1000uF 10.2<br> +2200uF 16.2<br> + + + + + + + +>NAME +>VALUE + + + + + + + +>NAME +>VALUE + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>NAME +>VALUE + + + + + + + + + +>NAME +>VALUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ++3.3V + + + + + + + + + ++5V + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ECHO from Postmaster + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/integration_test/runner/CMakeLists.txt b/integration_test/runner/CMakeLists.txt new file mode 100644 index 00000000..ea573548 --- /dev/null +++ b/integration_test/runner/CMakeLists.txt @@ -0,0 +1,22 @@ +add_executable(integration_test.runner) +emil_build_for(integration_test.runner HOST Windows) + +target_sources(integration_test.runner PRIVATE + FixtureEcho.cpp + FixtureEcho.hpp + Hooks.cpp + StepsGpio.cpp + StepsUart.cpp + Waiting.cpp + Waiting.hpp +) + +target_link_libraries(integration_test.runner PRIVATE + args + cucumber-cpp-runner + integration_test.logic + hal.generic + gtest + gmock + services.network_instantiations +) diff --git a/integration_test/runner/FixtureEcho.cpp b/integration_test/runner/FixtureEcho.cpp new file mode 100644 index 00000000..e1b0be90 --- /dev/null +++ b/integration_test/runner/FixtureEcho.cpp @@ -0,0 +1,80 @@ +#include "integration_test/runner/FixtureEcho.hpp" + +namespace main_ +{ + EchoClientWebSocket::EchoClientWebSocket(services::ConnectionFactoryWithNameResolver& connectionFactory, + infra::BoundedString url, hal::SynchronousRandomDataGenerator& randomDataGenerator) + : url(url) + , clientConnector(connectionFactory) + , httpClientInitiationCreator( + [this](infra::Optional& value, services::WebSocketClientObserverFactory& clientObserverFactory, + services::HttpClientWebSocketInitiationResult& result, hal::SynchronousRandomDataGenerator& randomDataGenerator) + { + value.Emplace(clientObserverFactory, clientConnector, result, randomDataGenerator); + }) + , webSocketFactory(randomDataGenerator, { httpClientInitiationCreator }) + { + webSocketFactory.Connect(*this); + } + + void EchoClientWebSocket::OnDone(const OnDoneType& onDone) + { + this->onDone = onDone; + } + + infra::BoundedString EchoClientWebSocket::Url() const + { + return url; + } + + uint16_t EchoClientWebSocket::Port() const + { + return 80; + } + + void EchoClientWebSocket::ConnectionEstablished(infra::AutoResetFunction client)>&& createdClientObserver) + { + auto echoConnectionPtr = echoConnection.Emplace(serializerFactory); + createdClientObserver(echoConnectionPtr); + onDone(*echoConnectionPtr); + } + + void EchoClientWebSocket::ConnectionFailed(ConnectFailReason reason) + { + throw std::runtime_error("Creating ECHO over WebSocket failed"); + } + + EchoClientTcp::EchoClientTcp(services::ConnectionFactoryWithNameResolver& connectionFactory, infra::BoundedConstString hostname, uint16_t port) + : hostname(hostname) + , port(port) + { + connectionFactory.Connect(*this); + } + + void EchoClientTcp::OnDone(const OnDoneType& onDone) + { + this->onDone = onDone; + } + + infra::BoundedConstString EchoClientTcp::Hostname() const + { + return hostname; + } + + uint16_t EchoClientTcp::Port() const + { + return port; + } + + void EchoClientTcp::ConnectionEstablished(infra::AutoResetFunction connectionObserver)>&& createdObserver) + { + auto echoConnectionPtr = echoConnection.Emplace(serializerFactory); + createdObserver(echoConnectionPtr); + onDone(*echoConnectionPtr); + } + + void EchoClientTcp::ConnectionFailed(services::ClientConnectionObserverFactoryWithNameResolver::ConnectFailReason reason) + { + throw std::runtime_error("Creating ECHO over TCP/IP failed"); + } +} diff --git a/integration_test/runner/FixtureEcho.hpp b/integration_test/runner/FixtureEcho.hpp new file mode 100644 index 00000000..60fa358b --- /dev/null +++ b/integration_test/runner/FixtureEcho.hpp @@ -0,0 +1,102 @@ +#ifndef FIXTURES_ECHO_HPP +#define FIXTURES_ECHO_HPP + +#include "generated/echo/TracingTesting.pb.hpp" +#include "hal/generic/UartGeneric.hpp" +#include "services/network/EchoOnConnection.hpp" +#include "services/network/HttpClientImpl.hpp" +#include "services/network/WebSocketClientConnectionObserver.hpp" +#include "services/tracer/GlobalTracer.hpp" +#include "services/tracer/TracingEchoInstantiation.hpp" + +namespace main_ +{ + struct FixtureEchoSerialBase + { + FixtureEchoSerialBase(const std::string& portName) + : serial(portName) + {} + + hal::UartGeneric serial; + services::MethodSerializerFactory::OnHeap serializerFactory; + hal::BufferedSerialCommunicationOnUnbuffered::WithStorage<256> bufferedSerial{ serial }; + }; + + struct FixtureEchoSerial + : FixtureEchoSerialBase + { + main_::EchoOnSesame<256> echoOnSesame{ bufferedSerial, serializerFactory }; + + services::Echo& echo{ echoOnSesame.echo }; + }; + + struct FixtureTracingEchoSerial + : FixtureEchoSerialBase + { + main_::TracingEchoOnSesame<256> echoOnSesame{ bufferedSerial, serializerFactory, services::GlobalTracer() }; + + services::Echo& echo{ echoOnSesame.echo }; + testing::TesterTracer testerTracer{ echoOnSesame.echo }; + testing::TestedTracer testedTracer{ echoOnSesame.echo }; + testing::TestedObserverTracer testedObserverTracer{ echoOnSesame.echo }; + testing::GpioTesterTracer gpioTesterTracer{ echoOnSesame.echo }; + testing::GpioTestedTracer gpioTestedTracer{ echoOnSesame.echo }; + testing::GpioObserverTracer gpioObserverTracer{ echoOnSesame.echo }; + }; + + class EchoClientWebSocket + : private services::WebSocketClientObserverFactory + { + public: + using OnDoneType = infra::Function)>; + + EchoClientWebSocket(services::ConnectionFactoryWithNameResolver& connectionFactory, + infra::BoundedString url, hal::SynchronousRandomDataGenerator& randomDataGenerator); + + void OnDone(const OnDoneType& onDone); + + private: + infra::BoundedString Url() const override; + uint16_t Port() const override; + void ConnectionEstablished(infra::AutoResetFunction client)>&& createdClientObserver) override; + void ConnectionFailed(ConnectFailReason reason) override; + + private: + infra::BoundedString url; + services::HttpClientConnectorWithNameResolverImpl<> clientConnector; + infra::Creator httpClientInitiationCreator; + services::WebSocketClientFactorySingleConnection webSocketFactory; + + infra::SharedOptional echoConnection; + OnDoneType onDone; + services::MethodSerializerFactory::OnHeap serializerFactory; + }; + + class EchoClientTcp + : private services::ClientConnectionObserverFactoryWithNameResolver + { + public: + using OnDoneType = infra::Function)>; + + EchoClientTcp(services::ConnectionFactoryWithNameResolver& connectionFactory, infra::BoundedConstString hostname, uint16_t port); + + void OnDone(const OnDoneType& onDone); + + private: + // Implementation of ClientConnectionObserverFactoryWithNameResolver + infra::BoundedConstString Hostname() const override; + uint16_t Port() const override; + void ConnectionEstablished(infra::AutoResetFunction connectionObserver)>&& createdObserver) override; + void ConnectionFailed(services::ClientConnectionObserverFactoryWithNameResolver::ConnectFailReason reason) override; + + private: + infra::BoundedConstString hostname; + uint16_t port; + + infra::SharedOptional echoConnection; + OnDoneType onDone; + services::MethodSerializerFactory::OnHeap serializerFactory; + }; +} + +#endif diff --git a/integration_test/runner/Hooks.cpp b/integration_test/runner/Hooks.cpp new file mode 100644 index 00000000..fe9a2e2b --- /dev/null +++ b/integration_test/runner/Hooks.cpp @@ -0,0 +1,114 @@ +#include "cucumber-cpp/Hooks.hpp" +#include "args.hxx" +#include "generated/echo/Testing.pb.hpp" +#include "hal/generic/SynchronousRandomDataGeneratorGeneric.hpp" +#include "hal/generic/TimerServiceGeneric.hpp" +#include "infra/event/EventDispatcherThreadAware.hpp" +#include "integration_test/logic/Tested.hpp" +#include "integration_test/runner/FixtureEcho.hpp" +#include "integration_test/runner/Waiting.hpp" +#include "services/network_instantiations/NetworkAdapter.hpp" +#include "gtest/gtest.h" + +HOOK_BEFORE_ALL() +{ + args::ArgumentParser parser("Integration test runner for amp-hal-st"); + args::Group arguments(parser, "Arguments:"); + args::Positional target(arguments, "target", "COM port or hostname (ws:///path or tcp://) of the amp-hal-st integration test board", args::Options::Required); + args::Group flags(parser, "Optional flags:"); + args::HelpFlag help(flags, "help", "Display this help menu.", { 'h', "help" }); + + try + { + const auto& args = context.Get>("args"); + std::vector stringArgs(args.begin(), args.end()); + parser.ParseArgs(stringArgs); + + auto networkAdapter = std::make_shared(); + context.SetShared(std::shared_ptr(networkAdapter, &networkAdapter->EventDispatcher())); + context.SetShared(std::shared_ptr(networkAdapter, &networkAdapter->ConnectionFactoryWithNameResolver())); + context.Emplace(); + + if (args::get(target).substr(0, 3) == "COM" || args::get(target).substr(0, 4) == "/dev") + { + auto echoFixture = std::make_shared(args::get(target)); + context.SetShared(std::shared_ptr(echoFixture, &echoFixture->echo)); + } + else if (services::SchemeFromUrl(infra::BoundedConstString(args::get(target))) == "ws") + { + if (!infra::WaitUntilDone( + context, [&](const std::function& done) + { + static hal::SynchronousRandomDataGeneratorGeneric randomDataGenerator; + + auto echoFixture = std::make_shared( + context.Get(), + args::get(target), randomDataGenerator); + echoFixture->OnDone([&, echoFixture](services::Echo& echo) + { + context.SetShared(std::shared_ptr(echoFixture, &echo)); + done(); + }); + }, + std::chrono::seconds(10))) + throw std::runtime_error("Couldn't open websocket connection"); + } + else if (services::SchemeFromUrl(infra::BoundedConstString(args::get(target))) == "tcp") + { + if (!infra::WaitUntilDone( + context, [&](const std::function& done) + { + static hal::SynchronousRandomDataGeneratorGeneric randomDataGenerator; + + auto echoFixture = std::make_shared( + context.Get(), + services::HostFromUrl(infra::BoundedConstString(args::get(target))), services::PortFromUrl(args::get(target)).ValueOr(1234)); + echoFixture->OnDone([&, echoFixture](services::Echo& echo) + { + context.SetShared(std::shared_ptr(echoFixture, &echo)); + done(); + }); + }, + std::chrono::seconds(10))) + throw std::runtime_error("Couldn't open websocket connection"); + } + else + throw std::runtime_error("Don't know how to open " + args::get(target)); + + context.Emplace(context.Get()); + context.Emplace(context.Get()); + context.Emplace(context.Get()); + } + catch (const args::Error& error) + { + std::ostringstream errorPlusHelp; + errorPlusHelp << error.what() << parser; + throw std::runtime_error(errorPlusHelp.str()); + } +} + +HOOK_BEFORE_SCENARIO() +{ + EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + { + context.Get().RequestSend([&]() + { + context.Get().Reset(); + done(); + }); + })); + + EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + { + context.Get().RequestSend([&]() + { + context.Get().Ping(); + done(); + }); + })); + + EXPECT_TRUE(infra::WaitFor(context, [&]() + { + return context.Get().ReceivedPong(); + })); +} diff --git a/integration_test/runner/StepsGpio.cpp b/integration_test/runner/StepsGpio.cpp new file mode 100644 index 00000000..3bcfe3f5 --- /dev/null +++ b/integration_test/runner/StepsGpio.cpp @@ -0,0 +1,126 @@ +#include "cucumber-cpp/Steps.hpp" +#include "generated/echo/Testing.pb.hpp" +#include "integration_test/logic/Tested.hpp" +#include "integration_test/runner/Waiting.hpp" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace +{ + bool ConvertPinState(const std::string& state) + { + if (state == "high") + return true; + else if (state == "low") + return false; + else + std::abort(); + } + + class GpioObserver + : public testing::GpioObserver + { + public: + GpioObserver(services::Echo& echo) + : testing::GpioObserver(echo) + {} + + void TesterGpioChanged(bool state) override + { + testerGpio = state; + MethodDone(); + } + + void TestedGpioChanged(bool state) override + { + testedGpio = state; + MethodDone(); + } + + bool testerGpio = false; + bool testedGpio = false; + }; +} + +STEP("gpio peripherals are enabled") +{ + EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + { + context.Emplace(context.Get()); + + context.Get().RequestSend([&]() + { + context.Get().EnablePeripheral(testing::Peripheral::gpio); + done(); + }); + })); + + EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + { + context.Get().RequestSend([&]() + { + context.Get().EnablePeripheral(testing::Peripheral::gpio); + context.Get().RequestSend([&]() + { + context.Get().Ping(); + done(); + }); + }); + })); + + EXPECT_TRUE(infra::WaitFor(context, [&]() + { + return context.Get().ReceivedPong(); + })); + + context.Emplace(context.Get()); + context.Emplace(context.Get()); +} + +STEP("the tester sets its output pin (high|low)", (std::string state)) +{ + context.EmplaceAt("state", ConvertPinState(state)); + + EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + { + context.Get().RequestSend([&]() + { + context.Get().SetGpio(context.Get("state")); + done(); + }); + })); +} + +STEP("the tester sees a (high|low) value", (std::string state)) +{ + context.EmplaceAt("state", ConvertPinState(state)); + + EXPECT_TRUE(infra::WaitFor(context, [&]() + { + return context.Get().testerGpio == context.Get("state"); + })); +} + +STEP("the tested sets its output pin (high|low)", (std::string state)) +{ + context.EmplaceAt("state", ConvertPinState(state)); + + EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + { + context.Get().RequestSend([&]() + { + context.Get().SetGpio(context.Get("state")); + done(); + }); + })); +} + +STEP("the tested sees a (high|low) value", (std::string state)) +{ + context.EmplaceAt("state", ConvertPinState(state)); + + EXPECT_TRUE(infra::WaitFor(context, [&]() + { + return context.Get().testedGpio == context.Get("state"); + })); +} diff --git a/integration_test/runner/StepsUart.cpp b/integration_test/runner/StepsUart.cpp new file mode 100644 index 00000000..14ac869d --- /dev/null +++ b/integration_test/runner/StepsUart.cpp @@ -0,0 +1,151 @@ +#include "cucumber-cpp/Steps.hpp" +#include "generated/echo/Testing.pb.hpp" +#include "integration_test/logic/Tested.hpp" +#include "integration_test/runner/Waiting.hpp" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace +{ + class UartObserver + : public testing::UartObserver + { + public: + UartObserver(services::Echo& echo) + : testing::UartObserver(echo) + {} + + void TesterReceivedData(infra::ConstByteRange data) override + { + testerData.insert(testerData.end(), data.begin(), data.end()); + MethodDone(); + } + + void TestedReceivedData(infra::ConstByteRange data) override + { + testedData.insert(testedData.end(), data.begin(), data.end()); + MethodDone(); + } + + std::vector testerData; + std::vector testedData; + }; +} + +STEP("uart peripherals are enabled") +{ + EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + { + context.Emplace(context.Get()); + + context.Get().RequestSend([&]() + { + context.Get().EnablePeripheral(testing::Peripheral::uart); + done(); + }); + })); + + EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + { + context.Get().RequestSend([&]() + { + context.Get().EnablePeripheral(testing::Peripheral::uart); + context.Get().RequestSend([&]() + { + context.Get().Ping(); + done(); + }); + }); + })); + + EXPECT_TRUE(infra::WaitFor(context, [&]() + { + return context.Get().ReceivedPong(); + })); + + context.Emplace(context.Get()); + context.Emplace(context.Get()); +} + +STEP("uart duplex dma peripherals are enabled") +{ + EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + { + context.Emplace(context.Get()); + + context.Get().RequestSend([&]() + { + context.Get().EnablePeripheral(testing::Peripheral::uartDuplexDma); + done(); + }); + })); + + EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + { + context.Get().RequestSend([&]() + { + context.Get().EnablePeripheral(testing::Peripheral::uartDuplexDma); + context.Get().RequestSend([&]() + { + context.Get().Ping(); + done(); + }); + }); + })); + + EXPECT_TRUE(infra::WaitFor(context, [&]() + { + return context.Get().ReceivedPong(); + })); + + context.Emplace(context.Get()); + context.Emplace(context.Get()); +} + +STEP("the tester sends UART data") +{ + static const infra::BoundedVector::WithMaxSize<32> expectedData{ { 1, 2, 3, 4, 5, 6 } }; + + EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + { + context.Get().RequestSend([&]() + { + context.Get().SendData(expectedData.range()); + done(); + }); + })); +} + +STEP("the tested sends UART data") +{ + static const infra::BoundedVector::WithMaxSize<32> expectedData{ { 1, 2, 3, 4, 5, 6 } }; + + EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + { + context.Get().RequestSend([&]() + { + context.Get().SendData(expectedData.range()); + done(); + }); + })); +} + +STEP("the tester sees UART data") +{ + static const std::vector expectedData{ 1, 2, 3, 4, 5, 6 }; + + EXPECT_TRUE(infra::WaitFor(context, [&]() + { + return context.Get().testerData == expectedData; + })); +} + +STEP("the tested sees UART data") +{ + static const std::vector expectedData{ 1, 2, 3, 4, 5, 6 }; + + EXPECT_TRUE(infra::WaitFor(context, [&]() + { + return context.Get().testedData == expectedData; + })); +} diff --git a/integration_test/runner/Waiting.cpp b/integration_test/runner/Waiting.cpp new file mode 100644 index 00000000..a2dee555 --- /dev/null +++ b/integration_test/runner/Waiting.cpp @@ -0,0 +1,98 @@ +#include "integration_test/runner/Waiting.hpp" +#include "infra/event/EventDispatcherThreadAware.hpp" +#include "gmock/gmock.h" + +namespace infra +{ + bool WaitUntilDone(cucumber_cpp::Context& context, const std::function&)>& action, infra::Duration timeout) + { + bool done{ false }; + bool timedOut{ false }; + + std::function onDone = [&done]() + { + done = true; + }; + + action(onDone); + + infra::TimerSingleShot timeoutTimer{ timeout, [&timedOut]() + { + timedOut = true; + } }; + + context.Get().ExecuteUntil([&done, &timedOut]() + { + return done || timedOut; + }); + + return !timedOut; + } + + bool WaitFor(cucumber_cpp::Context& context, const std::function& pred, infra::Duration timeout) + { + bool timedOut{ false }; + + infra::TimerSingleShot timeoutTimer{ timeout, [&timedOut] + { + timedOut = true; + } }; + + context.Get().ExecuteUntil([&pred, &timedOut]() + { + return pred() || timedOut; + }); + + return !timedOut; + } + + void WaitFor(cucumber_cpp::Context& context, infra::Duration timeout) + { + bool done{ false }; + + infra::TimerSingleShot timeoutTimer{ timeout, [&done]() + { + done = true; + } }; + + context.Get().ExecuteUntil([&done]() + { + return done; + }); + } + + Async::Async(cucumber_cpp::Context& context) + : Async{ context, [this]() + { + return notified; + } } + {} + + Async::Async(cucumber_cpp::Context& context, std::function func) + : context{ context } + , func{ std::move(func) } + {} + + Async::operator infra::Function() + { + return [this]() + { + Notify(); + }; + } + + void Async::Notify() + { + notified = true; + } + + [[nodiscard]] bool Async::Wait(infra::Duration timeout) const + { + return WaitFor( + context, [this]() + { + return func(); + }, + timeout); + } +} diff --git a/integration_test/runner/Waiting.hpp b/integration_test/runner/Waiting.hpp new file mode 100644 index 00000000..4aa8ef12 --- /dev/null +++ b/integration_test/runner/Waiting.hpp @@ -0,0 +1,44 @@ +#ifndef INTEGRATION_TEST_WAITING_HPP +#define INTEGRATION_TEST_WAITING_HPP + +#include "cucumber-cpp/Context.hpp" +#include "infra/timer/Timer.hpp" + +namespace infra +{ + constexpr inline infra::Duration defaultTimeout{ std::chrono::seconds{ 1 } }; + + bool WaitUntilDone(cucumber_cpp::Context& context, const std::function&)>& action, infra::Duration timeout = defaultTimeout); + bool WaitFor(cucumber_cpp::Context& context, const std::function& pred, infra::Duration timeout = defaultTimeout); + void WaitFor(cucumber_cpp::Context& context, infra::Duration timeout); + + template + bool WaitForValue(cucumber_cpp::Context& context, const Obj& obj, const T& value, Proj proj = {}, Arg&&... args, infra::Duration timeout = defaultTimeout) + { + return WaitFor( + context, [&proj, &obj, &args..., &value]() + { + return std::invoke(proj, obj, std::forward(args)...) == value; + }, + timeout); + } + + struct Async + { + explicit Async(cucumber_cpp::Context& context); + Async(cucumber_cpp::Context& context, std::function func); + + operator infra::Function(); + + void Notify(); + + [[nodiscard]] bool Wait(infra::Duration timeout = defaultTimeout) const; + + private: + cucumber_cpp::Context& context; + std::function func; + bool notified{ false }; + }; +} + +#endif diff --git a/integration_test/runner/features/gpio.feature b/integration_test/runner/features/gpio.feature new file mode 100644 index 00000000..3919a393 --- /dev/null +++ b/integration_test/runner/features/gpio.feature @@ -0,0 +1,18 @@ +@device:stm32f767 +Feature: GPIO + Test the GPIO functionality + + Background: + Given gpio peripherals are enabled + + Scenario: toggle an output pin + When the tested sets its output pin high + Then the tester sees a high value + When the tested sets its output pin low + Then the tester sees a low value + + Scenario: observe an input pin + When the tester sets its output pin high + Then the tested sees a high value + When the tester sets its output pin low + Then the tested sees a low value diff --git a/integration_test/runner/features/uart.feature b/integration_test/runner/features/uart.feature new file mode 100644 index 00000000..f1c438cc --- /dev/null +++ b/integration_test/runner/features/uart.feature @@ -0,0 +1,14 @@ +@device:stm32f767 +Feature: UART + Test the UART functionality + + Background: + Given uart peripherals are enabled + + Scenario: Send data over UART + When the tested sends UART data + Then the tester sees UART data + + Scenario: Receive data over UART + When the tester sends UART data + Then the tested sees UART data diff --git a/integration_test/runner/features/uart_duplex_dma.feature b/integration_test/runner/features/uart_duplex_dma.feature new file mode 100644 index 00000000..20ef4af5 --- /dev/null +++ b/integration_test/runner/features/uart_duplex_dma.feature @@ -0,0 +1,14 @@ +@device:stm32f767 +Feature: UART Duplex DMA + Test the UART duplex DMA functionality + + Background: + Given uart duplex dma peripherals are enabled + + Scenario: Send data over UART + When the tested sends UART data + Then the tester sees UART data + + Scenario: Receive data over UART + When the tester sends UART data + Then the tested sees UART data diff --git a/integration_test/tested/CMakeLists.txt b/integration_test/tested/CMakeLists.txt index 701f3dfb..a10bddce 100644 --- a/integration_test/tested/CMakeLists.txt +++ b/integration_test/tested/CMakeLists.txt @@ -3,7 +3,8 @@ emil_build_for(integration_test.tested TARGET_MCU stm32f767) target_sources(integration_test.tested PRIVATE EchoFromTester.hpp - Main.cpp + $<$:MainStm32f767.cpp> + $<$:MainStm32wb55.cpp> Tested.cpp Tested.hpp ) diff --git a/integration_test/tested/EchoFromTester.hpp b/integration_test/tested/EchoFromTester.hpp index 203f41da..f04d8834 100644 --- a/integration_test/tested/EchoFromTester.hpp +++ b/integration_test/tested/EchoFromTester.hpp @@ -2,20 +2,36 @@ #define HAL_ST_INTEGRATION_TEST_ECHO_FROM_TESTER_HPP #include "generated/echo/Testing.pb.hpp" +#include "generated/echo/TracingTesting.pb.hpp" #include "hal_st/stm32fxxx/GpioStm.hpp" -#include "hal_st/stm32fxxx/UartStm.hpp" -#include "services/util/EchoInstantiation.hpp" +#include "hal_st/stm32fxxx/UartStmDuplexDma.hpp" +#include "services/tracer/GlobalTracer.hpp" +#include "services/tracer/TracingEchoInstantiation.hpp" namespace main_ { struct EchoFromTester { + EchoFromTester(hal::DmaStm& dma) + : transmitStream{ dma, hal::DmaChannelId{ 1, 7, 4 } } + , receiveStream{ dma, hal::DmaChannelId{ 1, 0, 4 } } + {} + hal::GpioPinStm echoUartTx{ hal::Port::C, 12 }; hal::GpioPinStm echoUartRx{ hal::Port::D, 2 }; - hal::UartStm echoUart{ 5, echoUartTx, echoUartRx }; - services::MethodSerializerFactory ::ForServices::AndProxies serializerFactory; + hal::DmaStm::TransmitStream transmitStream; + hal::DmaStm::ReceiveStream receiveStream; + hal::UartStmDuplexDma::WithRxBuffer<256> echoUart{ transmitStream, receiveStream, 5, echoUartTx, echoUartRx }; + services::MethodSerializerFactory::ForServices::AndProxies serializerFactory; hal::BufferedSerialCommunicationOnUnbuffered::WithStorage<256> bufferedEchoUart{ echoUart }; - main_::EchoOnSesame<256> echo{ bufferedEchoUart, serializerFactory }; + main_::TracingEchoOnSesame<256> echo{ bufferedEchoUart, serializerFactory, services::GlobalTracer() }; + + testing::TestedTracer testedTracer{ echo.echo }; + testing::TestedObserverTracer testedObserverTracer{ echo.echo }; + testing::GpioTestedTracer gpioTestedTracer{ echo.echo }; + testing::GpioObserverTracer gpioObserverTracer{ echo.echo }; + testing::UartTestedTracer uartTestedTracer{ echo.echo }; + testing::UartObserverTracer uartObserverTracer{ echo.echo }; }; } diff --git a/integration_test/tested/Main.cpp b/integration_test/tested/MainStm32f767.cpp similarity index 58% rename from integration_test/tested/Main.cpp rename to integration_test/tested/MainStm32f767.cpp index a838d82a..83151653 100644 --- a/integration_test/tested/Main.cpp +++ b/integration_test/tested/MainStm32f767.cpp @@ -1,8 +1,10 @@ +#include "hal_st/instantiations/NucleoTracerInfrastructure.hpp" #include "hal_st/instantiations/NucleoUi.hpp" #include "hal_st/instantiations/StmEventInfrastructure.hpp" #include "hal_st/stm32fxxx/DefaultClockNucleoF767ZI.hpp" #include "integration_test/tested/EchoFromTester.hpp" #include "integration_test/tested/Tested.hpp" +#include "services/tracer/GlobalTracer.hpp" #include "services/util/DebugLed.hpp" unsigned int hse_value = 8000000; @@ -13,11 +15,16 @@ int main() ConfigureDefaultClockNucleo767ZI(); static main_::StmEventInfrastructure eventInfrastructure; + static main_::NucleoF767ziTracerInfrastructure tracerInfrastructure; + services::SetGlobalTracerInstance(tracerInfrastructure.tracer); static main_::Nucleo144Ui ui; static services::DebugLed debugLed(ui.ledBlue); - static main_::EchoFromTester echo; - static main_::Tested tested(echo.echo); + static hal::DmaStm dma; + static main_::EchoFromTester echo(dma); + static main_::Tested tested(echo.echo, dma); + + services::GlobalTracer().Trace() << "Starting tested!"; eventInfrastructure.Run(); __builtin_unreachable(); diff --git a/integration_test/tested/MainStm32wb55.cpp b/integration_test/tested/MainStm32wb55.cpp new file mode 100644 index 00000000..b97ce770 --- /dev/null +++ b/integration_test/tested/MainStm32wb55.cpp @@ -0,0 +1,31 @@ +#include "hal_st/instantiations/NucleoTracerInfrastructure.hpp" +#include "hal_st/instantiations/NucleoUi.hpp" +#include "hal_st/instantiations/StmEventInfrastructure.hpp" +#include "hal_st/stm32fxxx/DefaultClockNucleoWB55RG.hpp" +#include "integration_test/tested/EchoFromTester.hpp" +#include "integration_test/tested/Tested.hpp" +#include "services/tracer/GlobalTracer.hpp" +#include "services/util/DebugLed.hpp" + +unsigned int hse_value = 32000000; + +int main() +{ + HAL_Init(); + ConfigureDefaultClockNucleoWB55RG(); + + static main_::StmEventInfrastructure eventInfrastructure; + static main_::NucleoWb55rgTracerInfrastructure tracerInfrastructure; + services::SetGlobalTracerInstance(tracerInfrastructure.tracer); + static main_::Nucleo64WBUi ui; + static services::DebugLed debugLed(ui.ledBlue); + + static hal::DmaStm dma; + static main_::EchoFromTester echo(dma); + static main_::Tested tested(echo.echo, dma); + + services::GlobalTracer().Trace() << "Starting tested!"; + + eventInfrastructure.Run(); + __builtin_unreachable(); +} diff --git a/integration_test/tested/Tested.cpp b/integration_test/tested/Tested.cpp index f0dccc4c..3cc1372e 100644 --- a/integration_test/tested/Tested.cpp +++ b/integration_test/tested/Tested.cpp @@ -6,7 +6,18 @@ namespace main_ : gpioTested(echo, inPin, outPin) {} - Tested::Tested(services::Echo& echo) + UartTested::UartTested(services::Echo& echo) + : uartTested{ echo, bufferedUart } + {} + + UartDuplexDmaTested::UartDuplexDmaTested(services::Echo& echo, hal::DmaStm& dma) + : uartTested{ echo, bufferedUart } + , transmitStream{ dma, hal::DmaChannelId{ 1, 6, 4 } } + , receiveStream{ dma, hal::DmaChannelId{ 1, 5, 4 } } + {} + + Tested::Tested(services::Echo& echo, hal::DmaStm& dma) : tested(echo) + , uartDuplexDmaTested{ tested, testing::Peripheral::uartDuplexDma, dma } {} } diff --git a/integration_test/tested/Tested.hpp b/integration_test/tested/Tested.hpp index 238c7147..a5d297c9 100644 --- a/integration_test/tested/Tested.hpp +++ b/integration_test/tested/Tested.hpp @@ -3,8 +3,11 @@ #include "generated/echo/Testing.pb.hpp" #include "hal_st/stm32fxxx/GpioStm.hpp" +#include "hal_st/stm32fxxx/UartStm.hpp" +#include "hal_st/stm32fxxx/UartStmDuplexDma.hpp" #include "integration_test/logic/Gpio.hpp" #include "integration_test/logic/Tested.hpp" +#include "integration_test/logic/Uart.hpp" namespace main_ { @@ -17,12 +20,38 @@ namespace main_ application::GpioTested gpioTested; }; + struct UartTested + { + UartTested(services::Echo& echo); + + hal::GpioPinStm tx{ hal::Port::D, 5 }; + hal::GpioPinStm rx{ hal::Port::D, 6 }; + hal::UartStm uart{ 2, tx, rx }; + hal::BufferedSerialCommunicationOnUnbuffered::WithStorage<32> bufferedUart{ uart }; + application::UartTested uartTested; + }; + + struct UartDuplexDmaTested + { + UartDuplexDmaTested(services::Echo& echo, hal::DmaStm& dma); + + hal::GpioPinStm tx{ hal::Port::D, 5 }; + hal::GpioPinStm rx{ hal::Port::D, 6 }; + hal::DmaStm::TransmitStream transmitStream; + hal::DmaStm::ReceiveStream receiveStream; + hal::UartStmDuplexDma::WithRxBuffer<32> uart{ transmitStream, receiveStream, 2, tx, rx }; + hal::BufferedSerialCommunicationOnUnbuffered::WithStorage<32> bufferedUart{ uart }; + application::UartTested uartTested; + }; + struct Tested { - Tested(services::Echo& echo); + Tested(services::Echo& echo, hal::DmaStm& dma); application::Tested tested; - application::Perpipheral gpioTested{ tested, testing::Peripheral::gpio }; + application::Peripheral gpioTested{ tested, testing::Peripheral::gpio }; + application::Peripheral uartTested{ tested, testing::Peripheral::uart }; + application::Peripheral uartDuplexDmaTested; }; } diff --git a/integration_test/tester/EchoFromCloud.hpp b/integration_test/tester/EchoFromCloud.hpp index cd025cfd..d0406a12 100644 --- a/integration_test/tester/EchoFromCloud.hpp +++ b/integration_test/tester/EchoFromCloud.hpp @@ -2,21 +2,40 @@ #define HAL_ST_INTEGRATION_TEST_ECHO_FROM_CLOUD_HPP #include "generated/echo/Testing.pb.hpp" -#include "hal_st/stm32fxxx/UartStmDma.hpp" -#include "services/util/EchoInstantiation.hpp" +#include "generated/echo/TracingTesting.pb.hpp" +#include "hal_st/stm32fxxx/UartStmDuplexDma.hpp" +#include "services/tracer/GlobalTracer.hpp" +#include "services/tracer/TracingEchoInstantiation.hpp" namespace main_ { struct EchoFromCloud { + EchoFromCloud(hal::DmaStm& dma, services::Tracer& tracer) + : transmitStream{ dma, hal::DmaChannelId{ 1, 4, 4 } } + , receiveStream{ dma, hal::DmaChannelId{ 1, 2, 4 } } + , redTracer{ services::TracerColoured::red, tracer } + {} + hal::GpioPinStm hostUartTxPin{ hal::Port::C, 10 }; hal::GpioPinStm hostUartRxPin{ hal::Port::C, 11 }; - hal::DmaStm dma; - hal::DmaStm::TransmitStream transmitStream{ dma, hal::DmaChannelId{ 1, 4, 4 } }; - hal::UartStmDma hostUart{ transmitStream, 4, hostUartTxPin, hostUartRxPin }; - services::MethodSerializerFactory ::ForServices::AndProxies serializerFactory; + hal::DmaStm::TransmitStream transmitStream; + hal::DmaStm::ReceiveStream receiveStream; + hal::UartStmDuplexDma::WithRxBuffer<256> hostUart{ transmitStream, receiveStream, 4, hostUartTxPin, hostUartRxPin }; + services::MethodSerializerFactory::ForServices::AndProxies serializerFactory; hal::BufferedSerialCommunicationOnUnbuffered::WithStorage<256> bufferedHostUart{ hostUart }; - main_::EchoOnSesame<256> echo{ bufferedHostUart, serializerFactory }; + services::TracerColoured redTracer; + main_::TracingEchoOnSesame<256> echo{ bufferedHostUart, serializerFactory, redTracer }; + + testing::TesterTracer testerTracer{ echo.echo }; + testing::TestedTracer testedTracer{ echo.echo }; + testing::TestedObserverTracer testedObserverTracer{ echo.echo }; + testing::GpioTesterTracer gpioTesterTracer{ echo.echo }; + testing::GpioTestedTracer gpioTestedTracer{ echo.echo }; + testing::GpioObserverTracer gpioObserverTracer{ echo.echo }; + testing::UartTesterTracer uartTesterTracer{ echo.echo }; + testing::UartTestedTracer uartTestedTracer{ echo.echo }; + testing::UartObserverTracer uartObserverTracer{ echo.echo }; }; } diff --git a/integration_test/tester/ForwardingEchoToTested.cpp b/integration_test/tester/ForwardingEchoToTested.cpp index 6de80c07..1ff4d790 100644 --- a/integration_test/tester/ForwardingEchoToTested.cpp +++ b/integration_test/tester/ForwardingEchoToTested.cpp @@ -2,9 +2,13 @@ namespace main_ { - ForwardingEchoToTested::ForwardingEchoToTested(services::Echo& echo) - : forwardTested(echo, testing::Tested::serviceId, echoToTested.echo) + ForwardingEchoToTested::ForwardingEchoToTested(services::Echo& echo, hal::DmaStm& dma, services::Tracer& tracer) + : echoToTested(dma, tracer) + , forwardTested(echo, testing::Tested::serviceId, echoToTested.echo) + , forwardTestedObserver(echoToTested.echo, testing::TestedObserver::serviceId, echo) , forwardGpioTested(echo, testing::GpioTested::serviceId, echoToTested.echo) , forwardGpioObserver(echoToTested.echo, testing::GpioObserver::serviceId, echo) + , forwardUartTested(echo, testing::UartTested::serviceId, echoToTested.echo) + , forwardUartObserver(echoToTested.echo, testing::UartObserver::serviceId, echo) {} } diff --git a/integration_test/tester/ForwardingEchoToTested.hpp b/integration_test/tester/ForwardingEchoToTested.hpp index 7f933f4a..6feaa84f 100644 --- a/integration_test/tester/ForwardingEchoToTested.hpp +++ b/integration_test/tester/ForwardingEchoToTested.hpp @@ -2,31 +2,52 @@ #define HAL_ST_INTEGRATION_TEST_FORWARDING_ECHO_TO_TESTED_HPP #include "generated/echo/Testing.pb.hpp" +#include "generated/echo/TracingTesting.pb.hpp" #include "hal_st/stm32fxxx/GpioStm.hpp" -#include "hal_st/stm32fxxx/UartStm.hpp" +#include "hal_st/stm32fxxx/UartStmDuplexDma.hpp" #include "protobuf/echo/ServiceForwarder.hpp" -#include "services/util/EchoInstantiation.hpp" +#include "services/tracer/GlobalTracer.hpp" +#include "services/tracer/TracingEchoInstantiation.hpp" namespace main_ { struct EchoToTested { + EchoToTested(hal::DmaStm& dma, services::Tracer& tracer) + : transmitStream{ dma, hal::DmaChannelId{ 1, 7, 4 } } + , receiveStream{ dma, hal::DmaChannelId{ 1, 0, 4 } } + , blueTracer(services::TracerColoured::blue, tracer) + {} + hal::GpioPinStm echoUartTx{ hal::Port::C, 12 }; hal::GpioPinStm echoUartRx{ hal::Port::D, 2 }; - hal::UartStm echoUart{ 5, echoUartTx, echoUartRx }; - services::MethodSerializerFactory ::ForServices::AndProxies serializerFactory; + hal::DmaStm::TransmitStream transmitStream; + hal::DmaStm::ReceiveStream receiveStream; + hal::UartStmDuplexDma::WithRxBuffer<256> echoUart{ transmitStream, receiveStream, 5, echoUartTx, echoUartRx }; + services::MethodSerializerFactory::ForServices::AndProxies serializerFactory; hal::BufferedSerialCommunicationOnUnbuffered::WithStorage<256> bufferedEchoUart{ echoUart }; - main_::EchoOnSesame<256> echo{ bufferedEchoUart, serializerFactory }; + services::TracerColoured blueTracer; + main_::TracingEchoOnSesame<256> echo{ bufferedEchoUart, serializerFactory, blueTracer }; + + testing::TestedTracer testedTracer{ echo.echo }; + testing::TestedObserverTracer testedObserverTracer{ echo.echo }; + testing::GpioTestedTracer gpioTestedTracer{ echo.echo }; + testing::GpioObserverTracer gpioObserverTracer{ echo.echo }; + testing::UartTestedTracer uartTestedTracer{ echo.echo }; + testing::UartObserverTracer uartObserverTracer{ echo.echo }; }; struct ForwardingEchoToTested { - ForwardingEchoToTested(services::Echo& echo); + ForwardingEchoToTested(services::Echo& echo, hal::DmaStm& dma, services::Tracer& tracer); main_::EchoToTested echoToTested; services::ServiceForwarder forwardTested; + services::ServiceForwarder forwardTestedObserver; services::ServiceForwarder forwardGpioTested; services::ServiceForwarder forwardGpioObserver; + services::ServiceForwarder forwardUartTested; + services::ServiceForwarder forwardUartObserver; }; } diff --git a/integration_test/tester/Main.cpp b/integration_test/tester/Main.cpp index cbfe440f..49c578fd 100644 --- a/integration_test/tester/Main.cpp +++ b/integration_test/tester/Main.cpp @@ -1,9 +1,11 @@ +#include "hal_st/instantiations/NucleoTracerInfrastructure.hpp" #include "hal_st/instantiations/NucleoUi.hpp" #include "hal_st/instantiations/StmEventInfrastructure.hpp" #include "hal_st/stm32fxxx/DefaultClockNucleoF767ZI.hpp" #include "integration_test/tester/EchoFromCloud.hpp" #include "integration_test/tester/ForwardingEchoToTested.hpp" #include "integration_test/tester/Tester.hpp" +#include "services/tracer/GlobalTracer.hpp" #include "services/util/DebugLed.hpp" // Tester Tested Function @@ -24,12 +26,18 @@ int main() ConfigureDefaultClockNucleo767ZI(); static main_::StmEventInfrastructure eventInfrastructure; + static main_::NucleoF767ziTracerInfrastructure tracerInfrastructure; + services::TracerColoured tracer{ services::TracerColoured::resetColour, tracerInfrastructure.tracer }; + services::SetGlobalTracerInstance(tracer); static main_::Nucleo144Ui ui; static services::DebugLed debugLed(ui.ledBlue); - static main_::EchoFromCloud echo; - static main_::Tester tester(echo.echo); - static main_::ForwardingEchoToTested forwarder(echo.echo); + static hal::DmaStm dma; + static main_::EchoFromCloud echo(dma, tracerInfrastructure.tracer); + static main_::ForwardingEchoToTested forwarder(echo.echo, dma, tracerInfrastructure.tracer); + static main_::Tester tester(echo.echo, forwarder.echoToTested.echo.echo, dma); + + services::GlobalTracer().Trace() << "Starting tester!"; eventInfrastructure.Run(); __builtin_unreachable(); diff --git a/integration_test/tester/Tester.cpp b/integration_test/tester/Tester.cpp index debc4250..86f6fbb1 100644 --- a/integration_test/tester/Tester.cpp +++ b/integration_test/tester/Tester.cpp @@ -6,7 +6,18 @@ namespace main_ : gpioTester{ echo, inPin, outPin } {} - Tester::Tester(services::Echo& echo) - : tester(echo, nResetTester) + UartTester::UartTester(services::Echo& echo) + : uartTester{ echo, bufferedUart } + {} + + UartDuplexDmaTester::UartDuplexDmaTester(services::Echo& echo, hal::DmaStm& dma) + : uartTester{ echo, bufferedUart } + , transmitStream{ dma, hal::DmaChannelId{ 1, 6, 4 } } + , receiveStream{ dma, hal::DmaChannelId{ 1, 5, 4 } } + {} + + Tester::Tester(services::Echo& echo, services::EchoOnSesame& echoToTested, hal::DmaStm& dma) + : tester(echo, nResetTester, echoToTested) + , uartDuplexDmaTester{ tester, testing::Peripheral::uartDuplexDma, dma } {} } diff --git a/integration_test/tester/Tester.hpp b/integration_test/tester/Tester.hpp index e62ffbce..4f485673 100644 --- a/integration_test/tester/Tester.hpp +++ b/integration_test/tester/Tester.hpp @@ -3,8 +3,11 @@ #include "generated/echo/Testing.pb.hpp" #include "hal_st/stm32fxxx/GpioStm.hpp" +#include "hal_st/stm32fxxx/UartStm.hpp" +#include "hal_st/stm32fxxx/UartStmDuplexDma.hpp" #include "integration_test/logic/Gpio.hpp" #include "integration_test/logic/Tester.hpp" +#include "integration_test/logic/Uart.hpp" namespace main_ { @@ -17,13 +20,39 @@ namespace main_ application::GpioTester gpioTester; }; + struct UartTester + { + UartTester(services::Echo& echo); + + hal::GpioPinStm tx{ hal::Port::D, 5 }; + hal::GpioPinStm rx{ hal::Port::D, 6 }; + hal::UartStm uart{ 2, tx, rx }; + hal::BufferedSerialCommunicationOnUnbuffered::WithStorage<32> bufferedUart{ uart }; + application::UartTester uartTester; + }; + + struct UartDuplexDmaTester + { + UartDuplexDmaTester(services::Echo& echo, hal::DmaStm& dma); + + hal::GpioPinStm tx{ hal::Port::D, 5 }; + hal::GpioPinStm rx{ hal::Port::D, 6 }; + hal::DmaStm::TransmitStream transmitStream; + hal::DmaStm::ReceiveStream receiveStream; + hal::UartStmDuplexDma::WithRxBuffer<32> uart{ transmitStream, receiveStream, 2, tx, rx }; + hal::BufferedSerialCommunicationOnUnbuffered::WithStorage<32> bufferedUart{ uart }; + application::UartTester uartTester; + }; + struct Tester { - Tester(services::Echo& echo); + Tester(services::Echo& echo, services::EchoOnSesame& echoToTested, hal::DmaStm& dma); hal::GpioPinStm nResetTester{ hal::Port::E, 6, hal::Drive::OpenDrain }; application::Tester tester; - application::Perpipheral gpioTester{ tester, testing::Peripheral::gpio }; + application::Peripheral gpioTester{ tester, testing::Peripheral::gpio }; + application::Peripheral uartTester{ tester, testing::Peripheral::uart }; + application::Peripheral uartDuplexDmaTester; }; } diff --git a/st/hal_driver.cmake b/st/hal_driver.cmake index 020e6769..40cccb80 100644 --- a/st/hal_driver.cmake +++ b/st/hal_driver.cmake @@ -22,6 +22,10 @@ function(add_hal_driver target_name hal_driver cmsis) $<$>:USE_FULL_ASSERT=1> ) + target_compile_options(${target_name} PUBLIC + $<$:-Wno-volatile> + ) + # Assembler does not understand -Werror set_target_properties(${target_name} PROPERTIES COMPILE_WARNING_AS_ERROR Off)