Skip to content

Commit

Permalink
WIP: Implement some requested changes for ringbuffer
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromehue committed Jul 13, 2024
1 parent 5998e5e commit 1c9c064
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 176 deletions.
5 changes: 3 additions & 2 deletions Sts1CobcSw/Edu/ProgramStatusHistory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

namespace sts1cobcsw::edu
{
ProgramStatusHistoryClass<programStatusHistorySize> programStatusHistory =
ProgramStatusHistoryClass<programStatusHistorySize>();
// TODO: Put a real variable for start Address
ProgramStatusHistoryClass<programStatusHistorySize, 0> programStatusHistory =
ProgramStatusHistoryClass<programStatusHistorySize, 0>();
}

namespace sts1cobcsw::edu
Expand Down
18 changes: 10 additions & 8 deletions Sts1CobcSw/Edu/ProgramStatusHistory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

// clang-format off
#include <cstdint> // NOLINT(llvm-include-order)
#include "Sts1CobcSw/Periphery/Fram.hpp"
#include "Sts1CobcSw/Periphery/FramRingBuffer.hpp"
// ringbuffer.h does not include <cstdint> even though it requires it
#include <rodos/support/support-libs/ringbuffer.h>
Expand Down Expand Up @@ -56,14 +57,14 @@ template<std::endian endianness>
[[nodiscard]] auto SerializeTo(void * destination, ProgramStatusHistoryEntry const & data)
-> void *;

template<std::size_t poolSize>
auto UpdateRingBufferEntry(fram::RingBuffer<ProgramStatusHistoryEntry, poolSize> & ringBuffer,
template<std::size_t poolSize, fram::Address address>
auto UpdateRingBufferEntry(fram::RingBuffer<ProgramStatusHistoryEntry, poolSize, address> & ringBuffer,
std::int32_t startTime,
ProgramId programId,
ProgramStatus newStatus) -> bool;


template<std::size_t size>
template<std::size_t size, fram::Address address>
class ProgramStatusHistoryClass
{
public:
Expand All @@ -76,7 +77,7 @@ class ProgramStatusHistoryClass
{
if(fram::framIsWorking)
{
framProgramStatusHistory_.Put(programStatusHistoryEntry);
//framProgramStatusHistory_.Put(programStatusHistoryEntry);
}
ramProgramStatusHistory_.put(programStatusHistoryEntry);
}
Expand Down Expand Up @@ -104,16 +105,17 @@ class ProgramStatusHistoryClass
}

private:
sts1cobcsw::fram::RingBuffer<ProgramStatusHistoryEntry, size> framProgramStatusHistory_;
sts1cobcsw::fram::RingBuffer<ProgramStatusHistoryEntry, size, address> framProgramStatusHistory_;
RODOS::RingBuffer<ProgramStatusHistoryEntry, size> ramProgramStatusHistory_;
};

extern ProgramStatusHistoryClass<programStatusHistorySize> programStatusHistory;
// TODO: Put a real value here
extern ProgramStatusHistoryClass<programStatusHistorySize, 0> programStatusHistory;


// TODO: Move this into .cpp file
template<std::size_t poolSize>
auto UpdateRingBufferEntry(fram::RingBuffer<ProgramStatusHistoryEntry, poolSize> & ringBuffer,
template<std::size_t poolSize, fram::Address startAddress>
auto UpdateRingBufferEntry(fram::RingBuffer<ProgramStatusHistoryEntry, poolSize, startAddress> & ringBuffer,
const std::int32_t startTime,
const ProgramId programId,
const ProgramStatus newStatus) -> bool
Expand Down
74 changes: 30 additions & 44 deletions Sts1CobcSw/Periphery/FramRingBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,61 +14,30 @@

namespace sts1cobcsw::fram
{
using sts1cobcsw::Span;
using sts1cobcsw::TriviallySerializable;

int ANewMethod(int b);

template<typename T, std::size_t poolSize>
template<typename T, std::size_t size, Address startAddress>
class RingBuffer
{
public:
// NOLINTBEGIN(*non-private-member-variables-in-classes)
std::uint64_t writeCnt = 0;
std::uint64_t readCnt = 0;
std::uint32_t occupiedCnt = 0;
Address startAddress;
// NOLINTEND(*non-private-member-variables-in-classes)

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

RingBuffer() : startAddress(0){};

void Put(T const & newdata)
{
currentWrite_ = writeIndex_;
auto const address = startAddress + writeIndex_ * serialSize<T>;
fram::WriteTo(address, Span(Serialize(newdata)), 0);
writeIndex_++;

if(writeIndex_ >= poolSize)
{
writeIndex_ = 0;
}
if(occupiedCnt < poolSize)
{
occupiedCnt++;
}
writeCnt++;
currentWrite_ = UINT32_MAX;
}
RingBuffer() = default;

// Get next item
void Get(T & fromRing)
{
// Jump the current being written record
if(readIndex_ == currentWrite_)
if(readIndex_ == currentWriteIndex_)
{
readIndex_++;
}
if(readIndex_ >= poolSize)
if(readIndex_ >= size)
{
readIndex_ = 0;
}

// readIndex should not pass write index if there is no data after it
if(writeCnt < poolSize && readIndex_ >= writeIndex_)
if(writeCount_ < size && readIndex_ >= writeIndex_)
{
readIndex_ = 0;
}
Expand All @@ -79,26 +48,43 @@ class RingBuffer
fromRing = Deserialize<T>(std::span(readData));

readIndex_++;
if(readIndex_ >= poolSize)
if(readIndex_ >= size)
{
readIndex_ = 0;
}

if(occupiedCnt > 0)
if(occupiedCount_ > 0)
{
occupiedCnt--;
occupiedCount_--;
}
readCnt++;
readCount_++;
}

auto Capacity() -> std::size_t
{
return capacity_;
}

auto GetLen() -> int
auto Size() -> std::size_t
{
return poolSize;
return size;
}

auto Push(T const& newData) -> void;

// TODO: return type syntax for functions
T& operator[](std::size_t index);

private:
std::uint32_t writeIndex_ = 0;
std::uint32_t readIndex_ = 0;
std::uint32_t currentWrite_ = UINT32_MAX;
std::uint32_t currentWriteIndex_ = UINT32_MAX;
std::uint64_t writeCount_ = 0;
std::uint64_t readCount_ = 0;
std::uint32_t occupiedCount_ = 0;
std::size_t capacity_ = 0;
};
}


#include <Sts1CobcSw/Periphery/FramRingBuffer.ipp> // IWYU pragma: keep
27 changes: 27 additions & 0 deletions Sts1CobcSw/Periphery/FramRingBuffer.ipp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once


#include <Sts1CobcSw/Periphery/FramRingBuffer.hpp>


namespace sts1cobcsw::fram
{
template<typename T, std::size_t size, Address startAddress>
void RingBuffer<T, size, startAddress>::Push(T const& newData)
{
currentWriteIndex_ = writeIndex_;
auto const address = startAddress + writeIndex_ * serialSize<T>;
fram::WriteTo(address, Span(Serialize(newData)), 0);
writeIndex_++;

if (writeIndex_ >= size) {
writeIndex_ = 0;
}
if (occupiedCount_ < size) {
occupiedCount_++;
}
writeCount_++;
// TODO: iwyu
currentWriteIndex_ = UINT32_MAX;
}
}
132 changes: 12 additions & 120 deletions Tests/UnitTests/FramRingBuffer.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@

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

#include <array>
#include <cstdint>


namespace fram = sts1cobcsw::fram;
Expand All @@ -29,129 +27,23 @@ using sts1cobcsw::Deserialize;
using sts1cobcsw::Serialize;


TEST_CASE("RODOS ringbuffer put and get operations")
// TODO: Sections could be useful
TEST_CASE("Initial State ringbuffer")
{
RODOS::RingBuffer<int, 10> buffer;
sts1cobcsw::fram::RingBuffer<int, 10, fram::Address(0)> buffer;

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);

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

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 = 0;
for(int i = 20; i < 30; ++i)
{
buffer.get(result);
REQUIRE(result == i);
}
}

// TODO: Split in different 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);
REQUIRE(buffer.Size() == 10);
REQUIRE(buffer.Capacity() == 0);
}


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


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 = sts1cobcsw::ProgramId(12),
.startTime = 34,
.status = ProgramStatus::programExecutionFailed};
auto result = ProgramStatusHistoryEntry{};
fram::RingBuffer<int, 10, fram::Address(0)> buffer;

ringBuffer.Put(value);
ringBuffer.Get(result);
buffer.Push(1);
buffer.Push(2);
buffer.Push(3);

CHECK(result.programId == 12);
CHECK(result.startTime == 34);
CHECK(result.status == ProgramStatus::programExecutionFailed);
// Failing
// REQUIRE(buffer.Size() == 3);
}
4 changes: 2 additions & 2 deletions Tests/UnitTests/UpdateRingBuffer.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ using sts1cobcsw::Serialize;
// Normally this would be set in Sts1CobcSw/someThread.cpp
bool sts1cobcsw::fram::framIsWorking = true;

ProgramStatusHistoryClass<sts1cobcsw::edu::programStatusHistorySize> programStatusHistory =
ProgramStatusHistoryClass<sts1cobcsw::edu::programStatusHistorySize>();
ProgramStatusHistoryClass<sts1cobcsw::edu::programStatusHistorySize, 0> programStatusHistory =
ProgramStatusHistoryClass<sts1cobcsw::edu::programStatusHistorySize, 0>();

namespace sts1cobcsw::edu
{
Expand Down

0 comments on commit 1c9c064

Please sign in to comment.