Skip to content

Commit

Permalink
Rework Edu.cpp and edu error codes
Browse files Browse the repository at this point in the history
Remove edu::ErrorCode::success/successEof/noErrorCodeSet and modify
related files accordingly, sometimes by getting rid of do-while loops.
  • Loading branch information
jeromehue committed Nov 11, 2023
1 parent 7ed19bb commit d4bd1f7
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 68 deletions.
121 changes: 78 additions & 43 deletions Sts1CobcSw/Edu/Edu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ auto SendCommand(Byte commandId) -> void;
auto FlushUartBuffer() -> void;
[[nodiscard]] auto CheckCrc32(std::span<Byte> data) -> Result<void>;
[[nodiscard]] auto GetStatusCommunication() -> Result<Status>;
[[nodiscard]] auto ReturnResultCommunication() -> Result<ts::size_t>;
[[nodiscard]] auto ReturnResultRetry() -> Result<ts::size_t>;
[[nodiscard]] auto ReturnResultCommunication() -> Result<ResultInfo>;
[[nodiscard]] auto ReturnResultRetry() -> Result<ResultInfo>;

void MockWriteToFile(std::span<Byte> data);
auto Print(std::span<Byte> data, int nRows = 30) -> void; // NOLINT
Expand Down Expand Up @@ -224,42 +224,41 @@ auto GetStatus() -> Result<Status>
auto serialData = Serialize(getStatusId);
OUTCOME_TRY(SendData(serialData));

Result<Status> status = ErrorCode::noErrorCodeSet;
std::size_t errorCount = 0;
do

while(true)
{
status = GetStatusCommunication();
if(status.has_value())
auto status = GetStatusCommunication();
if(status)
{
SendCommand(cmdAck);
break;
RODOS::PRINTF(
" .statusType = %d\n .programId = %d\n .queueId = %d\n exitCode = "
"%d\n",
status.value().statusType,
status.value().programId,
status.value().queueId,
status.value().exitCode);
return status;
}

// Error in GetStatusCommunication()
FlushUartBuffer();
SendCommand(cmdNack);
} while(errorCount++ < maxNNackRetries);
errorCount++;

if(status.has_value())
{
RODOS::PRINTF(
" .statusType = %d\n .programId = %d\n .queueId = %d\n exitCode = "
"%d\n",
status.value().statusType,
status.value().programId,
status.value().queueId,
status.value().exitCode);
}
else
{
RODOS::PRINTF(" .errorCode = %d\n", status.error());
if(errorCount >= maxNNackRetries)
{
RODOS::PRINTF(" .errorCode = %d\n", status.error());
return status.error();
}
}
return status;
}


//! @brief Communication function for GetStatus() to separate a single try from
//! retry logic.
//! @returns The received EDU status
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
auto GetStatusCommunication() -> Result<Status>
{
// Get header data
Expand Down Expand Up @@ -352,7 +351,7 @@ auto GetStatusCommunication() -> Result<Status>
}


auto ReturnResult() -> Result<ts::size_t>
auto ReturnResult() -> Result<ResultInfo>
{
// DEBUG
RODOS::PRINTF("ReturnResult()\n");
Expand All @@ -372,62 +371,97 @@ auto ReturnResult() -> Result<ts::size_t>

ts::size_t totalResultSize = 0_usize;
ts::size_t packets = 0_usize;
Result<ts::size_t> resultInfo = ErrorCode::noErrorCodeSet;
// TODO: Turn into for loop
// Result<ResultInfo> resultInfo = ErrorCode::noErrorCodeSet;
// TODO: Turn into for loop
while(packets < maxNPackets)
{
// DEBUG
// RODOS::PRINTF("\nPacket %d\n", static_cast<int>(packets.get()));
// END DEBUG
resultInfo = ReturnResultRetry();
auto resultInfo = ReturnResultRetry();
// TYPE Result<something>
// DEBUG

// Break if returned an error or reached EOF
if(resultInfo.has_error())
{
auto errorCode = resultInfo.error();
RODOS::PRINTF(" ResultResultRetry() resulted in an error : %d",
static_cast<int>(errorCode));
break;
return resultInfo.error();
}
if(resultInfo.value().reachedEof)
{
RODOS::PRINTF(" ResultResultRetry() reached EOF\n");
return {/*reachedEof*/ true, totalResultSize};
}

// END DEBUG
// RODOS::PRINTF("\nWriting to file...\n");
// TODO: Actually write to a file

totalResultSize += resultInfo.value();
totalResultSize += resultInfo.value().resultSize;
packets++;
}
return totalResultSize;
return {false, totalResultSize};
}


//! @brief This function handles the retry logic for a single transmission round and is called by
//! the actual ReturnResult function. The communication happens in ReturnResultCommunication.
//!
//! @returns An error code and the number of received bytes in ResultInfo
auto ReturnResultRetry() -> Result<ts::size_t>
auto ReturnResultRetry() -> Result<ResultInfo>
{
Result<ts::size_t> result = ErrorCode::noErrorCodeSet;
std::size_t errorCount = 0U;
do

// TODO: infinite loop could be avoided by setting
// errorCount <= maxNNackRetries as the termination condition
while(true)
{
result = ReturnResultCommunication();
// TODO: That is ugly, maybe a successCommunicationEnum would be better
if(result.has_value() or (result.has_error() and result.error() == ErrorCode::successEof))
auto resultInfo = ReturnResultCommunication();
if(resultInfo.has_value())
{
SendCommand(cmdNack);
return result;
SendCommand(cmdAck);
// returns {reachedEof, resultSize}
return resultInfo.value();
}

// Error in ReturnResultCommunication()
FlushUartBuffer();
SendCommand(cmdNack);
} while(errorCount++ < maxNNackRetries);
return result.value();
errorCount++;
if(errorCount == maxNNackRetries)
{
return resultInfo.error();
}
}


// Result<ResultInfo> result = ErrorCode::noErrorCodeSet;
// std::size_t errorCount = 0U;
// // TODO: CHange this
// do
// {
// result = ReturnResultCommunication();
// // Could have reached EOF or not
// if(result.has_value())
// {
// SendCommand(cmdAck);
// return result;
// }
// FlushUartBuffer();
// SendCommand(cmdNack);
// } while(errorCount++ < maxNNackRetries);
// return result.value();
}


// This function writes the result to the COBC file system (flash). Maybe it doesn't do that
// directly and instead writes to a non-primary RAM bank as an intermediate step.
//
// Simple results -> 1 round should work with DMA to RAM
auto ReturnResultCommunication() -> Result<ts::size_t>
auto ReturnResultCommunication() -> Result<edu::ResultInfo>
{
// Receive command
// If no result is available, the command will be NACK,
Expand All @@ -445,7 +479,7 @@ auto ReturnResultCommunication() -> Result<ts::size_t>
}
if(command == cmdEof)
{
return ErrorCode::successEof;
return {/*reachedEof*/ true, 0_usize};
}
if(command != cmdData)
{
Expand Down Expand Up @@ -476,6 +510,7 @@ auto ReturnResultCommunication() -> Result<ts::size_t>
auto dataError = UartReceive(
std::span<Byte>(cepDataBuffer.begin(), cepDataBuffer.begin() + actualDataLength.get()));

// TODO: OUTCOME_TRY
if(dataError.has_error())
{
return dataError.error();
Expand All @@ -497,7 +532,7 @@ auto ReturnResultCommunication() -> Result<ts::size_t>
RODOS::PRINTF("\nSuccess\n");
// END DEBUG

return actualDataLength;
return {false, actualDataLength};
}


Expand Down
2 changes: 1 addition & 1 deletion Sts1CobcSw/Edu/Edu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ auto TurnOff() -> void;
[[nodiscard]] auto StopProgram() -> Result<void>;
// TODD: Find better name (or maybe even mechanism) for GetStatus
[[nodiscard]] auto GetStatus() -> Result<Status>;
[[nodiscard]] auto ReturnResult() -> Result<ts::size_t>;
[[nodiscard]] auto ReturnResult() -> Result<ResultInfo>;
[[nodiscard]] auto UpdateTime(UpdateTimeData const & data) -> Result<void>;
}
15 changes: 7 additions & 8 deletions Sts1CobcSw/Edu/EduMock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ auto ExecuteProgram(ExecuteProgramData const & data) -> Result<void>
data.programId.get(),
data.queueId.get(),
data.timeout.get());
return ErrorCode::success;
return outcome_v2::success();
}


Expand All @@ -75,7 +75,7 @@ auto StopProgram() -> Result<void>
{
PrintFormattedSystemUtc();
PRINTF("Call to StopProgram()\n");
return ErrorCode::success;
return outcome_v2::success();
}


Expand All @@ -94,8 +94,7 @@ auto UpdateTime(UpdateTimeData const & data) -> Result<void>
{
PrintFormattedSystemUtc();
PRINTF("Call to UpdateTime(timestamp = %d)\n", data.timestamp.get());
// FIXME: Return outcome::success
return ErrorCode::success;
return outcome_v2::success();
}


Expand All @@ -108,20 +107,20 @@ auto SendCommand(Byte commandId) -> void


// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
auto SendData(std::span<Byte> data) -> ErrorCode
auto SendData(std::span<Byte> data) -> Result<void>
{
PrintFormattedSystemUtc();
PRINTF("Call to SendData(size(data) = %d)\n", size(data));
return ErrorCode::success;
return outcome_v2::success();
}


// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
auto UartReceive([[maybe_unused]] std::span<Byte> destination) -> ErrorCode
auto UartReceive([[maybe_unused]] std::span<Byte> destination) -> Result<void>
{
PrintFormattedSystemUtc();
PRINTF("Call to UartReceive(size(destination) = %d)\n", size(destination));
return ErrorCode::success;
return outcome_v2::success();
}


Expand Down
5 changes: 1 addition & 4 deletions Sts1CobcSw/Edu/Enums.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ namespace sts1cobcsw::edu
{
enum class ErrorCode
{
noErrorCodeSet,
success,
successEof,
invalidResult,
invalidResult = 1,
bufferTooSmall,
uartNotInitialized,
timeout,
Expand Down
2 changes: 1 addition & 1 deletion Sts1CobcSw/Edu/Structs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ struct ProgramFinishedStatus

struct ResultInfo
{
ErrorCode errorCode = ErrorCode::noErrorCodeSet;
bool reachedEof = false;
ts::size_t resultSize = 0_usize;
};
}
Expand Down
1 change: 1 addition & 0 deletions Sts1CobcSw/EduListenerThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class EduListenerThread : public RODOS::StaticThread<>
}


// NOLINTNEXTLINE(readability-function-cognitive-complexity)
void run() override
{
TIME_LOOP(0, timeLoopPeriod)
Expand Down
51 changes: 40 additions & 11 deletions Tests/HardwareTests/EduCommandTests/EduCommands.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,14 @@ class EduCommandsTest : public RODOS::StaticThread<>
auto timestamp = utility::GetUnixUtc();
PRINTF("Sending UpdateTime(timestamp = %d)\n", static_cast<int>(timestamp));
auto errorCode = edu::UpdateTime({.timestamp = timestamp});
PRINTF("Returned error code: %d\n", static_cast<int>(errorCode));
if(errorCode.has_error())
{
PRINTF("Returned error code: %d\n", static_cast<int>(errorCode.error()));
}
else
{
PRINTF("UpdateTime executed successfully\n");
}
break;
}
case 'e':
Expand Down Expand Up @@ -92,28 +99,50 @@ class EduCommandsTest : public RODOS::StaticThread<>
static_cast<int>(timeout));
auto errorCode = edu::ExecuteProgram(
{.programId = programId, .queueId = queueId, .timeout = timeout});
PRINTF("Returned error code: %d\n", static_cast<int>(errorCode));
// TODO: Fix naming
if(errorCode.has_error())
{
PRINTF("Returned error code: %d\n", static_cast<int>(errorCode.error()));
}
else
{
PRINTF("Execute Program Returned no error");
}
break;
}
case 'g':
{
PRINTF("Sending GetStatus()\n");
auto status = edu::GetStatus();
auto statusResult = edu::GetStatus();
PRINTF("Returned status:\n");
PRINTF(" type = %d\n", static_cast<int>(status.statusType));
PRINTF(" program ID = %d\n", static_cast<int>(status.programId));
PRINTF(" queue ID = %d\n", static_cast<int>(status.queueId));
PRINTF(" exit code = %d\n", static_cast<int>(status.exitCode));
PRINTF(" error code = %d\n", static_cast<int>(status.errorCode));
if(statusResult.has_error())
{
PRINTF(" error code = %d\n", static_cast<int>(statusResult.error()));
}
else
{
auto status = statusResult.value();
PRINTF(" type = %d\n", static_cast<int>(status.statusType));
PRINTF(" program ID = %d\n", static_cast<int>(status.programId));
PRINTF(" queue ID = %d\n", static_cast<int>(status.queueId));
PRINTF(" exit code = %d\n", static_cast<int>(status.exitCode));
}
break;
}
case 'r':
{
PRINTF("Sending ReturnResult()\n");
auto resultInfo = edu::ReturnResult();
auto resultStatus = edu::ReturnResult();
PRINTF("Returned result info:\n");
PRINTF(" error code = %d\n", static_cast<int>(resultInfo.errorCode));
PRINTF(" result size = %d\n", static_cast<int>(resultInfo.resultSize.get()));
if(resultStatus.has_error())
{
PRINTF(" error code = %d\n", static_cast<int>(resultStatus.error()));
}
else
{
PRINTF(" result size = %d\n",
static_cast<int>(resultStatus.value().resultSize.get()));
}
break;
}
default:
Expand Down

0 comments on commit d4bd1f7

Please sign in to comment.