Skip to content

Commit

Permalink
Add an x86 test case using ProgramStatusHistoryEntry
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromehue committed May 28, 2024
1 parent 29336ac commit 7513f7b
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 32 deletions.
53 changes: 38 additions & 15 deletions Sts1CobcSw/Periphery/FramRingBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,60 @@


#include <Sts1CobcSw/Periphery/Fram.hpp>
#include <Sts1CobcSw/Serial/Byte.hpp>
#include <Sts1CobcSw/Serial/Serial.hpp>

#include <rodos-debug.h>

#include <array>
#include <bit>
#include <cstddef>
#include <cstdint>
#include <span>

#include "Sts1CobcSw/Utility/Span.hpp"


namespace sts1cobcsw::fram
{
using sts1cobcsw::Byte;
using sts1cobcsw::Span;
using sts1cobcsw::operator""_b; // NOLINT(misc-unused-using-decls)
using sts1cobcsw::TriviallySerializable;

template<class T, std::size_t poolSize>

// TODO: Handle non trivially serializable types/class
// template<typename T, std::size_t poolSize>
template<typename T, std::size_t poolSize>
class RingBuffer
{
public:
Address startAddress;
std::uint32_t writeIndex = 0;
std::uint32_t readIndex = 0;
std::uint32_t currentWrite = UINT32_MAX;
// TODO: Check that this is correct, or that it should be
std::array<T, poolSize> vals;

public:
std::uint64_t writeCnt = 0;
std::uint64_t readCnt = 0;
std::uint32_t occupiedCnt = 0;

RingBuffer(Address startAddress) : startAddress(startAddress)
explicit RingBuffer(Address address) : startAddress(address)
{
}

T * getNextEntryToPut()
auto GetNextEntryToPut() -> T *
{
return &vals[writeIndex];
}

void put(T const & newdata)
void Put(T const & newdata)
{
currentWrite = writeIndex;
Address address = startAddress + writeIndex * sizeof(T);

WriteTo(address, reinterpret_cast<Byte const *>(&newdata), sizeof(T), 0);
// NOTE: For trivially serializable types, sizeof and serialSize should be the same.
auto const address = startAddress + writeIndex * serialSize<T>;
fram::WriteTo(address, Span(Serialize(newdata)), 0);
writeIndex++;

if(writeIndex >= poolSize)
Expand All @@ -57,7 +71,7 @@ class RingBuffer
}

// Get next item
void get(T & fromRing)
void Get(T & fromRing)
{
// Jump the current being written record
if(readIndex == currentWrite)
Expand All @@ -75,10 +89,19 @@ class RingBuffer
readIndex = 0;
}

Address address = startAddress + readIndex * sizeof(T);
std::array<Byte, sizeof(T)> buffer;
ReadFrom(address, buffer, 0);
fromRing = *reinterpret_cast<T *>(buffer.data());
auto const address = startAddress + readIndex * serialSize<T>;
// TODO: Deal with timeout
auto readData = fram::ReadFrom<serialSize<T>>(address, 0);
fromRing = Deserialize<T>(std::span(readData));

// DEBUG PRINT
std::printf("Printing read data in buffer.Get() method :\n");
for(auto byte : readData)
{
std::printf("0x%02x ", static_cast<unsigned char>(byte));
}
std::printf("\n");
// END DEBUG PRINT

readIndex++;
if(readIndex >= poolSize)
Expand All @@ -93,9 +116,9 @@ class RingBuffer
readCnt++;
}

int getLen()
auto GetLen() -> int
{
return poolSize;
}
};
}
}
2 changes: 1 addition & 1 deletion Tests/UnitTests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ target_link_libraries(
)

add_program(RingBuffer FramRingBuffer.test.cpp)
target_link_libraries(Sts1CobcSwTests_RingBuffer PRIVATE Catch2::Catch2WithMain)
target_link_libraries(Sts1CobcSwTests_RingBuffer PRIVATE Catch2::Catch2WithMain Sts1CobcSw_Periphery Sts1CobcSw_Serial)

# TODO: Enable again once problem with segmentation violation on CI is fixed
add_program(LfsRam LfsRam.test.cpp)
Expand Down
161 changes: 145 additions & 16 deletions Tests/UnitTests/FramRingBuffer.test.cpp
Original file line number Diff line number Diff line change
@@ -1,61 +1,190 @@
#include <cstdint>
#include <rodos/support/support-libs/ringbuffer.h>
#include <Sts1CobcSw/Edu/ProgramStatusHistory.hpp>
#include <Sts1CobcSw/Periphery/Fram.hpp>
#include <Sts1CobcSw/Periphery/FramMock.hpp>
#include <Sts1CobcSw/Periphery/FramRingBuffer.hpp>
#include <Sts1CobcSw/Serial/Byte.hpp>
#include <Sts1CobcSw/Serial/Serial.hpp>

#include <catch2/catch_test_macros.hpp>
#include <catch2/generators/catch_generators.hpp>
#include <catch2/generators/catch_generators_adapters.hpp>
#include <catch2/generators/catch_generators_random.hpp>

#include <rodos/support/support-libs/ringbuffer.h>

#include <array>
#include <bit>
#include <cstddef>
#include <cstdint>


namespace fram = sts1cobcsw::fram;

using sts1cobcsw::Byte;
using sts1cobcsw::Span;
using sts1cobcsw::edu::ProgramStatus;
using sts1cobcsw::edu::ProgramStatusHistoryEntry;
using sts1cobcsw::operator""_b; // NOLINT(misc-unused-using-decls)
using sts1cobcsw::Deserialize;
using sts1cobcsw::Serialize;


TEST_CASE("RODOS ringbuffer put and get operations")
{

RODOS::RingBuffer<int, 10> buffer;

REQUIRE(buffer.getLen() == 10);

int value = 42;
int result;
REQUIRE(buffer.getLen() == 10);

auto const value = 42;
int result = 0;
buffer.put(value);
buffer.get(result);
REQUIRE(value == result);
}

TEST_CASE("RODOS ringbuffer overwrite")
{

RODOS::RingBuffer<int, 10> buffer;
REQUIRE(buffer.getLen() == 10);
REQUIRE(buffer.getLen() == 10);

for(int i = 0; i < 15; i++)
{
buffer.put(i);
}

int result;
int result = 0;
for(int i = 10; i < 15; ++i)
{
buffer.get(result);
REQUIRE(result == i);
}
}
}

TEST_CASE("RODOS ringbuffer wrapping")
{

RODOS::RingBuffer<int, 10> buffer;
for(int i = 0; i < 30; ++i)
{
buffer.put(i);
}

int result;
int result = 0;
for(int i = 20; i < 30; ++i)
{
buffer.get(result);
REQUIRE(result == i);
}


}

// TODO: Split in differents tests or sections
TEST_CASE("RingBuffer put and get operations")
{
}
fram::ram::SetAllDoFunctions();
fram::ram::storage.fill(0x00_b);
fram::Initialize();

auto address = GENERATE(take(2, random(0U, 1U << 20U)));
auto int8Buffer = sts1cobcsw::fram::RingBuffer<std::int8_t, 10>(address);
auto uint16Buffer = sts1cobcsw::fram::RingBuffer<std::uint16_t, 10>(address + 10);
auto int32Buffer = sts1cobcsw::fram::RingBuffer<std::int32_t, 10>(address + 20);


REQUIRE(int8Buffer.GetLen() == 10);


auto const i8Value = 42;
std::int8_t result = 0;
int8Buffer.Put(i8Value);
int8Buffer.Get(result);
REQUIRE(i8Value == result);

const std::uint16_t u16Value = 65000;
std::uint16_t u16Result = 0;
uint16Buffer.Put(u16Value);
uint16Buffer.Get(u16Result);
REQUIRE(u16Value == u16Result);


const std::int32_t i32Value = -2'147'483'648;
std::int32_t i32Result = 0;
int32Buffer.Put(i32Value);
int32Buffer.Get(i32Result);
REQUIRE(i32Value == i32Result);
}


// Debug test case
TEST_CASE("Simple put and get inlined")
{
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){});
}


namespace sts1cobcsw
{
template<>
constexpr std::size_t serialSize<edu::ProgramStatusHistoryEntry> =
totalSerialSize<decltype(edu::ProgramStatusHistoryEntry::programId),
decltype(edu::ProgramStatusHistoryEntry::startTime),
decltype(edu::ProgramStatusHistoryEntry::status)>;
}


namespace sts1cobcsw::edu
{
template<std::endian endianness>
auto SerializeTo(void * destination, sts1cobcsw::edu::ProgramStatusHistoryEntry const & data)
-> void *
{
destination = sts1cobcsw::SerializeTo<endianness>(destination, data.programId);
destination = sts1cobcsw::SerializeTo<endianness>(destination, data.startTime);
destination = sts1cobcsw::SerializeTo<endianness>(destination, data.status);
return destination;
}

template<std::endian endianness>
auto DeserializeFrom(void const * source, sts1cobcsw::edu::ProgramStatusHistoryEntry * data)
-> void const *
{
source = sts1cobcsw::DeserializeFrom<endianness>(source, &(data->programId));
source = sts1cobcsw::DeserializeFrom<endianness>(source, &(data->startTime));
source = sts1cobcsw::DeserializeFrom<endianness>(source, &(data->status));
return source;
}
}


TEST_CASE("Program status and history")
{
fram::ram::SetAllDoFunctions();
fram::ram::storage.fill(0x00_b);
fram::Initialize();

// Put() and Get() a ProgramStatusHistoryEntry variable.
auto ringBuffer = fram::RingBuffer<ProgramStatusHistoryEntry, 10>(0);
auto value = ProgramStatusHistoryEntry{
.programId = 12, .startTime = 34, .status = ProgramStatus::programExecutionFailed};
auto result = ProgramStatusHistoryEntry{};

ringBuffer.Put(value);
ringBuffer.Get(result);

CHECK(result.programId == 12);
CHECK(result.startTime == 34);
CHECK(result.status == ProgramStatus::programExecutionFailed);
}

0 comments on commit 7513f7b

Please sign in to comment.