From c779c4bcf7f11c24621d3cd65ea02d80991ad711 Mon Sep 17 00:00:00 2001 From: Jerome Hue Date: Mon, 22 Apr 2024 13:16:31 +0000 Subject: [PATCH 01/12] Mock Fram Code --- .gitignore | 1 + CMakeLists.txt | 2 +- Sts1CobcSw/CMakeLists.txt | 2 +- Sts1CobcSw/Periphery/CMakeLists.txt | 2 + Sts1CobcSw/Periphery/FramMock.cpp | 121 ++++++++++++++++++++++++++++ Sts1CobcSw/Periphery/FramMock.hpp | 41 ++++++++++ Tests/UnitTests/CMakeLists.txt | 5 ++ Tests/UnitTests/Fram.test.cpp | 110 +++++++++++++++++++++++++ 8 files changed, 282 insertions(+), 2 deletions(-) create mode 100644 Sts1CobcSw/Periphery/FramMock.cpp create mode 100644 Sts1CobcSw/Periphery/FramMock.hpp create mode 100644 Tests/UnitTests/Fram.test.cpp diff --git a/.gitignore b/.gitignore index 15b08277..2aa0b375 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ prefix/ CMakeLists.txt.user CMakeUserPresets.json compile_commands.json +FramMock.bin diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e978245..c1f78323 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,11 +29,11 @@ add_library(Sts1CobcSw_FileSystem STATIC) add_library(Sts1CobcSw_Outcome INTERFACE) add_library(Sts1CobcSw_Serial INTERFACE) add_library(Sts1CobcSw_Utility STATIC) +add_library(Sts1CobcSw_Periphery STATIC) add_program(HelloDummy) # add_program(Heartbeat) if(CMAKE_SYSTEM_NAME STREQUAL Generic) - add_library(Sts1CobcSw_Periphery STATIC) add_library(Sts1CobcSw_Hal STATIC) add_program(CobcSw) endif() diff --git a/Sts1CobcSw/CMakeLists.txt b/Sts1CobcSw/CMakeLists.txt index e19899d9..435ca32c 100644 --- a/Sts1CobcSw/CMakeLists.txt +++ b/Sts1CobcSw/CMakeLists.txt @@ -1,7 +1,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL Generic) - add_subdirectory(Periphery) add_subdirectory(Hal) endif() +add_subdirectory(Periphery) add_subdirectory(Edu) add_subdirectory(FileSystem) add_subdirectory(Outcome) diff --git a/Sts1CobcSw/Periphery/CMakeLists.txt b/Sts1CobcSw/Periphery/CMakeLists.txt index e0140735..deb48f95 100644 --- a/Sts1CobcSw/Periphery/CMakeLists.txt +++ b/Sts1CobcSw/Periphery/CMakeLists.txt @@ -7,4 +7,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL Generic) ) target_link_libraries(Sts1CobcSw_Periphery PRIVATE Sts1CobcSw_Utility) target_link_libraries(Sts1CobcSw_Periphery PUBLIC Sts1CobcSw_Hal) +else() + target_sources(Sts1CobcSw_Periphery PRIVATE FramMock.cpp) endif() diff --git a/Sts1CobcSw/Periphery/FramMock.cpp b/Sts1CobcSw/Periphery/FramMock.cpp new file mode 100644 index 00000000..532201b6 --- /dev/null +++ b/Sts1CobcSw/Periphery/FramMock.cpp @@ -0,0 +1,121 @@ +#include + +#include +#include +#include +#include +#include + + +namespace sts1cobcsw::fram +{ + +auto ramSimulation = std::array{}; +MockMode mockDevice = MockMode::ram; +constexpr auto mockFilename = "FramMock.bin"; + +auto FramMockMode(MockMode mockMode) -> void +{ + mockDevice = mockMode; +} + +// Default do functions, doing nothing +auto DoInitializeDefault() -> void +{ +} + +auto DoReadDeviceIdDefault() -> DeviceId +{ + return DeviceId{}; +} + +auto DoActualBaudRateDefault() -> int32_t +{ + return 0; +} + + +auto doInitialize = DoInitializeDefault; +auto doReadDeviceId = DoReadDeviceIdDefault; +auto doActualBaudRate = DoActualBaudRateDefault; + + +auto SetDoInitialize(void (*doInitializeFunction)()) -> void +{ + doInitialize = doInitializeFunction; +} + +auto SetDoReadDeviceId(DeviceId (*doReadDeviceIdFunction)()) -> void +{ + doReadDeviceId = doReadDeviceIdFunction; +} + +void SetDoActualBaudRate(int32_t (*doActualBaudRateFunction)()) +{ + doActualBaudRate = doActualBaudRateFunction; +} + + +auto Initialize() -> void +{ + return doInitialize(); +} + +auto ReadDeviceId() -> DeviceId +{ + return doReadDeviceId(); +} + +auto ActualBaudRate() -> int32_t +{ + return doActualBaudRate(); +} + + +namespace internal +{ +auto WriteTo(Address address, void const * data, std::size_t nBytes) -> void +{ + if(mockDevice == MockMode::file) + { + std::ofstream file(mockFilename, std::ios::binary | std::ios_base::ate); + if(not file) + { + std::cerr << "Failed to open file " << mockFilename << " for writing." << '\n'; + return; + } + + file.seekp(address); + file.write(static_cast(data), static_cast(nBytes)); + file.close(); + } + else + { + // FIXME: Fix pointer arithmetic + std::memcpy(ramSimulation.data() + address, data, nBytes); + } +} + +auto ReadFrom(Address address, void * data, std::size_t nBytes) -> void +{ + if(mockDevice == MockMode::file) + { + std::ifstream file(mockFilename, std::ios::binary); + if(not file) + { + std::cerr << "Failed to open file " << mockFilename << " for reading." << '\n'; + return; + } + + file.clear(); + file.seekg(address); + file.read(static_cast(data), static_cast(nBytes)); + file.close(); + } + else + { + std::memcpy(data, ramSimulation.data() + address, nBytes); + } +} +} +} diff --git a/Sts1CobcSw/Periphery/FramMock.hpp b/Sts1CobcSw/Periphery/FramMock.hpp new file mode 100644 index 00000000..0af1c733 --- /dev/null +++ b/Sts1CobcSw/Periphery/FramMock.hpp @@ -0,0 +1,41 @@ +#pragma once + + +#include + + +namespace sts1cobcsw::fram +{ +auto SetDoInitialize(void (*doInitializeFunction)()) -> void; +auto SetDoReadDeviceId(DeviceId (*doReadDeviceIdFunction)()) -> void; +auto SetDoActualBaudRate(int32_t (*doActualBaudRateFunction)()) -> void; + + +// Default "do" functions that do nothing, used to initialized function pointers +auto DoInitializeDefault() -> void; +auto DoReadDeviceIdDefault() -> DeviceId; +auto DoActualBaudRateDefault() -> int32_t; + + +enum class MockMode +{ + ram, + file +}; + +auto FramMockMode(MockMode mockMode) -> void; + +namespace ram +{ +auto DoInitialize() -> void; +auto DoReadDeviceId() -> DeviceId; +auto DoActualBaudRate() -> int32_t; +} + +namespace file +{ +auto DoInitialize() -> void; +auto DoReadDeviceId() -> DeviceId; +auto DoActualBaudRate() -> int32_t; +} +} diff --git a/Tests/UnitTests/CMakeLists.txt b/Tests/UnitTests/CMakeLists.txt index a745cdea..4651a9a4 100644 --- a/Tests/UnitTests/CMakeLists.txt +++ b/Tests/UnitTests/CMakeLists.txt @@ -12,6 +12,11 @@ target_link_libraries(Sts1CobcSwTests_LfsRam PRIVATE Catch2::Catch2WithMain Sts1 add_program(Outcome Outcome.test.cpp) target_link_libraries(Sts1CobcSwTests_Outcome PRIVATE Catch2::Catch2WithMain) +add_program(Fram Fram.test.cpp) +target_link_libraries( + Sts1CobcSwTests_Fram PRIVATE Catch2::Catch2WithMain Sts1CobcSw_Periphery Sts1CobcSw_Serial +) + # TODO: Fix the problem with two main()s, one from Rodos one from Catch, somehow if(FALSE) add_program(PersistentState PersistentState.test.cpp) diff --git a/Tests/UnitTests/Fram.test.cpp b/Tests/UnitTests/Fram.test.cpp new file mode 100644 index 00000000..b976793a --- /dev/null +++ b/Tests/UnitTests/Fram.test.cpp @@ -0,0 +1,110 @@ +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace fram = sts1cobcsw::fram; + + +using sts1cobcsw::Byte; +using sts1cobcsw::Span; +using sts1cobcsw::operator""_b; // NOLINT(misc-unused-using-decls) + + +constexpr auto nAddressBits = 20U; +size_t const testDataSize = 11 * 1024; // 11 KiB +auto testData = std::array{}; +auto readData = std::array{}; + + +auto WriteAndReadTestData(sts1cobcsw::fram::Address const & address) -> void; +auto ReadCorrectDeviceId() -> fram::DeviceId; + +TEST_CASE("Fram mock using ram") +{ + fram::FramMockMode(fram::MockMode::ram); + + std::mt19937 randomEngine(std::random_device{}()); + std::uniform_int_distribution gen(0, (1U << nAddressBits) - 1); + fram::Address const address = gen(randomEngine); + + WriteAndReadTestData(address); + std::generate( + testData.begin(), testData.end(), [&]() { return static_cast(randomEngine()); }); + WriteAndReadTestData(address); +<<<<<<< HEAD +======= + + auto deviceId = fram::ReadDeviceId(); + constexpr auto correctDeviceId = + std::to_array({0x03_b, 0x2E_b, 0xC2_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b}); + REQUIRE(deviceId != correctDeviceId); + fram::SetDoReadDeviceId(ReadCorrectDeviceId); + deviceId = fram::ReadDeviceId(); + REQUIRE(deviceId == correctDeviceId); +>>>>>>> 465f578 (Fix more stuff) +} + +TEST_CASE("Fram mock using file") +{ + fram::FramMockMode(fram::MockMode::file); + + std::mt19937 randomEngine(std::random_device{}()); + std::uniform_int_distribution addressGenerator(0, ((1U << nAddressBits) - 1)); + fram::Address const address = addressGenerator(randomEngine); + + WriteAndReadTestData(address); + std::generate( + testData.begin(), testData.end(), [&]() { return static_cast(randomEngine()); }); + WriteAndReadTestData(address); +} + +auto WriteAndReadTestData(fram::Address const & address) -> void +{ + auto nBytesToPrint = 10U; + + std::printf("Writing %d bytes to address 0x%08x ...\n", + static_cast(testDataSize), + static_cast(address)); + fram::WriteTo(address, Span(testData)); +<<<<<<< HEAD + std::printf("Reading n bytes from address ...\n"); +======= + + std::printf("Reading %d bytes from address 0x%08x ...\n", + static_cast(testDataSize), + static_cast(address)); +>>>>>>> 465f578 (Fix more stuff) + fram::ReadFrom(address, Span(&readData)); + + std::printf("Comparing first %d written and read bytes:\n", nBytesToPrint); + std::printf(" "); + for(auto byte : Span(testData).first(nBytesToPrint)) + { + std::printf("0x%02x ", static_cast(byte)); + } + std::printf("\n "); + for(auto byte : Span(readData).first(nBytesToPrint)) + { + std::printf("0x%02x ", static_cast(byte)); + } + std::printf("\n"); + + REQUIRE(readData == testData); +} + +auto ReadCorrectDeviceId() -> fram::DeviceId +{ + return std::to_array({0x03_b, 0x2E_b, 0xC2_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b}); +} \ No newline at end of file From 205d037456d43be5646b71504d108f5eb1d8b8f6 Mon Sep 17 00:00:00 2001 From: Jerome Hue Date: Wed, 1 May 2024 20:08:41 +0000 Subject: [PATCH 02/12] Update devcontainer version to 1.6.1 --- .devcontainer/devcontainer.json | 2 +- Sts1CobcSw/Periphery/FramMock.cpp | 10 +++++----- Sts1CobcSw/Periphery/FramMock.hpp | 2 ++ Tests/UnitTests/Fram.test.cpp | 7 ------- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 287fea6a..7eb20a9f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,4 +1,4 @@ { "name": "STS1 COBC Full", - "image": "tuwienspaceteam/sts1-cobc:1.6.0" + "image": "tuwienspaceteam/sts1-cobc:1.6.1" } diff --git a/Sts1CobcSw/Periphery/FramMock.cpp b/Sts1CobcSw/Periphery/FramMock.cpp index 532201b6..2ac7f549 100644 --- a/Sts1CobcSw/Periphery/FramMock.cpp +++ b/Sts1CobcSw/Periphery/FramMock.cpp @@ -1,16 +1,16 @@ #include +#include #include -#include -#include +#include // IWYU pragma: keep #include -#include namespace sts1cobcsw::fram { -auto ramSimulation = std::array{}; +constexpr auto framSize = (1U << 20U); +auto ramSimulation = std::array{}; MockMode mockDevice = MockMode::ram; constexpr auto mockFilename = "FramMock.bin"; @@ -91,7 +91,7 @@ auto WriteTo(Address address, void const * data, std::size_t nBytes) -> void } else { - // FIXME: Fix pointer arithmetic + // FIXME: Fix pointer arithmetic and out of bounds access std::memcpy(ramSimulation.data() + address, data, nBytes); } } diff --git a/Sts1CobcSw/Periphery/FramMock.hpp b/Sts1CobcSw/Periphery/FramMock.hpp index 0af1c733..349ac7e0 100644 --- a/Sts1CobcSw/Periphery/FramMock.hpp +++ b/Sts1CobcSw/Periphery/FramMock.hpp @@ -3,6 +3,8 @@ #include +#include + namespace sts1cobcsw::fram { diff --git a/Tests/UnitTests/Fram.test.cpp b/Tests/UnitTests/Fram.test.cpp index b976793a..a01ec93b 100644 --- a/Tests/UnitTests/Fram.test.cpp +++ b/Tests/UnitTests/Fram.test.cpp @@ -43,8 +43,6 @@ TEST_CASE("Fram mock using ram") std::generate( testData.begin(), testData.end(), [&]() { return static_cast(randomEngine()); }); WriteAndReadTestData(address); -<<<<<<< HEAD -======= auto deviceId = fram::ReadDeviceId(); constexpr auto correctDeviceId = @@ -53,7 +51,6 @@ TEST_CASE("Fram mock using ram") fram::SetDoReadDeviceId(ReadCorrectDeviceId); deviceId = fram::ReadDeviceId(); REQUIRE(deviceId == correctDeviceId); ->>>>>>> 465f578 (Fix more stuff) } TEST_CASE("Fram mock using file") @@ -78,14 +75,10 @@ auto WriteAndReadTestData(fram::Address const & address) -> void static_cast(testDataSize), static_cast(address)); fram::WriteTo(address, Span(testData)); -<<<<<<< HEAD - std::printf("Reading n bytes from address ...\n"); -======= std::printf("Reading %d bytes from address 0x%08x ...\n", static_cast(testDataSize), static_cast(address)); ->>>>>>> 465f578 (Fix more stuff) fram::ReadFrom(address, Span(&readData)); std::printf("Comparing first %d written and read bytes:\n", nBytesToPrint); From 97dd61187be4816af76359d816af7be419f501ee Mon Sep 17 00:00:00 2001 From: Patrick Kappl Date: Mon, 6 May 2024 18:30:20 +0000 Subject: [PATCH 03/12] Make cosmetic changes and add TODO comments --- Sts1CobcSw/Periphery/FramMock.cpp | 56 +++++++++++++++++++------------ Sts1CobcSw/Periphery/FramMock.hpp | 29 +++++++++------- 2 files changed, 52 insertions(+), 33 deletions(-) diff --git a/Sts1CobcSw/Periphery/FramMock.cpp b/Sts1CobcSw/Periphery/FramMock.cpp index 2ac7f549..142ac8a6 100644 --- a/Sts1CobcSw/Periphery/FramMock.cpp +++ b/Sts1CobcSw/Periphery/FramMock.cpp @@ -8,72 +8,84 @@ namespace sts1cobcsw::fram { - constexpr auto framSize = (1U << 20U); auto ramSimulation = std::array{}; MockMode mockDevice = MockMode::ram; constexpr auto mockFilename = "FramMock.bin"; -auto FramMockMode(MockMode mockMode) -> void -{ - mockDevice = mockMode; -} +auto doInitialize = DoInitializeDefault; +auto doReadDeviceId = DoReadDeviceIdDefault; +auto doActualBaudRate = DoActualBaudRateDefault; -// Default do functions, doing nothing -auto DoInitializeDefault() -> void + +// --- Mocked functions --- + +auto Initialize() -> void { + return doInitialize(); } -auto DoReadDeviceIdDefault() -> DeviceId + +auto ReadDeviceId() -> DeviceId { - return DeviceId{}; + return doReadDeviceId(); } -auto DoActualBaudRateDefault() -> int32_t + +auto ActualBaudRate() -> int32_t { - return 0; + return doActualBaudRate(); } -auto doInitialize = DoInitializeDefault; -auto doReadDeviceId = DoReadDeviceIdDefault; -auto doActualBaudRate = DoActualBaudRateDefault; - +// --- Set functions --- auto SetDoInitialize(void (*doInitializeFunction)()) -> void { doInitialize = doInitializeFunction; } + auto SetDoReadDeviceId(DeviceId (*doReadDeviceIdFunction)()) -> void { doReadDeviceId = doReadDeviceIdFunction; } + void SetDoActualBaudRate(int32_t (*doActualBaudRateFunction)()) { doActualBaudRate = doActualBaudRateFunction; } -auto Initialize() -> void +// --- Default do functions, doing nothing --- + +auto DoInitializeDefault() -> void { - return doInitialize(); } -auto ReadDeviceId() -> DeviceId + +auto DoReadDeviceIdDefault() -> DeviceId { - return doReadDeviceId(); + return DeviceId{}; } -auto ActualBaudRate() -> int32_t + +auto DoActualBaudRateDefault() -> int32_t { - return doActualBaudRate(); + return 0; +} + + +auto FramMockMode(MockMode mockMode) -> void +{ + mockDevice = mockMode; } namespace internal { +// TODO: This must also forward to a do function which can be set with a SetDoWriteTo function auto WriteTo(Address address, void const * data, std::size_t nBytes) -> void { if(mockDevice == MockMode::file) @@ -96,6 +108,8 @@ auto WriteTo(Address address, void const * data, std::size_t nBytes) -> void } } + +// TODO: This must also forward to a do function which can be set with a SetDoReadFrom function auto ReadFrom(Address address, void * data, std::size_t nBytes) -> void { if(mockDevice == MockMode::file) diff --git a/Sts1CobcSw/Periphery/FramMock.hpp b/Sts1CobcSw/Periphery/FramMock.hpp index 349ac7e0..73abbba7 100644 --- a/Sts1CobcSw/Periphery/FramMock.hpp +++ b/Sts1CobcSw/Periphery/FramMock.hpp @@ -8,36 +8,41 @@ namespace sts1cobcsw::fram { +enum class MockMode +{ + ram, + file +}; + + +// TODO: Add SetDoWriteTo and SetDoReadFrom functions auto SetDoInitialize(void (*doInitializeFunction)()) -> void; auto SetDoReadDeviceId(DeviceId (*doReadDeviceIdFunction)()) -> void; -auto SetDoActualBaudRate(int32_t (*doActualBaudRateFunction)()) -> void; - +auto SetDoActualBaudRate(std::int32_t (*doActualBaudRateFunction)()) -> void; +// TODO: Move to namespace "default" // Default "do" functions that do nothing, used to initialized function pointers auto DoInitializeDefault() -> void; auto DoReadDeviceIdDefault() -> DeviceId; -auto DoActualBaudRateDefault() -> int32_t; - - -enum class MockMode -{ - ram, - file -}; +auto DoActualBaudRateDefault() -> std::int32_t; +// TODO: Remove this auto FramMockMode(MockMode mockMode) -> void; +// TODO: Implement ram::do functions namespace ram { auto DoInitialize() -> void; auto DoReadDeviceId() -> DeviceId; -auto DoActualBaudRate() -> int32_t; +auto DoActualBaudRate() -> std::int32_t; } + +// TODO: Since this isn't fully implemented yet, remove it. The RAM mock should be enough. namespace file { auto DoInitialize() -> void; auto DoReadDeviceId() -> DeviceId; -auto DoActualBaudRate() -> int32_t; +auto DoActualBaudRate() -> std::int32_t; } } From bfa8651144c045b28cc477f45b65db97a2d30144 Mon Sep 17 00:00:00 2001 From: Patrick Kappl Date: Fri, 10 May 2024 09:49:15 +0000 Subject: [PATCH 04/12] Move default do funtions for FRAM to namespace "empty" --- Sts1CobcSw/Periphery/FramMock.cpp | 18 +++++++++++------- Sts1CobcSw/Periphery/FramMock.hpp | 12 +++++++----- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/Sts1CobcSw/Periphery/FramMock.cpp b/Sts1CobcSw/Periphery/FramMock.cpp index 142ac8a6..02e99ca0 100644 --- a/Sts1CobcSw/Periphery/FramMock.cpp +++ b/Sts1CobcSw/Periphery/FramMock.cpp @@ -13,9 +13,9 @@ auto ramSimulation = std::array{}; MockMode mockDevice = MockMode::ram; constexpr auto mockFilename = "FramMock.bin"; -auto doInitialize = DoInitializeDefault; -auto doReadDeviceId = DoReadDeviceIdDefault; -auto doActualBaudRate = DoActualBaudRateDefault; +auto doInitialize = empty::DoInitialize; +auto doReadDeviceId = empty::DoReadDeviceId; +auto doActualBaudRate = empty::DoActualBaudRate; // --- Mocked functions --- @@ -58,23 +58,26 @@ void SetDoActualBaudRate(int32_t (*doActualBaudRateFunction)()) } -// --- Default do functions, doing nothing --- +// --- Predefined do functions --- -auto DoInitializeDefault() -> void +namespace empty +{ +auto DoInitialize() -> void { } -auto DoReadDeviceIdDefault() -> DeviceId +auto DoReadDeviceId() -> DeviceId { return DeviceId{}; } -auto DoActualBaudRateDefault() -> int32_t +auto DoActualBaudRate() -> int32_t { return 0; } +} auto FramMockMode(MockMode mockMode) -> void @@ -83,6 +86,7 @@ auto FramMockMode(MockMode mockMode) -> void } + namespace internal { // TODO: This must also forward to a do function which can be set with a SetDoWriteTo function diff --git a/Sts1CobcSw/Periphery/FramMock.hpp b/Sts1CobcSw/Periphery/FramMock.hpp index 73abbba7..b6de219d 100644 --- a/Sts1CobcSw/Periphery/FramMock.hpp +++ b/Sts1CobcSw/Periphery/FramMock.hpp @@ -20,11 +20,13 @@ auto SetDoInitialize(void (*doInitializeFunction)()) -> void; auto SetDoReadDeviceId(DeviceId (*doReadDeviceIdFunction)()) -> void; auto SetDoActualBaudRate(std::int32_t (*doActualBaudRateFunction)()) -> void; -// TODO: Move to namespace "default" -// Default "do" functions that do nothing, used to initialized function pointers -auto DoInitializeDefault() -> void; -auto DoReadDeviceIdDefault() -> DeviceId; -auto DoActualBaudRateDefault() -> std::int32_t; +namespace empty +{ + // Empty do functions that do nothing, used to initialized function pointers + auto DoInitialize()->void; + auto DoReadDeviceId()->DeviceId; + auto DoActualBaudRate()->std::int32_t; +} // TODO: Remove this auto FramMockMode(MockMode mockMode) -> void; From bf0fe9bf549430121c186d56d5743394437d947e Mon Sep 17 00:00:00 2001 From: Patrick Kappl Date: Fri, 10 May 2024 09:50:55 +0000 Subject: [PATCH 05/12] Link missing dependency of FRAM unit test --- Tests/UnitTests/CMakeLists.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Tests/UnitTests/CMakeLists.txt b/Tests/UnitTests/CMakeLists.txt index 4651a9a4..9b5f28e9 100644 --- a/Tests/UnitTests/CMakeLists.txt +++ b/Tests/UnitTests/CMakeLists.txt @@ -5,6 +5,12 @@ target_link_libraries(Sts1CobcSwTests_Dummy PRIVATE Catch2::Catch2WithMain Sts1C add_program(FlatArray FlatArray.test.cpp) target_link_libraries(Sts1CobcSwTests_FlatArray PRIVATE Catch2::Catch2WithMain Sts1CobcSw_Utility) +add_program(Fram Fram.test.cpp) +target_link_libraries( + Sts1CobcSwTests_Fram PRIVATE Catch2::Catch2WithMain Sts1CobcSw_Periphery Sts1CobcSw_Serial + Sts1CobcSw_Utility +) + # TODO: Enable again once problem with segmentation violation on CI is fixed add_program(LfsRam LfsRam.test.cpp) target_link_libraries(Sts1CobcSwTests_LfsRam PRIVATE Catch2::Catch2WithMain Sts1CobcSw_FileSystem) @@ -12,11 +18,6 @@ target_link_libraries(Sts1CobcSwTests_LfsRam PRIVATE Catch2::Catch2WithMain Sts1 add_program(Outcome Outcome.test.cpp) target_link_libraries(Sts1CobcSwTests_Outcome PRIVATE Catch2::Catch2WithMain) -add_program(Fram Fram.test.cpp) -target_link_libraries( - Sts1CobcSwTests_Fram PRIVATE Catch2::Catch2WithMain Sts1CobcSw_Periphery Sts1CobcSw_Serial -) - # TODO: Fix the problem with two main()s, one from Rodos one from Catch, somehow if(FALSE) add_program(PersistentState PersistentState.test.cpp) From 3bcc5a6b9c247b93b751415a3b29a4cde4bb7f10 Mon Sep 17 00:00:00 2001 From: Patrick Kappl Date: Fri, 10 May 2024 10:31:49 +0000 Subject: [PATCH 06/12] Add timeout to write and read functions of FRAM mock --- Sts1CobcSw/Periphery/FramMock.cpp | 10 ++++++++-- Tests/UnitTests/Fram.test.cpp | 11 ++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Sts1CobcSw/Periphery/FramMock.cpp b/Sts1CobcSw/Periphery/FramMock.cpp index 02e99ca0..140fd88f 100644 --- a/Sts1CobcSw/Periphery/FramMock.cpp +++ b/Sts1CobcSw/Periphery/FramMock.cpp @@ -90,7 +90,10 @@ auto FramMockMode(MockMode mockMode) -> void namespace internal { // TODO: This must also forward to a do function which can be set with a SetDoWriteTo function -auto WriteTo(Address address, void const * data, std::size_t nBytes) -> void +auto WriteTo(Address address, + void const * data, + std::size_t nBytes, + [[maybe_unused]] std::int64_t timeout) -> void { if(mockDevice == MockMode::file) { @@ -114,7 +117,10 @@ auto WriteTo(Address address, void const * data, std::size_t nBytes) -> void // TODO: This must also forward to a do function which can be set with a SetDoReadFrom function -auto ReadFrom(Address address, void * data, std::size_t nBytes) -> void +auto ReadFrom(Address address, + void * data, + std::size_t nBytes, + [[maybe_unused]] std::int64_t timeout) -> void { if(mockDevice == MockMode::file) { diff --git a/Tests/UnitTests/Fram.test.cpp b/Tests/UnitTests/Fram.test.cpp index a01ec93b..75adf25b 100644 --- a/Tests/UnitTests/Fram.test.cpp +++ b/Tests/UnitTests/Fram.test.cpp @@ -22,6 +22,7 @@ using sts1cobcsw::Span; using sts1cobcsw::operator""_b; // NOLINT(misc-unused-using-decls) +constexpr auto spiTimeout = 1; // in ms constexpr auto nAddressBits = 20U; size_t const testDataSize = 11 * 1024; // 11 KiB auto testData = std::array{}; @@ -31,6 +32,7 @@ auto readData = std::array{}; auto WriteAndReadTestData(sts1cobcsw::fram::Address const & address) -> void; auto ReadCorrectDeviceId() -> fram::DeviceId; + TEST_CASE("Fram mock using ram") { fram::FramMockMode(fram::MockMode::ram); @@ -53,6 +55,7 @@ TEST_CASE("Fram mock using ram") REQUIRE(deviceId == correctDeviceId); } + TEST_CASE("Fram mock using file") { fram::FramMockMode(fram::MockMode::file); @@ -67,6 +70,7 @@ TEST_CASE("Fram mock using file") WriteAndReadTestData(address); } + auto WriteAndReadTestData(fram::Address const & address) -> void { auto nBytesToPrint = 10U; @@ -74,12 +78,12 @@ auto WriteAndReadTestData(fram::Address const & address) -> void std::printf("Writing %d bytes to address 0x%08x ...\n", static_cast(testDataSize), static_cast(address)); - fram::WriteTo(address, Span(testData)); + fram::WriteTo(address, Span(testData), spiTimeout); std::printf("Reading %d bytes from address 0x%08x ...\n", static_cast(testDataSize), static_cast(address)); - fram::ReadFrom(address, Span(&readData)); + fram::ReadFrom(address, Span(&readData), spiTimeout); std::printf("Comparing first %d written and read bytes:\n", nBytesToPrint); std::printf(" "); @@ -97,7 +101,8 @@ auto WriteAndReadTestData(fram::Address const & address) -> void REQUIRE(readData == testData); } + auto ReadCorrectDeviceId() -> fram::DeviceId { return std::to_array({0x03_b, 0x2E_b, 0xC2_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b}); -} \ No newline at end of file +} From 67c6ab4dcb7dd47f90f316610a5c444978987f54 Mon Sep 17 00:00:00 2001 From: Patrick Kappl Date: Fri, 10 May 2024 10:40:46 +0000 Subject: [PATCH 07/12] Add missing std:: before int32_t et al. --- Sts1CobcSw/Hal/Spi.cpp | 2 +- Sts1CobcSw/Hal/Spi.hpp | 2 +- Sts1CobcSw/Periphery/Flash.cpp | 2 +- Sts1CobcSw/Periphery/Flash.hpp | 2 +- Sts1CobcSw/Periphery/FramMock.cpp | 6 +++--- Sts1CobcSw/Periphery/Rf.cpp | 4 ++-- Sts1CobcSw/Utility/Time.cpp | 10 +++++----- Tests/HardwareTests/Fram.test.cpp | 2 +- Tests/UnitTests/Fram.test.cpp | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Sts1CobcSw/Hal/Spi.cpp b/Sts1CobcSw/Hal/Spi.cpp index 21f069fc..501c7532 100644 --- a/Sts1CobcSw/Hal/Spi.cpp +++ b/Sts1CobcSw/Hal/Spi.cpp @@ -33,7 +33,7 @@ auto Spi::TransferEnd() const -> std::int64_t } -auto Spi::BaudRate() -> int32_t +auto Spi::BaudRate() -> std::int32_t { return this->spi_.status(RODOS::SPI_STATUS_BAUDRATE); } diff --git a/Sts1CobcSw/Hal/Spi.hpp b/Sts1CobcSw/Hal/Spi.hpp index d1d3b337..83946c68 100644 --- a/Sts1CobcSw/Hal/Spi.hpp +++ b/Sts1CobcSw/Hal/Spi.hpp @@ -28,7 +28,7 @@ class Spi friend auto ReadFrom(Spi * spi, std::span data, std::int64_t timeout) -> void; auto TransferEnd() const -> std::int64_t; - auto BaudRate() -> int32_t; + auto BaudRate() -> std::int32_t; private: diff --git a/Sts1CobcSw/Periphery/Flash.cpp b/Sts1CobcSw/Periphery/Flash.cpp index b9c25775..a06d7e59 100644 --- a/Sts1CobcSw/Periphery/Flash.cpp +++ b/Sts1CobcSw/Periphery/Flash.cpp @@ -182,7 +182,7 @@ auto WaitWhileBusy(std::int64_t timeout) -> Result } -auto ActualBaudRate() -> int32_t +auto ActualBaudRate() -> std::int32_t { return spi.BaudRate(); } diff --git a/Sts1CobcSw/Periphery/Flash.hpp b/Sts1CobcSw/Periphery/Flash.hpp index 373038cf..ceeab3eb 100644 --- a/Sts1CobcSw/Periphery/Flash.hpp +++ b/Sts1CobcSw/Periphery/Flash.hpp @@ -55,5 +55,5 @@ auto Initialize() -> void; auto ProgramPage(std::uint32_t address, PageSpan data) -> void; auto EraseSector(std::uint32_t address) -> void; [[nodiscard]] auto WaitWhileBusy(std::int64_t timeout) -> Result; -auto ActualBaudRate() -> int32_t; +auto ActualBaudRate() -> std::int32_t; } diff --git a/Sts1CobcSw/Periphery/FramMock.cpp b/Sts1CobcSw/Periphery/FramMock.cpp index 140fd88f..cf5995fe 100644 --- a/Sts1CobcSw/Periphery/FramMock.cpp +++ b/Sts1CobcSw/Periphery/FramMock.cpp @@ -32,7 +32,7 @@ auto ReadDeviceId() -> DeviceId } -auto ActualBaudRate() -> int32_t +auto ActualBaudRate() -> std::int32_t { return doActualBaudRate(); } @@ -52,7 +52,7 @@ auto SetDoReadDeviceId(DeviceId (*doReadDeviceIdFunction)()) -> void } -void SetDoActualBaudRate(int32_t (*doActualBaudRateFunction)()) +void SetDoActualBaudRate(std::int32_t (*doActualBaudRateFunction)()) { doActualBaudRate = doActualBaudRateFunction; } @@ -73,7 +73,7 @@ auto DoReadDeviceId() -> DeviceId } -auto DoActualBaudRate() -> int32_t +auto DoActualBaudRate() -> std::int32_t { return 0; } diff --git a/Sts1CobcSw/Periphery/Rf.cpp b/Sts1CobcSw/Periphery/Rf.cpp index 21ccf4ee..ef900a08 100644 --- a/Sts1CobcSw/Periphery/Rf.cpp +++ b/Sts1CobcSw/Periphery/Rf.cpp @@ -133,10 +133,10 @@ auto SetTxType(TxType txType) -> void { // Constants for setting the TX type (morse, 2GFSK) // MODEM_DATA_RATE: unused, 20 kBaud - static constexpr uint32_t dataRateMorse = 20'000U; + static constexpr std::uint32_t dataRateMorse = 20'000U; // MODEM_DATA_RATE: For 9k6 Baud: (TX_DATA_RATE * MODEM_TX_NCO_MODE * TXOSR) / F_XTAL_Hz = (9600 // * 2600000 * 10) / 26000000 = 9600 = 0x002580 - static constexpr uint32_t dataRate2Gfsk = 9'600U; + static constexpr std::uint32_t dataRate2Gfsk = 9'600U; // MODEM_MODE_TYPE: TX data from GPIO0 pin, modulation OOK static constexpr auto modemModTypeMorse = 0x09_b; // MODEM_MODE_TYPE: TX data from packet handler, modulation 2GFSK diff --git a/Sts1CobcSw/Utility/Time.cpp b/Sts1CobcSw/Utility/Time.cpp index d94f144c..319ccf1e 100644 --- a/Sts1CobcSw/Utility/Time.cpp +++ b/Sts1CobcSw/Utility/Time.cpp @@ -8,11 +8,11 @@ namespace sts1cobcsw::utility //! @brief Print UTC system time in human readable format void PrintFormattedSystemUtc() { - int32_t year = 0; - int32_t month = 0; - int32_t day = 0; - int32_t hour = 0; - int32_t min = 0; + std::int32_t year = 0; + std::int32_t month = 0; + std::int32_t day = 0; + std::int32_t hour = 0; + std::int32_t min = 0; double sec = 0; auto sysUtc = RODOS::sysTime.getUTC(); diff --git a/Tests/HardwareTests/Fram.test.cpp b/Tests/HardwareTests/Fram.test.cpp index 29f522c5..562f1106 100644 --- a/Tests/HardwareTests/Fram.test.cpp +++ b/Tests/HardwareTests/Fram.test.cpp @@ -67,7 +67,7 @@ class FramTest : public RODOS::StaticThread<> Check(deviceId == correctDeviceId); RODOS::setRandSeed(static_cast(RODOS::NOW())); - constexpr uint32_t nAdressBits = 20U; + constexpr std::uint32_t nAdressBits = 20U; auto address = fram::Address{RODOS::uint32Rand() % (1U << nAdressBits)}; PRINTF("\n"); diff --git a/Tests/UnitTests/Fram.test.cpp b/Tests/UnitTests/Fram.test.cpp index 75adf25b..790e0de4 100644 --- a/Tests/UnitTests/Fram.test.cpp +++ b/Tests/UnitTests/Fram.test.cpp @@ -38,7 +38,7 @@ TEST_CASE("Fram mock using ram") fram::FramMockMode(fram::MockMode::ram); std::mt19937 randomEngine(std::random_device{}()); - std::uniform_int_distribution gen(0, (1U << nAddressBits) - 1); + std::uniform_int_distribution gen(0, (1U << nAddressBits) - 1); fram::Address const address = gen(randomEngine); WriteAndReadTestData(address); From 24b9f1e256f8da3decc7859eb2709f9bea9bfd1e Mon Sep 17 00:00:00 2001 From: Patrick Kappl Date: Fri, 10 May 2024 11:03:56 +0000 Subject: [PATCH 08/12] Correctly mock read and write functions for FRAM Also, remove everything related to simulating the FRAM with a file. --- Sts1CobcSw/Periphery/FramMock.cpp | 97 +++++++++++++------------------ Sts1CobcSw/Periphery/FramMock.hpp | 34 ++++------- Tests/UnitTests/Fram.test.cpp | 17 ------ 3 files changed, 51 insertions(+), 97 deletions(-) diff --git a/Sts1CobcSw/Periphery/FramMock.cpp b/Sts1CobcSw/Periphery/FramMock.cpp index cf5995fe..f75e0284 100644 --- a/Sts1CobcSw/Periphery/FramMock.cpp +++ b/Sts1CobcSw/Periphery/FramMock.cpp @@ -10,12 +10,12 @@ namespace sts1cobcsw::fram { constexpr auto framSize = (1U << 20U); auto ramSimulation = std::array{}; -MockMode mockDevice = MockMode::ram; -constexpr auto mockFilename = "FramMock.bin"; auto doInitialize = empty::DoInitialize; auto doReadDeviceId = empty::DoReadDeviceId; auto doActualBaudRate = empty::DoActualBaudRate; +auto doWriteTo = empty::DoWriteTo; +auto doReadFrom = empty::DoReadFrom; // --- Mocked functions --- @@ -38,6 +38,21 @@ auto ActualBaudRate() -> std::int32_t } +namespace internal +{ +auto WriteTo(Address address, void const * data, std::size_t nBytes, std::int64_t timeout) -> void +{ + return doWriteTo(address, data, nBytes, timeout); +} + + +auto ReadFrom(Address address, void * data, std::size_t nBytes, std::int64_t timeout) -> void +{ + return doReadFrom(address, data, nBytes, timeout); +} +} + + // --- Set functions --- auto SetDoInitialize(void (*doInitializeFunction)()) -> void @@ -58,6 +73,20 @@ void SetDoActualBaudRate(std::int32_t (*doActualBaudRateFunction)()) } +auto SetDoWriteTo(void (*doWriteToFunction)( + Address address, void const * data, std::size_t nBytes, std::int64_t timeout)) -> void +{ + doWriteTo = doWriteToFunction; +} + + +auto SetDoReadFrom(void (*doReadFromFunction)( + Address address, void * data, std::size_t nBytes, std::int64_t timeout)) -> void +{ + doReadFrom = doReadFromFunction; +} + + // --- Predefined do functions --- namespace empty @@ -77,69 +106,21 @@ auto DoActualBaudRate() -> std::int32_t { return 0; } -} -auto FramMockMode(MockMode mockMode) -> void +auto DoWriteTo([[maybe_unused]] Address address, + [[maybe_unused]] void const * data, + [[maybe_unused]] std::size_t nBytes, + [[maybe_unused]] std::int64_t timeout) -> void { - mockDevice = mockMode; } - -namespace internal +auto DoReadFrom([[maybe_unused]] Address address, + [[maybe_unused]] void * data, + [[maybe_unused]] std::size_t nBytes, + [[maybe_unused]] std::int64_t timeout) -> void { -// TODO: This must also forward to a do function which can be set with a SetDoWriteTo function -auto WriteTo(Address address, - void const * data, - std::size_t nBytes, - [[maybe_unused]] std::int64_t timeout) -> void -{ - if(mockDevice == MockMode::file) - { - std::ofstream file(mockFilename, std::ios::binary | std::ios_base::ate); - if(not file) - { - std::cerr << "Failed to open file " << mockFilename << " for writing." << '\n'; - return; - } - - file.seekp(address); - file.write(static_cast(data), static_cast(nBytes)); - file.close(); - } - else - { - // FIXME: Fix pointer arithmetic and out of bounds access - std::memcpy(ramSimulation.data() + address, data, nBytes); - } -} - - -// TODO: This must also forward to a do function which can be set with a SetDoReadFrom function -auto ReadFrom(Address address, - void * data, - std::size_t nBytes, - [[maybe_unused]] std::int64_t timeout) -> void -{ - if(mockDevice == MockMode::file) - { - std::ifstream file(mockFilename, std::ios::binary); - if(not file) - { - std::cerr << "Failed to open file " << mockFilename << " for reading." << '\n'; - return; - } - - file.clear(); - file.seekg(address); - file.read(static_cast(data), static_cast(nBytes)); - file.close(); - } - else - { - std::memcpy(data, ramSimulation.data() + address, nBytes); - } } } } diff --git a/Sts1CobcSw/Periphery/FramMock.hpp b/Sts1CobcSw/Periphery/FramMock.hpp index b6de219d..566e5d17 100644 --- a/Sts1CobcSw/Periphery/FramMock.hpp +++ b/Sts1CobcSw/Periphery/FramMock.hpp @@ -8,40 +8,30 @@ namespace sts1cobcsw::fram { -enum class MockMode -{ - ram, - file -}; - - -// TODO: Add SetDoWriteTo and SetDoReadFrom functions auto SetDoInitialize(void (*doInitializeFunction)()) -> void; auto SetDoReadDeviceId(DeviceId (*doReadDeviceIdFunction)()) -> void; auto SetDoActualBaudRate(std::int32_t (*doActualBaudRateFunction)()) -> void; +auto SetDoWriteTo(void (*doWriteToFunction)( + Address address, void const * data, std::size_t nBytes, std::int64_t timeout)) -> void; +auto SetDoReadFrom(void (*doReadFromFunction)( + Address address, void * data, std::size_t nBytes, std::int64_t timeout)) -> void; -namespace empty -{ - // Empty do functions that do nothing, used to initialized function pointers - auto DoInitialize()->void; - auto DoReadDeviceId()->DeviceId; - auto DoActualBaudRate()->std::int32_t; -} - -// TODO: Remove this -auto FramMockMode(MockMode mockMode) -> void; -// TODO: Implement ram::do functions -namespace ram +// Empty do functions that do nothing; used to initialized function pointers +namespace empty { auto DoInitialize() -> void; auto DoReadDeviceId() -> DeviceId; auto DoActualBaudRate() -> std::int32_t; +auto DoWriteTo(Address address, void const * data, std::size_t nBytes, std::int64_t timeout) + -> void; +auto DoReadFrom(Address address, void * data, std::size_t nBytes, std::int64_t timeout) -> void; } -// TODO: Since this isn't fully implemented yet, remove it. The RAM mock should be enough. -namespace file +// TODO: Implement ram::do functions +// Do functions +namespace ram { auto DoInitialize() -> void; auto DoReadDeviceId() -> DeviceId; diff --git a/Tests/UnitTests/Fram.test.cpp b/Tests/UnitTests/Fram.test.cpp index 790e0de4..4b135d4d 100644 --- a/Tests/UnitTests/Fram.test.cpp +++ b/Tests/UnitTests/Fram.test.cpp @@ -35,8 +35,6 @@ auto ReadCorrectDeviceId() -> fram::DeviceId; TEST_CASE("Fram mock using ram") { - fram::FramMockMode(fram::MockMode::ram); - std::mt19937 randomEngine(std::random_device{}()); std::uniform_int_distribution gen(0, (1U << nAddressBits) - 1); fram::Address const address = gen(randomEngine); @@ -56,21 +54,6 @@ TEST_CASE("Fram mock using ram") } -TEST_CASE("Fram mock using file") -{ - fram::FramMockMode(fram::MockMode::file); - - std::mt19937 randomEngine(std::random_device{}()); - std::uniform_int_distribution addressGenerator(0, ((1U << nAddressBits) - 1)); - fram::Address const address = addressGenerator(randomEngine); - - WriteAndReadTestData(address); - std::generate( - testData.begin(), testData.end(), [&]() { return static_cast(randomEngine()); }); - WriteAndReadTestData(address); -} - - auto WriteAndReadTestData(fram::Address const & address) -> void { auto nBytesToPrint = 10U; From 66029607625d8341dab575607b6ba9d0eacf1b1d Mon Sep 17 00:00:00 2001 From: Patrick Kappl Date: Sat, 11 May 2024 11:35:41 +0000 Subject: [PATCH 09/12] Rework unit test for FRAM mock --- Tests/UnitTests/Fram.test.cpp | 87 +++++++++-------------------------- 1 file changed, 22 insertions(+), 65 deletions(-) diff --git a/Tests/UnitTests/Fram.test.cpp b/Tests/UnitTests/Fram.test.cpp index 4b135d4d..7d2e277f 100644 --- a/Tests/UnitTests/Fram.test.cpp +++ b/Tests/UnitTests/Fram.test.cpp @@ -1,91 +1,48 @@ #include -#include #include #include #include +#include +#include +#include -#include #include -#include -#include -#include -#include -#include namespace fram = sts1cobcsw::fram; - using sts1cobcsw::Byte; using sts1cobcsw::Span; using sts1cobcsw::operator""_b; // NOLINT(misc-unused-using-decls) -constexpr auto spiTimeout = 1; // in ms -constexpr auto nAddressBits = 20U; -size_t const testDataSize = 11 * 1024; // 11 KiB -auto testData = std::array{}; -auto readData = std::array{}; - - auto WriteAndReadTestData(sts1cobcsw::fram::Address const & address) -> void; auto ReadCorrectDeviceId() -> fram::DeviceId; -TEST_CASE("Fram mock using ram") -{ - std::mt19937 randomEngine(std::random_device{}()); - std::uniform_int_distribution gen(0, (1U << nAddressBits) - 1); - fram::Address const address = gen(randomEngine); - - WriteAndReadTestData(address); - std::generate( - testData.begin(), testData.end(), [&]() { return static_cast(randomEngine()); }); - WriteAndReadTestData(address); - - auto deviceId = fram::ReadDeviceId(); - constexpr auto correctDeviceId = - std::to_array({0x03_b, 0x2E_b, 0xC2_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b}); - REQUIRE(deviceId != correctDeviceId); - fram::SetDoReadDeviceId(ReadCorrectDeviceId); - deviceId = fram::ReadDeviceId(); - REQUIRE(deviceId == correctDeviceId); -} - - -auto WriteAndReadTestData(fram::Address const & address) -> void +TEST_CASE("Mocked functions do nothing by default") { - auto nBytesToPrint = 10U; - - std::printf("Writing %d bytes to address 0x%08x ...\n", - static_cast(testDataSize), - static_cast(address)); - fram::WriteTo(address, Span(testData), spiTimeout); - - std::printf("Reading %d bytes from address 0x%08x ...\n", - static_cast(testDataSize), - static_cast(address)); - fram::ReadFrom(address, Span(&readData), spiTimeout); - - std::printf("Comparing first %d written and read bytes:\n", nBytesToPrint); - std::printf(" "); - for(auto byte : Span(testData).first(nBytesToPrint)) + SECTION("Initialize(), ReadDeviceId() and ActualBaudRate()") { - std::printf("0x%02x ", static_cast(byte)); + fram::Initialize(); + auto deviceId = fram::ReadDeviceId(); + CHECK(deviceId == fram::DeviceId{}); + auto actualBaudRate = fram::ActualBaudRate(); + CHECK(actualBaudRate == 0); } - std::printf("\n "); - for(auto byte : Span(readData).first(nBytesToPrint)) - { - std::printf("0x%02x ", static_cast(byte)); - } - std::printf("\n"); - REQUIRE(readData == testData); -} + auto address = GENERATE(take(10, random(0U, 1U << 20U))); - -auto ReadCorrectDeviceId() -> fram::DeviceId -{ - return std::to_array({0x03_b, 0x2E_b, 0xC2_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b}); + SECTION("WriteTo() and ReadFrom()") + { + auto readData = std::array{0x11_b, 0x22_b, 0x33_b, 0x44_b}; + fram::ReadFrom(address, Span(&readData), 0); + CHECK(readData == std::array{0x11_b, 0x22_b, 0x33_b, 0x44_b}); + + auto writeData = std::array{0xAA_b, 0xBB_b, 0xCC_b, 0xDD_b}; + fram::WriteTo(address, Span(writeData), 0); + readData = fram::ReadFrom(address, 0); + CHECK(readData == decltype(readData){}); + } } From cb226ccd17d320f0967e75782e615719135b46a9 Mon Sep 17 00:00:00 2001 From: Patrick Kappl Date: Sat, 11 May 2024 12:04:03 +0000 Subject: [PATCH 10/12] Implement do functions for mocking FRAM in RAM --- Sts1CobcSw/Periphery/FramMock.cpp | 49 +++++++++++++++++++++++++++---- Sts1CobcSw/Periphery/FramMock.hpp | 13 ++++++-- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/Sts1CobcSw/Periphery/FramMock.cpp b/Sts1CobcSw/Periphery/FramMock.cpp index f75e0284..ac085192 100644 --- a/Sts1CobcSw/Periphery/FramMock.cpp +++ b/Sts1CobcSw/Periphery/FramMock.cpp @@ -1,16 +1,10 @@ #include -#include #include -#include // IWYU pragma: keep -#include namespace sts1cobcsw::fram { -constexpr auto framSize = (1U << 20U); -auto ramSimulation = std::array{}; - auto doInitialize = empty::DoInitialize; auto doReadDeviceId = empty::DoReadDeviceId; auto doActualBaudRate = empty::DoActualBaudRate; @@ -123,4 +117,47 @@ auto DoReadFrom([[maybe_unused]] Address address, { } } + + +namespace ram +{ +std::array storage{}; + + +auto DoInitialize() -> void +{ +} + + +auto DoReadDeviceId() -> DeviceId +{ + static constexpr auto deviceId = + std::to_array({0x03_b, 0x2E_b, 0xC2_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b}); + return deviceId; +} + + +auto DoActualBaudRate() -> std::int32_t +{ + return 6'000'000; // NOLINT(*magic-numbers*) +} + + +auto DoWriteTo(Address address, + void const * data, + std::size_t nBytes, + [[maybe_unused]] std::int64_t timeout) -> void +{ + std::memcpy(storage.data() + address, data, nBytes); +} + + +auto DoReadFrom(Address address, + void * data, + std::size_t nBytes, + [[maybe_unused]] std::int64_t timeout) -> void +{ + std::memcpy(data, storage.data() + address, nBytes); +} +} } diff --git a/Sts1CobcSw/Periphery/FramMock.hpp b/Sts1CobcSw/Periphery/FramMock.hpp index 566e5d17..75e72f94 100644 --- a/Sts1CobcSw/Periphery/FramMock.hpp +++ b/Sts1CobcSw/Periphery/FramMock.hpp @@ -2,7 +2,10 @@ #include +#include +#include +#include #include @@ -29,12 +32,18 @@ auto DoReadFrom(Address address, void * data, std::size_t nBytes, std::int64_t t } -// TODO: Implement ram::do functions -// Do functions +// Do functions that simulate the FRAM in RAM namespace ram { +constexpr auto storageSize = (1U << 20U); +extern std::array storage; + + auto DoInitialize() -> void; auto DoReadDeviceId() -> DeviceId; auto DoActualBaudRate() -> std::int32_t; +auto DoWriteTo(Address address, void const * data, std::size_t nBytes, std::int64_t timeout) + -> void; +auto DoReadFrom(Address address, void * data, std::size_t nBytes, std::int64_t timeout) -> void; } } From 7f66caa319d88ece05c9c19a04bf2e279b5b605c Mon Sep 17 00:00:00 2001 From: Patrick Kappl Date: Sat, 11 May 2024 14:19:23 +0000 Subject: [PATCH 11/12] Add fram::empty/ram::SetAllDoFunctions() --- Sts1CobcSw/Periphery/FramMock.cpp | 20 ++++++++++++++++++++ Sts1CobcSw/Periphery/FramMock.hpp | 4 ++++ 2 files changed, 24 insertions(+) diff --git a/Sts1CobcSw/Periphery/FramMock.cpp b/Sts1CobcSw/Periphery/FramMock.cpp index ac085192..d961f7c1 100644 --- a/Sts1CobcSw/Periphery/FramMock.cpp +++ b/Sts1CobcSw/Periphery/FramMock.cpp @@ -85,6 +85,16 @@ auto SetDoReadFrom(void (*doReadFromFunction)( namespace empty { +auto SetAllDoFunctions() -> void +{ + SetDoInitialize(DoInitialize); + SetDoReadDeviceId(DoReadDeviceId); + SetDoActualBaudRate(DoActualBaudRate); + SetDoWriteTo(DoWriteTo); + SetDoReadFrom(DoReadFrom); +} + + auto DoInitialize() -> void { } @@ -124,6 +134,16 @@ namespace ram std::array storage{}; +auto SetAllDoFunctions() -> void +{ + SetDoInitialize(DoInitialize); + SetDoReadDeviceId(DoReadDeviceId); + SetDoActualBaudRate(DoActualBaudRate); + SetDoWriteTo(DoWriteTo); + SetDoReadFrom(DoReadFrom); +} + + auto DoInitialize() -> void { } diff --git a/Sts1CobcSw/Periphery/FramMock.hpp b/Sts1CobcSw/Periphery/FramMock.hpp index 75e72f94..c2ebf36d 100644 --- a/Sts1CobcSw/Periphery/FramMock.hpp +++ b/Sts1CobcSw/Periphery/FramMock.hpp @@ -23,6 +23,8 @@ auto SetDoReadFrom(void (*doReadFromFunction)( // Empty do functions that do nothing; used to initialized function pointers namespace empty { +auto SetAllDoFunctions() -> void; + auto DoInitialize() -> void; auto DoReadDeviceId() -> DeviceId; auto DoActualBaudRate() -> std::int32_t; @@ -39,6 +41,8 @@ constexpr auto storageSize = (1U << 20U); extern std::array storage; +auto SetAllDoFunctions() -> void; + auto DoInitialize() -> void; auto DoReadDeviceId() -> DeviceId; auto DoActualBaudRate() -> std::int32_t; From a2f9416661d44e5d492ddd54338c8a43c14a2641 Mon Sep 17 00:00:00 2001 From: Patrick Kappl Date: Sat, 11 May 2024 14:41:39 +0000 Subject: [PATCH 12/12] Add test case for mocking FRAM in RAM --- Tests/UnitTests/Fram.test.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Tests/UnitTests/Fram.test.cpp b/Tests/UnitTests/Fram.test.cpp index 7d2e277f..9c234b2e 100644 --- a/Tests/UnitTests/Fram.test.cpp +++ b/Tests/UnitTests/Fram.test.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -8,6 +9,7 @@ #include #include +#include namespace fram = sts1cobcsw::fram; @@ -46,3 +48,34 @@ TEST_CASE("Mocked functions do nothing by default") CHECK(readData == decltype(readData){}); } } + + +TEST_CASE("Mocking FRAM in RAM") +{ + fram::ram::SetAllDoFunctions(); + fram::ram::storage.fill(0x00_b); + + fram::Initialize(); + auto const correctDeviceId = + std::to_array({0x03_b, 0x2E_b, 0xC2_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b, 0x7F_b}); + auto deviceId = fram::ReadDeviceId(); + CHECK(deviceId == correctDeviceId); + auto actualBaudRate = fram::ActualBaudRate(); + CHECK(actualBaudRate == 6'000'000); + + auto address = GENERATE(take(1, random(0U, fram::ram::storageSize - 10))); + + auto readData = std::array{0x01_b, 0x02_b, 0x03_b, 0x04_b}; + fram::ReadFrom(address, Span(&readData), 0); + CHECK(readData == decltype(readData){}); + + auto writeData = std::array{0xAA_b, 0xBB_b, 0xCC_b, 0xDD_b}; + fram::WriteTo(address, Span(writeData), 0); + CHECK(fram::ram::storage[address] == writeData[0]); + CHECK(fram::ram::storage[address + 1] == writeData[1]); + CHECK(fram::ram::storage[address + 2] == writeData[2]); + CHECK(fram::ram::storage[address + 3] == writeData[3]); + + readData = fram::ReadFrom(address, 0); + CHECK(readData == writeData); +}