Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move EDU program queue to FRAM #336

Merged
merged 15 commits into from
Jan 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions Sts1CobcSw/CobcSoftware/CommandParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@
#include <Sts1CobcSw/CobcSoftware/EduProgramQueueThread.hpp>
#include <Sts1CobcSw/Edu/Edu.hpp>
#include <Sts1CobcSw/Edu/ProgramQueue.hpp>
#include <Sts1CobcSw/FramSections/FramLayout.hpp>
#include <Sts1CobcSw/FramSections/FramVector.hpp>
#include <Sts1CobcSw/FramSections/PersistentVariables.hpp>
#include <Sts1CobcSw/Serial/Serial.hpp>
#include <Sts1CobcSw/Utility/DebugPrint.hpp>

#include <strong_type/type.hpp>

#include <cinttypes> // IWYU pragma: keep


Expand Down Expand Up @@ -59,14 +64,11 @@ auto DispatchCommand(etl::vector<Byte, commandSize> const & command) -> void
auto BuildEduQueue(std::span<Byte const> commandData) -> void
{
DEBUG_PRINT("Entering build queue command parsing\n");

edu::programQueue.clear();
edu::programQueue.Clear();
persistentVariables.Store<"eduProgramQueueIndex">(0);
ParseAndAddQueueEntries(commandData);
edu::queueIndex = 0;

DEBUG_PRINT("Queue index reset. Current size of EDU program queue is %d.\n",
static_cast<int>(edu::programQueue.size()));

static_cast<int>(edu::programQueue.Size()));
ResumeEduProgramQueueThread();
}

Expand All @@ -80,7 +82,7 @@ auto ParseAndAddQueueEntries(std::span<Byte const> queueEntries) -> void
DEBUG_PRINT("Printing and parsing\n");

while(queueEntries.size() >= totalSerialSize<edu::ProgramQueueEntry>
and (not edu::programQueue.full()))
and (not edu::programQueue.IsFull()))
{
auto entry = Deserialize<edu::ProgramQueueEntry>(
queueEntries.first<totalSerialSize<edu::ProgramQueueEntry>>());
Expand All @@ -89,7 +91,7 @@ auto ParseAndAddQueueEntries(std::span<Byte const> queueEntries) -> void
DEBUG_PRINT("Start Time : %" PRIi32 "\n", value_of(entry.startTime));
DEBUG_PRINT("Timeout : %" PRIi16 "\n", entry.timeout);

edu::programQueue.push_back(entry);
edu::programQueue.PushBack(entry);
queueEntries = queueEntries.subspan<totalSerialSize<edu::ProgramQueueEntry>>();
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sts1CobcSw/CobcSoftware/EduCommunicationErrorThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class EduCommunicationErrorThread : public RODOS::StaticThread<stackSize>
{
SuspendUntil(endOfTime);

persistentVariables.template Increment<"eduCommunicationErrorCounter">();
persistentVariables.template Increment<"nEduCommunicationErrors">();

DEBUG_PRINT("[EduCommunicationErrorThread] Resetting the Edu\n");
// Reset EDU
Expand Down
2 changes: 1 addition & 1 deletion Sts1CobcSw/CobcSoftware/EduHeartbeatThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ auto EduIsAlive() -> bool
}
}

auto executionTime = CurrentRodosTime() - begin;
[[maybe_unused]] auto executionTime = CurrentRodosTime() - begin;
DEBUG_PRINT("Execution Time of EduIsAlive: %" PRIi64 " ns\n", executionTime / ns);
DEBUG_PRINT("Execution Time of EduIsAlive: %" PRIi64 " ms\n", executionTime / ms);
return false;
Expand Down
61 changes: 30 additions & 31 deletions Sts1CobcSw/CobcSoftware/EduProgramQueueThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
#include <Sts1CobcSw/Edu/Edu.hpp>
#include <Sts1CobcSw/Edu/ProgramQueue.hpp>
#include <Sts1CobcSw/Edu/ProgramStatusHistory.hpp>
#include <Sts1CobcSw/Edu/Types.hpp>
#include <Sts1CobcSw/FramSections/RingArray.hpp>
#include <Sts1CobcSw/FramSections/FramLayout.hpp>
#include <Sts1CobcSw/FramSections/FramRingArray.hpp>
#include <Sts1CobcSw/FramSections/FramVector.hpp>
#include <Sts1CobcSw/FramSections/PersistentVariables.hpp>
#include <Sts1CobcSw/ProgramId/ProgramId.hpp> // IWYU pragma: keep
#include <Sts1CobcSw/Utility/DebugPrint.hpp>
#include <Sts1CobcSw/Utility/RealTime.hpp>
Expand All @@ -19,14 +21,12 @@

#include <rodos_no_using_namespace.h>

#include <etl/vector.h>

#include <cinttypes> // IWYU pragma: keep


namespace sts1cobcsw
{
[[nodiscard]] auto ComputeStartDelay() -> Duration;
[[nodiscard]] auto ComputeStartDelay(RealTime startTime) -> Duration;


// TODO: Get a better estimation for the required stack size. We only have 128 kB of RAM.
Expand Down Expand Up @@ -56,32 +56,33 @@ class EduProgramQueueThread : public RODOS::StaticThread<stackSize>
// eduProgramQueue.push_back(queueEntry1);
// eduProgramQueue.push_back(queueEntry2);

DEBUG_PRINT("Size of EduProgramQueue : %zu\n", edu::programQueue.size());
DEBUG_PRINT("Size of EDU program queue = %" PRIu32 "\n", edu::programQueue.Size());
}

void run() override
{
// TODO: Define some DebugPrint() or something in a separate file that can be turned on/off
DEBUG_PRINT("Entering EduProgramQueueThread\n");
DEBUG_PRINT_REAL_TIME();
while(true)
{
if(edu::programQueue.empty())
if(edu::programQueue.IsEmpty())
{
DEBUG_PRINT("Edu Program Queue is empty, thread set to sleep until end of time\n");
SuspendUntil(endOfTime);
}
else if(edu::queueIndex >= edu::programQueue.size())
else if(persistentVariables.Load<"eduProgramQueueIndex">() >= edu::programQueue.Size())
{
DEBUG_PRINT("End of queue is reached, thread set to sleep until end of time\n");
SuspendUntil(endOfTime);
}

auto startDelay = ComputeStartDelay();
auto queueIndex = persistentVariables.Load<"eduProgramQueueIndex">();
auto queueEntry = edu::programQueue.Get(queueIndex);
auto startDelay = ComputeStartDelay(queueEntry.startTime);
nextProgramStartDelayTopic.publish(startDelay);

DEBUG_PRINT("Program at queue index %d will start in : %" PRIi64 " s\n",
edu::queueIndex,
queueIndex,
startDelay / s);

// Suspend until delay time - 2 seconds
Expand All @@ -92,8 +93,7 @@ class EduProgramQueueThread : public RODOS::StaticThread<stackSize>
DEBUG_PRINT("Resuming here after first wait.\n");
DEBUG_PRINT_REAL_TIME();

auto updateTimeResult =
edu::UpdateTime(edu::UpdateTimeData{.currentTime = CurrentRealTime()});
auto updateTimeResult = edu::UpdateTime({CurrentRealTime()});
if(updateTimeResult.has_error())
{
DEBUG_PRINT("UpdateTime error code : %d\n",
Expand All @@ -103,11 +103,15 @@ class EduProgramQueueThread : public RODOS::StaticThread<stackSize>
ResumeEduCommunicationErrorThread();
}

auto startDelay2 = ComputeStartDelay();
// Reload queue index and entry because the start delay might be very long and the
// variables might have been corrupted in the meantime
queueIndex = persistentVariables.Load<"eduProgramQueueIndex">();
queueEntry = edu::programQueue.Get(queueIndex);
auto startDelay2 = ComputeStartDelay(queueEntry.startTime);
nextProgramStartDelayTopic.publish(startDelay2);

DEBUG_PRINT("Program at queue index %d will start in : %" PRIi64 " s\n",
edu::queueIndex,
queueIndex,
startDelay2 / s);

// Suspend for delay a second time
Expand All @@ -118,14 +122,10 @@ class EduProgramQueueThread : public RODOS::StaticThread<stackSize>
// Never reached
DEBUG_PRINT("Done suspending for the second time\n");

auto startTime = edu::programQueue[edu::queueIndex].startTime;
auto programId = edu::programQueue[edu::queueIndex].programId;
auto timeout = edu::programQueue[edu::queueIndex].timeout;

DEBUG_PRINT("Executing program %" PRIu16 "\n", value_of(programId));
DEBUG_PRINT("Executing EDU program %" PRIu16 "\n", value_of(queueEntry.programId));
// Start Process
auto executeProgramResult = edu::ExecuteProgram(edu::ExecuteProgramData{
.programId = programId, .startTime = startTime, .timeout = timeout});
auto executeProgramResult = edu::ExecuteProgram(
{queueEntry.programId, queueEntry.startTime, queueEntry.timeout});
// errorCode = edu::ErrorCode::success;

if(executeProgramResult.has_error())
Expand All @@ -137,20 +137,19 @@ class EduProgramQueueThread : public RODOS::StaticThread<stackSize>
}
else
{
edu::programStatusHistory.PushBack(
edu::ProgramStatusHistoryEntry{.programId = programId,
.startTime = startTime,
.status = edu::ProgramStatus::programRunning});
edu::programStatusHistory.PushBack({queueEntry.programId,
queueEntry.startTime,
edu::ProgramStatus::programRunning});

// Suspend Self for execution time
auto const executionTime = timeout * s + eduCommunicationDelay;
auto const executionTime = queueEntry.timeout * s + eduCommunicationDelay;
DEBUG_PRINT("Suspending for execution time\n");
SuspendFor(executionTime);
DEBUG_PRINT("Resuming from execution time\n");
DEBUG_PRINT_REAL_TIME();

// Set current Queue ID to next
edu::queueIndex++;
// Set current queue ID to next
persistentVariables.Increment<"eduProgramQueueIndex">();
}
}
}
Expand All @@ -160,9 +159,9 @@ class EduProgramQueueThread : public RODOS::StaticThread<stackSize>
// TODO: We should just use time points instead of delays in the thread. Then we won't need this
// function.
//! Compute the delay in nanoseconds before the start of program at current queue index
auto ComputeStartDelay() -> Duration
auto ComputeStartDelay(RealTime startTime) -> Duration
{
auto delay = ToRodosTime(edu::programQueue[edu::queueIndex].startTime) - CurrentRodosTime();
auto delay = ToRodosTime(startTime) - CurrentRodosTime();
return delay < Duration(0) ? Duration(0) : delay;
}

Expand Down
2 changes: 2 additions & 0 deletions Sts1CobcSw/Edu/EduMock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include <Sts1CobcSw/Edu/Types.hpp>
#include <Sts1CobcSw/Utility/DebugPrint.hpp>

#include <strong_type/type.hpp>

#include <cinttypes> // IWYU pragma: keep


Expand Down
8 changes: 5 additions & 3 deletions Sts1CobcSw/Edu/ProgramQueue.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#include <Sts1CobcSw/Edu/ProgramQueue.hpp>


// TODO: Change namespace here too, or move it back to Sts1CobSw/
namespace sts1cobcsw::edu
{
using sts1cobcsw::DeserializeFrom;
using sts1cobcsw::SerializeTo;


etl::vector<ProgramQueueEntry, nProgramQueueEntries> programQueue{};
std::uint16_t queueIndex = 0;
sts1cobcsw::
FramVector<ProgramQueueEntry, framSections.Get<"eduProgramQueue">(), nCachedProgramQueueEntries>
programQueue;


template<std::endian endianness>
Expand All @@ -21,6 +21,7 @@ auto DeserializeFrom(void const * source, ProgramQueueEntry * data) -> void cons
return source;
}


// Explicit template specializations to keep everything in .cpp file
template auto DeserializeFrom<std::endian::big>(void const *, ProgramQueueEntry *) -> void const *;
template auto DeserializeFrom<std::endian::little>(void const *, ProgramQueueEntry *)
Expand All @@ -36,6 +37,7 @@ auto SerializeTo(void * destination, ProgramQueueEntry const & data) -> void *
return destination;
}


// Explicit template specializations to keep everything in .cpp file
template auto SerializeTo<std::endian::big>(void *, ProgramQueueEntry const &) -> void *;
template auto SerializeTo<std::endian::little>(void *, ProgramQueueEntry const &) -> void *;
Expand Down
18 changes: 6 additions & 12 deletions Sts1CobcSw/Edu/ProgramQueue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@


#include <Sts1CobcSw/FramSections/FramLayout.hpp>
#include <Sts1CobcSw/FramSections/Section.hpp>
#include <Sts1CobcSw/FramSections/FramVector.hpp>
#include <Sts1CobcSw/FramSections/Subsections.hpp>
#include <Sts1CobcSw/ProgramId/ProgramId.hpp>
#include <Sts1CobcSw/Serial/Serial.hpp>
#include <Sts1CobcSw/Utility/TimeTypes.hpp>

#include <strong_type/type.hpp>

#include <etl/vector.h>

#include <bit>
#include <cstddef>
#include <cstdint>
Expand Down Expand Up @@ -39,13 +35,11 @@ inline constexpr std::size_t serialSize<edu::ProgramQueueEntry> =

namespace edu
{
inline constexpr auto nProgramQueueEntries =
value_of(framSections.template Get<"eduProgramQueue">().size)
/ totalSerialSize<ProgramQueueEntry>;


extern std::uint16_t queueIndex;
extern etl::vector<ProgramQueueEntry, nProgramQueueEntries> programQueue;
inline constexpr auto nCachedProgramQueueEntries = 10;
extern FramVector<ProgramQueueEntry,
framSections.template Get<"eduProgramQueue">(),
nCachedProgramQueueEntries>
programQueue;


template<std::endian endianness>
Expand Down
18 changes: 9 additions & 9 deletions Sts1CobcSw/Edu/ProgramStatusHistory.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
#include <Sts1CobcSw/Edu/ProgramStatusHistory.hpp>
#include <Sts1CobcSw/FramSections/FramLayout.hpp>
#include <Sts1CobcSw/FramSections/RingArray.hpp>

#include <strong_type/equality.hpp>

#include <etl/circular_buffer.h>


namespace sts1cobcsw::edu
{
sts1cobcsw::RingArray<ProgramStatusHistoryEntry,
framSections.Get<"eduProgramStatusHistory">(),
nCachedProgramStatusHistoryEntries>
using sts1cobcsw::DeserializeFrom;
using sts1cobcsw::SerializeTo;


sts1cobcsw::FramRingArray<ProgramStatusHistoryEntry,
framSections.Get<"eduProgramStatusHistory">(),
nCachedProgramStatusHistoryEntries>
programStatusHistory;


Expand All @@ -23,10 +27,6 @@ auto UpdateProgramStatusHistory(ProgramId programId, RealTime startTime, Program
}


using sts1cobcsw::DeserializeFrom;
using sts1cobcsw::SerializeTo;


template<std::endian endianness>
auto DeserializeFrom(void const * source, ProgramStatusHistoryEntry * data) -> void const *
{
Expand Down
10 changes: 5 additions & 5 deletions Sts1CobcSw/Edu/ProgramStatusHistory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


#include <Sts1CobcSw/FramSections/FramLayout.hpp>
#include <Sts1CobcSw/FramSections/RingArray.hpp>
#include <Sts1CobcSw/FramSections/FramRingArray.hpp>
#include <Sts1CobcSw/FramSections/Subsections.hpp>
#include <Sts1CobcSw/ProgramId/ProgramId.hpp>
#include <Sts1CobcSw/Serial/Serial.hpp>
Expand Down Expand Up @@ -49,12 +49,12 @@ inline constexpr std::size_t serialSize<edu::ProgramStatusHistoryEntry> =
namespace edu
{
inline constexpr auto nCachedProgramStatusHistoryEntries = 10;

extern RingArray<ProgramStatusHistoryEntry,
framSections.template Get<"eduProgramStatusHistory">(),
nCachedProgramStatusHistoryEntries>
extern FramRingArray<ProgramStatusHistoryEntry,
framSections.template Get<"eduProgramStatusHistory">(),
nCachedProgramStatusHistoryEntries>
programStatusHistory;


auto UpdateProgramStatusHistory(ProgramId programId, RealTime startTime, ProgramStatus newStatus)
-> void;

Expand Down
10 changes: 7 additions & 3 deletions Sts1CobcSw/FramSections/FramLayout.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,22 @@ namespace sts1cobcsw
inline constexpr auto framMemory = Section<fram::Address(0), fram::memorySize>{};
inline constexpr auto framSections =
Subsections<framMemory,
SubsectionInfo<"persistentVariables0", fram::Size(300)>,
SubsectionInfo<"persistentVariables", fram::Size(300)>,
SubsectionInfo<"eduProgramQueue", fram::Size(20 * 8)>,
SubsectionInfo<"eduProgramStatusHistory", fram::Size(50 * 7)>,
SubsectionInfo<"testMemory", fram::Size(1000)>,
SubsectionInfo<"telemetry", fram::Size(26'168 * 40)>>{};
inline constexpr auto persistentVariables =
PersistentVariables<framSections.Get<"persistentVariables0">(),
PersistentVariables<framSections.Get<"persistentVariables">(),
// Bootloader
PersistentVariableInfo<"nResetsSinceRf", std::uint16_t>,
PersistentVariableInfo<"activeSecondaryFwPartition", std::int8_t>,
PersistentVariableInfo<"backupSecondaryFwPartition", std::int8_t>,
// COBC state
PersistentVariableInfo<"txIsOn", bool>,
PersistentVariableInfo<"antennasShouldBeDeployed", bool>,
PersistentVariableInfo<"eduProgramQueueIndex", std::uint8_t>,
// Housekeeping
PersistentVariableInfo<"nTotalResets", std::uint32_t>,
PersistentVariableInfo<"realTime", RealTime>,
PersistentVariableInfo<"realTimeOffset", Duration>,
Expand All @@ -37,5 +41,5 @@ inline constexpr auto persistentVariables =
PersistentVariableInfo<"nRfErrors", std::uint16_t>,
PersistentVariableInfo<"nFileSystemErrors", std::uint16_t>,
PersistentVariableInfo<"eduShouldBePowered", bool>,
PersistentVariableInfo<"eduCommunicationErrorCounter", std::uint16_t>>{};
PersistentVariableInfo<"nEduCommunicationErrors", std::uint16_t>>{};
}
Loading
Loading