Skip to content

Commit

Permalink
Add golden test for SPI supervisor
Browse files Browse the repository at this point in the history
  • Loading branch information
PatrickKa committed Nov 24, 2024
1 parent b37658f commit 94f23e7
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Sts1CobcSw/CobcSoftware/FlashStartupTestThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ class FlashStartupTestThread : public RODOS::StaticThread<stackSize>

void run() override
{
DEBUG_PRINT("Flash start-up test ...");
SuspendUntil(endOfTime);
DEBUG_PRINT("Flash start-up test ...");
flash::Initialize();
auto jedecId = flash::ReadJedecId();
if(jedecId.deviceId == flash::correctJedecId.deviceId
Expand Down
2 changes: 1 addition & 1 deletion Sts1CobcSw/CobcSoftware/FramEpsStartupTestThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ class FramEpsStartupTestThread : public RODOS::StaticThread<stackSize>

void run() override
{
DEBUG_PRINT("FRAM/EPS start-up test ...");
SuspendUntil(endOfTime);
DEBUG_PRINT("FRAM/EPS start-up test ...");
fram::Initialize();
auto deviceId = fram::ReadDeviceId();
if(deviceId == fram::correctDeviceId)
Expand Down
2 changes: 1 addition & 1 deletion Sts1CobcSw/CobcSoftware/RfStartupTestThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class RfStartupTestThread : public RODOS::StaticThread<stackSize>

void run() override
{
DEBUG_PRINT("RF start-up test ...");
SuspendUntil(endOfTime);
DEBUG_PRINT("RF start-up test ...");
rf::Initialize(rf::TxType::packet);
auto partNumber = rf::ReadPartNumber();
if(partNumber == rf::correctPartNumber)
Expand Down
9 changes: 7 additions & 2 deletions Sts1CobcSw/CobcSoftware/SpiStartupTestAndSupervisorThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@

namespace sts1cobcsw
{
constexpr auto stackSize = 100U;
// Running the integration test for the supervisor thread showed that at least 850 bytes are needed
constexpr auto stackSize = 900U;
constexpr auto initialSleepTime = 10 * ms;
// TODO: Measure how long the startup tests really take to determine the correct timeout
constexpr auto startupTestTimeout = 100 * ms;
// TODO: Think about how often the supervision should run
Expand All @@ -52,6 +54,10 @@ class SpiStartupTestAndSupervisorThread : public RODOS::StaticThread<stackSize>

void run() override
{
// Briefly go to sleep to ensure that the low-priority startup test threads have started and
// are waiting for the high-priority supervisor thread to resume them
SuspendFor(initialSleepTime);

static constexpr auto errorMessage = " failed to complete in time\n";
static constexpr auto successMessage = " completed in time\n";

Expand Down Expand Up @@ -118,7 +124,6 @@ class SpiStartupTestAndSupervisorThread : public RODOS::StaticThread<stackSize>
}
if(timeoutHappened)
{
DEBUG_PRINT("Hardware reset and reboot");
RODOS::hwResetAndReboot();
}
}
Expand Down
2 changes: 1 addition & 1 deletion Tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ add_custom_target(AllTests)
if(CMAKE_SYSTEM_NAME STREQUAL Linux)
add_subdirectory(GoldenTests EXCLUDE_FROM_ALL)
add_subdirectory(UnitTests EXCLUDE_FROM_ALL)
add_dependencies(AllTests AllUnitTests AllGoldenTests)
add_dependencies(AllTests AllGoldenTests AllUnitTests)
elseif(CMAKE_SYSTEM_NAME STREQUAL Generic)
add_subdirectory(HardwareTests EXCLUDE_FROM_ALL)
add_dependencies(AllTests AllHardwareTests)
Expand Down
11 changes: 11 additions & 0 deletions Tests/GoldenTests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ target_link_libraries(Sts1CobcSwTests_HelloWorld PRIVATE rodos::rodos)
add_golden_test(HelloDummy.test.cpp)
target_link_libraries(Sts1CobcSwTests_HelloDummy PRIVATE rodos::rodos etl::etl Sts1CobcSw_Dummy)

add_golden_test(SpiSupervisor.test.cpp)
target_sources(
Sts1CobcSwTests_SpiSupervisor
PRIVATE ${CMAKE_SOURCE_DIR}/Sts1CobcSw/CobcSoftware/StartupTestThreadStubs.cpp
${CMAKE_SOURCE_DIR}/Sts1CobcSw/CobcSoftware/SpiStartupTestAndSupervisorThread.cpp
)
target_link_libraries(
Sts1CobcSwTests_SpiSupervisor PRIVATE rodos::rodos Sts1CobcSw_FramSections Sts1CobcSw_Hal
Sts1CobcSw_Periphery Sts1CobcSw_Serial Sts1CobcSw_Utility
)

# --- All golden tests ---

get_property(
Expand Down
16 changes: 16 additions & 0 deletions Tests/GoldenTests/ExpectedOutputs/SpiSupervisor.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FRAM/EPS start-up test ...
completed in time
Flash start-up test ...
completed in time
RF start-up test ...
completed in time

SPI supervisor test

Writing with implementation that finishes in time ...
-> works
Writing with implementation that never finishes ...
FRAM/EPS SPI timeout occurred
Flash SPI timeout occurred
RF SPI timeout occurred
hw_resetAndReboot() -> exit
100 changes: 100 additions & 0 deletions Tests/GoldenTests/SpiSupervisor.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include <Sts1CobcSw/Hal/Spi.hpp>
#include <Sts1CobcSw/Hal/SpiMock.hpp>
#include <Sts1CobcSw/Periphery/Fram.hpp>
#include <Sts1CobcSw/Periphery/FramMock.hpp>
#include <Sts1CobcSw/Periphery/Spis.hpp>
#include <Sts1CobcSw/Serial/Byte.hpp>
#include <Sts1CobcSw/Utility/RodosTime.hpp>
#include <Sts1CobcSw/Utility/Span.hpp>
#include <Sts1CobcSw/Utility/TimeTypes.hpp>

#include <strong_type/affine_point.hpp>
#include <strong_type/difference.hpp>

#include <rodos_no_using_namespace.h>

#include <cstddef>


namespace sts1cobcsw
{
using RODOS::PRINTF;


auto WriteThatFinishesInTime([[maybe_unused]] void const * data,
[[maybe_unused]] std::size_t nBytes,
Duration duration) -> void;
auto WriteThatNeverFinishes([[maybe_unused]] void const * data,
[[maybe_unused]] std::size_t nBytes,
Duration duration) -> void;


auto transferEnd = endOfTime;


class SpiSupervisorTest : public RODOS::StaticThread<>
{
// We cannot use dynamic_cast because RTTI is disabled
// NOLINTBEGIN(*static-cast-downcast)
hal::SpiMock & flashSpi_ = static_cast<hal::SpiMock &>(flashSpi);
hal::SpiMock & framEpsSpi_ = static_cast<hal::SpiMock &>(framEpsSpi);
hal::SpiMock & rfSpi_ = static_cast<hal::SpiMock &>(rfSpi);
// NOLINTEND(*static-cast-downcast)


public:
SpiSupervisorTest() : StaticThread("SpiSupervisorTest", 200)
{
}

void init() override
{
flashSpi_.SetTransferEnd([]() { return transferEnd; });
flashSpi_.SetWrite(WriteThatFinishesInTime);
framEpsSpi_.SetTransferEnd([]() { return transferEnd; });
framEpsSpi_.SetWrite(WriteThatFinishesInTime);
rfSpi_.SetTransferEnd([]() { return transferEnd; });
rfSpi_.SetWrite(WriteThatFinishesInTime);
fram::ram::SetAllDoFunctions();
fram::Initialize();
}

void run() override
{
SuspendFor(1 * s);

PRINTF("\nSPI supervisor test\n\n");

PRINTF("Writing with implementation that finishes in time ...\n");
WriteTo(&flashSpi_, Span(0x00_b), 10 * ms);
WriteTo(&framEpsSpi_, Span(0x00_b), 100 * ms);
// The supervision period is 1 s so this write will definitely be checked at least once by
// the supervisor thread
WriteTo(&rfSpi_, Span(0x00_b), 1500 * ms);
PRINTF(" -> works\n");

PRINTF("Writing with implementation that never finishes ...\n");
flashSpi_.SetWrite(WriteThatNeverFinishes);
WriteTo(&flashSpi_, Span(0x00_b), 1 * ms);
}
} spiSupervisorTest;


auto WriteThatFinishesInTime([[maybe_unused]] void const * data,
[[maybe_unused]] std::size_t nBytes,
Duration duration) -> void
{
transferEnd = CurrentRodosTime() + duration;
SuspendFor(duration / 10 * 9);
transferEnd = endOfTime;
}


auto WriteThatNeverFinishes([[maybe_unused]] void const * data,
[[maybe_unused]] std::size_t nBytes,
Duration duration) -> void
{
transferEnd = CurrentRodosTime() + duration;
SuspendUntil(endOfTime);
}
}

0 comments on commit 94f23e7

Please sign in to comment.