diff --git a/CHANGELOG.md b/CHANGELOG.md index 054a5788..92a199f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,11 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +## Changed + +- Rewrote the PLOC Supervisor Handler, which is now based on a new device handler base class. + Added ADC and Logging Counters telemetry set support. + ## Fixed - Increase allowed time for PTME writers to finish partial transfers. A duration of 200 ms was diff --git a/linux/payload/PlocSupervisorHandler.cpp b/archive/PlocSupervisorHandler.cpp similarity index 91% rename from linux/payload/PlocSupervisorHandler.cpp rename to archive/PlocSupervisorHandler.cpp index 3863caea..67ec707f 100644 --- a/linux/payload/PlocSupervisorHandler.cpp +++ b/archive/PlocSupervisorHandler.cpp @@ -19,8 +19,6 @@ using namespace supv; using namespace returnvalue; -std::atomic_bool supv::SUPV_ON = false; - PlocSupervisorHandler::PlocSupervisorHandler(object_id_t objectId, CookieIF* comCookie, Gpio uartIsolatorSwitch, power::Switch_t powerSwitch, PlocSupvUartManager& supvHelper) @@ -29,7 +27,7 @@ PlocSupervisorHandler::PlocSupervisorHandler(object_id_t objectId, CookieIF* com hkset(this), bootStatusReport(this), latchupStatusReport(this), - loggingReport(this), + countersReport(this), adcReport(this), powerSwitch(powerSwitch), uartManager(supvHelper) { @@ -61,6 +59,19 @@ ReturnValue_t PlocSupervisorHandler::initialize() { } void PlocSupervisorHandler::performOperationHook() { + if (normalCommandIsPending and normalCmdCd.hasTimedOut()) { + // Event, FDIR, printout? Leads to spam though and normally should not happen.. + normalCommandIsPending = false; + } + if (commandIsPending and cmdCd.hasTimedOut()) { + // Event, FDIR, printout? Leads to spam though and normally should not happen.. + commandIsPending = false; + + // if(iter->second.sendReplyTo != NO_COMMANDER) { + // actionHelper.finish(true, iter->second.sendReplyTo, iter->first, returnvalue::OK); + // } + disableAllReplies(); + } EventMessage event; for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK; result = eventQueue->receiveMessage(&event)) { @@ -172,13 +183,16 @@ void PlocSupervisorHandler::doShutDown() { nextReplyId = supv::NONE; uartManager.stop(); uartIsolatorSwitch.pullLow(); + disableAllReplies(); supv::SUPV_ON = false; startupState = StartupState::OFF; } ReturnValue_t PlocSupervisorHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { - if (not commandIsExecuting(GET_HK_REPORT)) { + if (not normalCommandIsPending) { *id = GET_HK_REPORT; + normalCommandIsPending = true; + normalCmdCd.resetTimer(); return buildCommandFromCommand(*id, nullptr, 0); } return NOTHING_TO_SEND; @@ -274,8 +288,7 @@ ReturnValue_t PlocSupervisorHandler::buildCommandFromCommand(DeviceCommandId_t d break; } case SET_GPIO: { - prepareSetGpioCmd(commandData); - result = returnvalue::OK; + result = prepareSetGpioCmd(commandData, commandDataLen); break; } case FACTORY_RESET: { @@ -283,8 +296,7 @@ ReturnValue_t PlocSupervisorHandler::buildCommandFromCommand(DeviceCommandId_t d break; } case READ_GPIO: { - prepareReadGpioCmd(commandData); - result = returnvalue::OK; + result = prepareReadGpioCmd(commandData, commandDataLen); break; } case SET_SHUTDOWN_TIMEOUT: { @@ -321,12 +333,25 @@ ReturnValue_t PlocSupervisorHandler::buildCommandFromCommand(DeviceCommandId_t d result = prepareWipeMramCmd(commandData); break; } + case REQUEST_ADC_REPORT: { + prepareEmptyCmd(Apid::ADC_MON, static_cast(tc::AdcMonId::REQUEST_ADC_SAMPLE)); + result = returnvalue::OK; + break; + } + case REQUEST_LOGGING_COUNTERS: { + prepareEmptyCmd(Apid::DATA_LOGGER, + static_cast(tc::DataLoggerServiceId::REQUEST_COUNTERS)); + result = returnvalue::OK; + break; + } default: sif::debug << "PlocSupervisorHandler::buildCommandFromCommand: Command not implemented" << std::endl; result = DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; break; } + commandIsPending = true; + cmdCd.resetTimer(); return result; } @@ -358,6 +383,8 @@ void PlocSupervisorHandler::fillCommandAndReplyMap() { insertInCommandMap(SET_ADC_THRESHOLD); insertInCommandMap(SET_ADC_WINDOW_AND_STRIDE); insertInCommandMap(RESET_PL); + insertInCommandMap(REQUEST_ADC_REPORT); + insertInCommandMap(REQUEST_LOGGING_COUNTERS); // ACK replies, use countdown for them insertInReplyMap(ACK_REPORT, 0, nullptr, SIZE_ACK_REPORT, false, &acknowledgementReportTimeout); @@ -368,7 +395,7 @@ void PlocSupervisorHandler::fillCommandAndReplyMap() { insertInReplyMap(HK_REPORT, 3, &hkset); insertInReplyMap(BOOT_STATUS_REPORT, 3, &bootStatusReport, SIZE_BOOT_STATUS_REPORT); insertInReplyMap(LATCHUP_REPORT, 3, &latchupStatusReport, SIZE_LATCHUP_STATUS_REPORT); - insertInReplyMap(LOGGING_REPORT, 3, &loggingReport, SIZE_LOGGING_REPORT); + insertInReplyMap(COUNTERS_REPORT, 3, &countersReport, SIZE_COUNTERS_REPORT); insertInReplyMap(ADC_REPORT, 3, &adcReport, SIZE_ADC_REPORT); } @@ -410,13 +437,13 @@ ReturnValue_t PlocSupervisorHandler::enableReplyInReplyMap(DeviceCommandMap::ite } break; } - case LOGGING_REQUEST_COUNTERS: { + case REQUEST_LOGGING_COUNTERS: { enabledReplies = 3; result = - DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, LOGGING_REPORT); + DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, COUNTERS_REPORT); if (result != returnvalue::OK) { sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " - << LOGGING_REPORT << " not in replyMap" << std::endl; + << COUNTERS_REPORT << " not in replyMap" << std::endl; } break; } @@ -541,6 +568,9 @@ ReturnValue_t PlocSupervisorHandler::scanForReply(const uint8_t* start, size_t r } case (Apid::HK): { if (tmReader.getServiceId() == static_cast(supv::tm::HkId::REPORT)) { + normalCommandIsPending = false; + // Yeah apparently this is needed?? + disableCommand(GET_HK_REPORT); *foundLen = tmReader.getFullPacketLen(); *foundId = ReplyId::HK_REPORT; return OK; @@ -559,6 +589,14 @@ ReturnValue_t PlocSupervisorHandler::scanForReply(const uint8_t* start, size_t r } break; } + case (Apid::ADC_MON): { + if (tmReader.getServiceId() == static_cast(supv::tm::AdcMonId::ADC_REPORT)) { + *foundLen = tmReader.getFullPacketLen(); + *foundId = ReplyId::ADC_REPORT; + return OK; + } + break; + } case (Apid::MEM_MAN): { if (tmReader.getServiceId() == static_cast(supv::tm::MemManId::UPDATE_STATUS_REPORT)) { @@ -566,6 +604,15 @@ ReturnValue_t PlocSupervisorHandler::scanForReply(const uint8_t* start, size_t r *foundId = ReplyId::UPDATE_STATUS_REPORT; return OK; } + break; + } + case (Apid::DATA_LOGGER): { + if (tmReader.getServiceId() == + static_cast(supv::tm::DataLoggerId::COUNTERS_REPORT)) { + *foundLen = tmReader.getFullPacketLen(); + *foundId = ReplyId::COUNTERS_REPORT; + return OK; + } } } handleBadApidServiceCombination(SUPV_UNKNOWN_TM, apid, tmReader.getServiceId()); @@ -578,6 +625,14 @@ void PlocSupervisorHandler::handlePacketPrint() { if ((tmReader.getServiceId() == static_cast(supv::tm::TmtcId::ACK)) or (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::NAK))) { AcknowledgmentReport ack(tmReader); + ReturnValue_t result = ack.parse(); + if (result != returnvalue::OK) { + sif::warning << "PlocSupervisorHandler: Parsing ACK failed" << std::endl; + } + if (REDUCE_NORMAL_MODE_PRINTOUT and ack.getRefModuleApid() == (uint8_t)supv::Apid::HK and + ack.getRefServiceId() == (uint8_t)supv::tc::HkId::GET_REPORT) { + return; + } const char* printStr = "???"; if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::ACK)) { printStr = "ACK"; @@ -592,7 +647,15 @@ void PlocSupervisorHandler::handlePacketPrint() { } else if ((tmReader.getServiceId() == static_cast(supv::tm::TmtcId::EXEC_ACK)) or (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::EXEC_NAK))) { ExecutionReport exe(tmReader); + ReturnValue_t result = exe.parse(); + if (result != returnvalue::OK) { + sif::warning << "PlocSupervisorHandler: Parsing EXE failed" << std::endl; + } const char* printStr = "???"; + if (REDUCE_NORMAL_MODE_PRINTOUT and exe.getRefModuleApid() == (uint8_t)supv::Apid::HK and + exe.getRefServiceId() == (uint8_t)supv::tc::HkId::GET_REPORT) { + return; + } if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::EXEC_ACK)) { printStr = "ACK EXE"; @@ -627,12 +690,22 @@ ReturnValue_t PlocSupervisorHandler::interpretDeviceReply(DeviceCommandId_t id, result = handleBootStatusReport(packet); break; } + case (COUNTERS_REPORT): { + result = genericHandleTm("COUNTERS", packet, countersReport); +#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_PLOC_SUPERVISOR == 1 + countersReport.printSet(); +#endif + break; + } case (LATCHUP_REPORT): { result = handleLatchupStatusReport(packet); break; } case (ADC_REPORT): { - result = handleAdcReport(packet); + result = genericHandleTm("ADC", packet, adcReport); +#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_PLOC_SUPERVISOR == 1 + adcReport.printSet(); +#endif break; } case (EXE_REPORT): { @@ -697,13 +770,8 @@ ReturnValue_t PlocSupervisorHandler::initializeLocalDataPool(localpool::DataPool localDataPoolMap.emplace(supv::LATCHUP_RPT_TIME_YEAR, new PoolEntry({0})); localDataPoolMap.emplace(supv::LATCHUP_RPT_IS_SET, new PoolEntry({0})); - localDataPoolMap.emplace(supv::LATCHUP_HAPPENED_CNT_0, new PoolEntry({0})); - localDataPoolMap.emplace(supv::LATCHUP_HAPPENED_CNT_1, new PoolEntry({0})); - localDataPoolMap.emplace(supv::LATCHUP_HAPPENED_CNT_2, new PoolEntry({0})); - localDataPoolMap.emplace(supv::LATCHUP_HAPPENED_CNT_3, new PoolEntry({0})); - localDataPoolMap.emplace(supv::LATCHUP_HAPPENED_CNT_4, new PoolEntry({0})); - localDataPoolMap.emplace(supv::LATCHUP_HAPPENED_CNT_5, new PoolEntry({0})); - localDataPoolMap.emplace(supv::LATCHUP_HAPPENED_CNT_6, new PoolEntry({0})); + localDataPoolMap.emplace(supv::SIGNATURE, new PoolEntry()); + localDataPoolMap.emplace(supv::LATCHUP_HAPPENED_CNTS, &latchupCounters); localDataPoolMap.emplace(supv::ADC_DEVIATION_TRIGGERS_CNT, new PoolEntry({0})); localDataPoolMap.emplace(supv::TC_RECEIVED_CNT, new PoolEntry({0})); localDataPoolMap.emplace(supv::TM_AVAILABLE_CNT, new PoolEntry({0})); @@ -712,41 +780,22 @@ ReturnValue_t PlocSupervisorHandler::initializeLocalDataPool(localpool::DataPool localDataPoolMap.emplace(supv::MPSOC_BOOT_FAILED_ATTEMPTS, new PoolEntry({0})); localDataPoolMap.emplace(supv::MPSOC_POWER_UP, new PoolEntry({0})); localDataPoolMap.emplace(supv::MPSOC_UPDATES, new PoolEntry({0})); - localDataPoolMap.emplace(supv::LAST_RECVD_TC, new PoolEntry({0})); + localDataPoolMap.emplace(supv::MPSOC_HEARTBEAT_RESETS, new PoolEntry({0})); + localDataPoolMap.emplace(supv::CPU_WDT_RESETS, new PoolEntry({0})); + localDataPoolMap.emplace(supv::PS_HEARTBEATS_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::PL_HEARTBEATS_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::EB_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::BM_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::LM_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::AM_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::TCTMM_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::MM_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::HK_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::DL_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::RWS_TASKS_LOST, new PoolEntry(3)); - localDataPoolMap.emplace(supv::ADC_RAW_0, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_1, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_2, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_3, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_4, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_5, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_6, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_7, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_8, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_9, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_10, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_11, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_12, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_13, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_14, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_RAW_15, new PoolEntry({0})); - - localDataPoolMap.emplace(supv::ADC_ENG_0, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_1, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_2, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_3, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_4, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_5, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_6, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_7, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_8, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_9, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_10, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_11, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_12, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_13, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_14, new PoolEntry({0})); - localDataPoolMap.emplace(supv::ADC_ENG_15, new PoolEntry({0})); + localDataPoolMap.emplace(supv::ADC_RAW, &adcRawEntry); + localDataPoolMap.emplace(supv::ADC_ENG, &adcEngEntry); poolManager.subscribeForRegularPeriodicPacket( subdp::RegularHkPeriodicParams(hkset.getSid(), false, 10.0)); @@ -871,6 +920,7 @@ ReturnValue_t PlocSupervisorHandler::handleExecutionReport(const uint8_t* data) } else if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::EXEC_NAK)) { handleExecutionFailureReport(report); } + commandIsPending = false; nextReplyId = supv::NONE; return result; } @@ -1105,37 +1155,31 @@ ReturnValue_t PlocSupervisorHandler::handleLatchupStatusReport(const uint8_t* da return result; } -ReturnValue_t PlocSupervisorHandler::handleAdcReport(const uint8_t* data) { +ReturnValue_t PlocSupervisorHandler::genericHandleTm(const char* contextString, const uint8_t* data, + LocalPoolDataSetBase& set) { ReturnValue_t result = returnvalue::OK; - result = verifyPacket(data, supv::SIZE_ADC_REPORT); + result = verifyPacket(data, tmReader.getFullPacketLen()); if (result == result::CRC_FAILURE) { - sif::error << "PlocSupervisorHandler::handleAdcReport: ADC report has " - << "invalid crc" << std::endl; + sif::warning << "PlocSupervisorHandler: " << contextString << " report has " + << "invalid CRC" << std::endl; return result; } const uint8_t* dataField = data + supv::PAYLOAD_OFFSET; - result = adcReport.read(); - if (result != returnvalue::OK) { + PoolReadGuard pg(&set); + if (pg.getReadResult() != returnvalue::OK) { return result; } - adcReport.setValidityBufferGeneration(false); - size_t size = adcReport.getSerializedSize(); - result = adcReport.deSerialize(&dataField, &size, SerializeIF::Endianness::BIG); + set.setValidityBufferGeneration(false); + size_t size = set.getSerializedSize(); + result = set.deSerialize(&dataField, &size, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { - sif::warning << "PlocSupervisorHandler::handleAdcReport: Deserialization failed" << std::endl; + sif::warning << "PlocSupervisorHandler: Deserialization failed" << std::endl; } - adcReport.setValidityBufferGeneration(true); - adcReport.setValidity(true, true); - result = adcReport.commit(); - if (result != returnvalue::OK) { - return result; - } -#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_PLOC_SUPERVISOR == 1 - adcReport.printSet(); -#endif + set.setValidityBufferGeneration(true); + set.setValidity(true, true); nextReplyId = supv::EXE_REPORT; return result; } @@ -1157,8 +1201,8 @@ void PlocSupervisorHandler::setNextReplyId() { case supv::CONSECUTIVE_MRAM_DUMP: nextReplyId = supv::CONSECUTIVE_MRAM_DUMP; break; - case supv::LOGGING_REQUEST_COUNTERS: - nextReplyId = supv::LOGGING_REPORT; + case supv::REQUEST_LOGGING_COUNTERS: + nextReplyId = supv::COUNTERS_REPORT; break; case supv::REQUEST_ADC_REPORT: nextReplyId = supv::ADC_REPORT; @@ -1407,7 +1451,11 @@ ReturnValue_t PlocSupervisorHandler::prepareRunAutoEmTest(const uint8_t* command return returnvalue::OK; } -ReturnValue_t PlocSupervisorHandler::prepareSetGpioCmd(const uint8_t* commandData) { +ReturnValue_t PlocSupervisorHandler::prepareSetGpioCmd(const uint8_t* commandData, + size_t commandDataLen) { + if (commandDataLen < 3) { + return HasActionsIF::INVALID_PARAMETERS; + } uint8_t port = *commandData; uint8_t pin = *(commandData + 1); uint8_t val = *(commandData + 2); @@ -1420,7 +1468,11 @@ ReturnValue_t PlocSupervisorHandler::prepareSetGpioCmd(const uint8_t* commandDat return returnvalue::OK; } -ReturnValue_t PlocSupervisorHandler::prepareReadGpioCmd(const uint8_t* commandData) { +ReturnValue_t PlocSupervisorHandler::prepareReadGpioCmd(const uint8_t* commandData, + size_t commandDataLen) { + if (commandDataLen < 2) { + return HasActionsIF::INVALID_PARAMETERS; + } uint8_t port = *commandData; uint8_t pin = *(commandData + 1); supv::ReadGpio packet(spParams); @@ -1466,6 +1518,7 @@ ReturnValue_t PlocSupervisorHandler::prepareSetShutdownTimeoutCmd(const uint8_t* sif::warning << "PlocSupervisorHandler::prepareSetShutdownTimeoutCmd: Failed to deserialize timeout" << std::endl; + return result; } supv::SetShutdownTimeout packet(spParams); result = packet.buildPacket(timeout); @@ -1517,8 +1570,8 @@ void PlocSupervisorHandler::disableAllReplies() { disableReply(LATCHUP_REPORT); break; } - case LOGGING_REQUEST_COUNTERS: { - disableReply(LOGGING_REPORT); + case REQUEST_LOGGING_COUNTERS: { + disableReply(COUNTERS_REPORT); break; } default: { @@ -1532,6 +1585,9 @@ void PlocSupervisorHandler::disableAllReplies() { void PlocSupervisorHandler::disableReply(DeviceCommandId_t replyId) { DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId); + if (iter == deviceReplyMap.end()) { + return; + } DeviceReplyInfo* info = &(iter->second); info->delayCycles = 0; info->active = false; @@ -1562,6 +1618,9 @@ void PlocSupervisorHandler::sendFailureReport(DeviceCommandId_t replyId, ReturnV void PlocSupervisorHandler::disableExeReportReply() { DeviceReplyIter iter = deviceReplyMap.find(supv::EXE_REPORT); + if (iter == deviceReplyMap.end()) { + return; + } DeviceReplyInfo* info = &(iter->second); info->delayCycles = 0; info->command = deviceCommandMap.end(); @@ -1584,7 +1643,9 @@ ReturnValue_t PlocSupervisorHandler::handleMramDumpPacket(DeviceCommandId_t id) result = handleMramDumpFile(id); if (result != returnvalue::OK) { DeviceCommandMap::iterator iter = deviceCommandMap.find(id); - actionHelper.finish(false, iter->second.sendReplyTo, id, result); + if (iter != deviceCommandMap.end()) { + actionHelper.finish(false, iter->second.sendReplyTo, id, result); + } disableAllReplies(); nextReplyId = supv::NONE; return result; @@ -1851,7 +1912,12 @@ ReturnValue_t PlocSupervisorHandler::eventSubscription() { ReturnValue_t PlocSupervisorHandler::handleExecutionSuccessReport(ExecutionReport& report) { DeviceCommandId_t commandId = getPendingCommand(); - ReturnValue_t result = OK; + DeviceCommandMap::iterator iter = deviceCommandMap.find(commandId); + if (iter != deviceCommandMap.end() and iter->second.sendReplyTo != NO_COMMANDER) { + actionHelper.finish(true, iter->second.sendReplyTo, iter->first, returnvalue::OK); + iter->second.isExecuting = false; + } + commandIsPending = false; switch (commandId) { case supv::READ_GPIO: { // TODO: Fix @@ -1859,14 +1925,13 @@ ReturnValue_t PlocSupervisorHandler::handleExecutionSuccessReport(ExecutionRepor #if OBSW_DEBUG_PLOC_SUPERVISOR == 1 sif::info << "PlocSupervisorHandler: Read GPIO TM, State: " << gpioState << std::endl; #endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */ - DeviceCommandMap::iterator iter = deviceCommandMap.find(commandId); - if (iter->second.sendReplyTo == NO_COMMAND_ID) { + if (iter != deviceCommandMap.end() and iter->second.sendReplyTo == NO_COMMAND_ID) { return returnvalue::OK; } uint8_t data[sizeof(gpioState)]; size_t size = 0; - result = SerializeAdapter::serialize(&gpioState, data, &size, sizeof(gpioState), - SerializeIF::Endianness::BIG); + ReturnValue_t result = SerializeAdapter::serialize(&gpioState, data, &size, sizeof(gpioState), + SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { sif::debug << "PlocSupervisorHandler: Failed to deserialize GPIO state" << std::endl; } @@ -1942,6 +2007,11 @@ uint32_t PlocSupervisorHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t mod return 7000; } +void PlocSupervisorHandler::disableCommand(DeviceCommandId_t cmd) { + auto commandIter = deviceCommandMap.find(GET_HK_REPORT); + commandIter->second.isExecuting = false; +} + ReturnValue_t PlocSupervisorHandler::checkModeCommand(Mode_t commandedMode, Submode_t commandedSubmode, uint32_t* msToReachTheMode) { diff --git a/linux/payload/PlocSupervisorHandler.h b/archive/PlocSupervisorHandler.h similarity index 89% rename from linux/payload/PlocSupervisorHandler.h rename to archive/PlocSupervisorHandler.h index 4514e69f..85c3d94e 100644 --- a/linux/payload/PlocSupervisorHandler.h +++ b/archive/PlocSupervisorHandler.h @@ -20,7 +20,8 @@ using supv::ExecutionReport; using supv::TcBase; -static constexpr bool DEBUG_PLOC_SUPV = false; +static constexpr bool DEBUG_PLOC_SUPV = true; +static constexpr bool REDUCE_NORMAL_MODE_PRINTOUT = true; /** * @brief This is the device handler for the supervisor of the PLOC which is programmed by @@ -67,26 +68,6 @@ class PlocSupervisorHandler : public DeviceHandlerBase { void doOffActivity() override; private: - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_SUPERVISOR_HANDLER; - - //! [EXPORT] : [COMMENT] PLOC supervisor crc failure in telemetry packet - static const Event SUPV_MEMORY_READ_RPT_CRC_FAILURE = MAKE_EVENT(1, severity::LOW); - //! [EXPORT] : [COMMENT] Unhandled event. P1: APID, P2: Service ID - static constexpr Event SUPV_UNKNOWN_TM = MAKE_EVENT(2, severity::LOW); - static constexpr Event SUPV_UNINIMPLEMENTED_TM = MAKE_EVENT(3, severity::LOW); - //! [EXPORT] : [COMMENT] PLOC supervisor received acknowledgment failure report - static const Event SUPV_ACK_FAILURE = MAKE_EVENT(4, severity::LOW); - //! [EXPORT] : [COMMENT] PLOC received execution failure report - //! P1: ID of command for which the execution failed - //! P2: Status code sent by the supervisor handler - static const Event SUPV_EXE_FAILURE = MAKE_EVENT(5, severity::LOW); - //! [EXPORT] : [COMMENT] PLOC supervisor reply has invalid crc - static const Event SUPV_CRC_FAILURE_EVENT = MAKE_EVENT(6, severity::LOW); - //! [EXPORT] : [COMMENT] Supervisor helper currently executing a command - static const Event SUPV_HELPER_EXECUTING = MAKE_EVENT(7, severity::LOW); - //! [EXPORT] : [COMMENT] Failed to build the command to shutdown the MPSoC - static const Event SUPV_MPSOC_SHUTDOWN_BUILD_FAILED = MAKE_EVENT(8, severity::LOW); - static const uint16_t APID_MASK = 0x7FF; static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF; static const uint8_t EXE_STATUS_OFFSET = 10; @@ -94,15 +75,14 @@ class PlocSupervisorHandler : public DeviceHandlerBase { // 5 s static const uint32_t EXECUTION_DEFAULT_TIMEOUT = 5000; // 70 S - static const uint32_t ACKNOWLEDGE_DEFAULT_TIMEOUT = 70000; + static const uint32_t ACKNOWLEDGE_DEFAULT_TIMEOUT = 5000; // 60 s static const uint32_t MRAM_DUMP_EXECUTION_TIMEOUT = 60000; // 70 s static const uint32_t COPY_ADC_TO_MRAM_TIMEOUT = 70000; // 60 s static const uint32_t MRAM_DUMP_TIMEOUT = 60000; - // 4 s - static const uint32_t BOOT_TIMEOUT = 4000; + enum class StartupState : uint8_t { OFF, BOOTING, @@ -131,11 +111,18 @@ class PlocSupervisorHandler : public DeviceHandlerBase { LinuxLibgpioIF* gpioComIF = nullptr; Gpio uartIsolatorSwitch; bool shutdownCmdSent = false; + // Yeah, I am using an extra variable because I once again don't know + // what the hell the base class is doing and I don't care anymore. + bool normalCommandIsPending = false; + // True men implement their reply timeout handling themselves! + Countdown normalCmdCd = Countdown(2000); + bool commandIsPending = false; + Countdown cmdCd = Countdown(2000); supv::HkSet hkset; supv::BootStatusReport bootStatusReport; supv::LatchupStatusReport latchupStatusReport; - supv::LoggingReport loggingReport; + supv::CountersReport countersReport; supv::AdcReport adcReport; const power::Switch_t powerSwitch = power::NO_SWITCH; @@ -164,9 +151,12 @@ class PlocSupervisorHandler : public DeviceHandlerBase { Countdown executionReportTimeout = Countdown(EXECUTION_DEFAULT_TIMEOUT, false); Countdown acknowledgementReportTimeout = Countdown(ACKNOWLEDGE_DEFAULT_TIMEOUT, false); // Vorago nees some time to boot properly - Countdown bootTimeout = Countdown(BOOT_TIMEOUT); + Countdown bootTimeout = Countdown(supv::BOOT_TIMEOUT_MS); Countdown mramDumpTimeout = Countdown(MRAM_DUMP_TIMEOUT); + PoolEntry adcRawEntry = PoolEntry(16); + PoolEntry adcEngEntry = PoolEntry(16); + PoolEntry latchupCounters = PoolEntry(7); PoolEntry fmcStateEntry = PoolEntry(1); PoolEntry bootStateEntry = PoolEntry(1); PoolEntry bootCyclesEntry = PoolEntry(1); @@ -231,8 +221,13 @@ class PlocSupervisorHandler : public DeviceHandlerBase { ReturnValue_t handleBootStatusReport(const uint8_t* data); ReturnValue_t handleLatchupStatusReport(const uint8_t* data); + ReturnValue_t handleCounterReport(const uint8_t* data); void handleBadApidServiceCombination(Event result, unsigned int apid, unsigned int serviceId); ReturnValue_t handleAdcReport(const uint8_t* data); + ReturnValue_t genericHandleTm(const char* contextString, const uint8_t* data, + LocalPoolDataSetBase& set); + + void disableCommand(DeviceCommandId_t cmd); /** * @brief Depending on the current active command, this function sets the reply id of the @@ -301,8 +296,8 @@ class PlocSupervisorHandler : public DeviceHandlerBase { ReturnValue_t prepareSetAdcThresholdCmd(const uint8_t* commandData); ReturnValue_t prepareRunAutoEmTest(const uint8_t* commandData); ReturnValue_t prepareWipeMramCmd(const uint8_t* commandData); - ReturnValue_t prepareSetGpioCmd(const uint8_t* commandData); - ReturnValue_t prepareReadGpioCmd(const uint8_t* commandData); + ReturnValue_t prepareSetGpioCmd(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t prepareReadGpioCmd(const uint8_t* commandData, size_t commandDataLen); /** * @brief Copies the content of a space packet to the command buffer. diff --git a/bsp_hosted/fsfwconfig/events/translateEvents.cpp b/bsp_hosted/fsfwconfig/events/translateEvents.cpp index 099a4c7a..d4e113af 100644 --- a/bsp_hosted/fsfwconfig/events/translateEvents.cpp +++ b/bsp_hosted/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 315 translations. + * @brief Auto-generated event translation file. Contains 317 translations. * @details - * Generated on: 2023-10-27 14:24:05 + * Generated on: 2023-11-21 16:44:58 */ #include "translateEvents.h" @@ -157,6 +157,8 @@ const char *SUPV_EXE_FAILURE_STRING = "SUPV_EXE_FAILURE"; const char *SUPV_CRC_FAILURE_EVENT_STRING = "SUPV_CRC_FAILURE_EVENT"; const char *SUPV_HELPER_EXECUTING_STRING = "SUPV_HELPER_EXECUTING"; const char *SUPV_MPSOC_SHUTDOWN_BUILD_FAILED_STRING = "SUPV_MPSOC_SHUTDOWN_BUILD_FAILED"; +const char *SUPV_ACK_UNKNOWN_COMMAND_STRING = "SUPV_ACK_UNKNOWN_COMMAND"; +const char *SUPV_EXE_ACK_UNKNOWN_COMMAND_STRING = "SUPV_EXE_ACK_UNKNOWN_COMMAND"; const char *SANITIZATION_FAILED_STRING = "SANITIZATION_FAILED"; const char *MOUNTED_SD_CARD_STRING = "MOUNTED_SD_CARD"; const char *SEND_MRAM_DUMP_FAILED_STRING = "SEND_MRAM_DUMP_FAILED"; @@ -627,6 +629,10 @@ const char *translateEvents(Event event) { return SUPV_HELPER_EXECUTING_STRING; case (12008): return SUPV_MPSOC_SHUTDOWN_BUILD_FAILED_STRING; + case (12009): + return SUPV_ACK_UNKNOWN_COMMAND_STRING; + case (12010): + return SUPV_EXE_ACK_UNKNOWN_COMMAND_STRING; case (12100): return SANITIZATION_FAILED_STRING; case (12101): diff --git a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp index 1fa48c9a..145bf9aa 100644 --- a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp +++ b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 175 translations. - * Generated on: 2023-10-27 14:24:05 + * Generated on: 2023-11-21 16:44:58 */ #include "translateObjects.h" diff --git a/bsp_hosted/objectFactory.cpp b/bsp_hosted/objectFactory.cpp index 0f785e70..30a4154b 100644 --- a/bsp_hosted/objectFactory.cpp +++ b/bsp_hosted/objectFactory.cpp @@ -38,9 +38,9 @@ #include "devices/gpioIds.h" #include "fsfw_hal/linux/gpio/Gpio.h" +#include "linux/payload/FreshSupvHandler.h" #include "linux/payload/PlocMpsocHandler.h" #include "linux/payload/PlocMpsocSpecialComHelper.h" -#include "linux/payload/PlocSupervisorHandler.h" #include "linux/payload/PlocSupvUartMan.h" #include "test/gpio/DummyGpioIF.h" #endif @@ -97,10 +97,11 @@ void ObjectFactory::produce(void* args) { new SerialCookie(objects::PLOC_SUPERVISOR_HANDLER, plocSupvString, uart::PLOC_SUPV_BAUD, supv::MAX_PACKET_SIZE * 20, UartModes::NON_CANONICAL); supervisorCookie->setNoFixedSizeReply(); - auto supvHelper = new PlocSupvUartManager(objects::PLOC_SUPERVISOR_HELPER); - new PlocSupervisorHandler(objects::PLOC_SUPERVISOR_HANDLER, supervisorCookie, - Gpio(gpioIds::ENABLE_SUPV_UART, dummyGpioIF), pcdu::PDU1_CH6_PLOC_12V, - *supvHelper); + new PlocSupvUartManager(objects::PLOC_SUPERVISOR_HELPER); + DhbConfig dhbConf(objects::PLOC_SUPERVISOR_HANDLER); + auto* supvHandler = + new FreshSupvHandler(dhbConf, supervisorCookie, Gpio(gpioIds::ENABLE_SUPV_UART, dummyGpioIF), + dummySwitcher, power::PDU1_CH6_PLOC_12V); #endif /* OBSW_ADD_PLOC_SUPERVISOR == 1 */ #endif diff --git a/bsp_q7s/objectFactory.cpp b/bsp_q7s/objectFactory.cpp index f561e0f5..0880785b 100644 --- a/bsp_q7s/objectFactory.cpp +++ b/bsp_q7s/objectFactory.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -61,6 +60,7 @@ #include "linux/ipcore/PdecHandler.h" #include "linux/ipcore/Ptme.h" #include "linux/ipcore/PtmeConfig.h" +#include "linux/payload/FreshSupvHandler.h" #include "mission/config/configfile.h" #include "mission/system/acs/AcsBoardFdir.h" #include "mission/system/acs/AcsSubsystem.h" @@ -613,11 +613,11 @@ void ObjectFactory::createSyrlinksComponents(PowerSwitchIF* pwrSwitcher) { #endif } -void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF& pwrSwitch) { +void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF& pwrSwitcher) { using namespace gpio; std::stringstream consumer; auto* camSwitcher = - new CamSwitcher(objects::CAM_SWITCHER, pwrSwitch, power::PDU2_CH8_PAYLOAD_CAMERA); + new CamSwitcher(objects::CAM_SWITCHER, pwrSwitcher, power::PDU2_CH8_PAYLOAD_CAMERA); camSwitcher->connectModeTreeParent(satsystem::payload::SUBSYSTEM); #if OBSW_ADD_PLOC_MPSOC == 1 consumer << "0x" << std::hex << objects::PLOC_MPSOC_HANDLER; @@ -651,11 +651,11 @@ void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwit new SerialCookie(objects::PLOC_SUPERVISOR_HANDLER, plocSupvDev, serial::PLOC_SUPV_BAUD, supv::MAX_PACKET_SIZE * 20, UartModes::NON_CANONICAL); supervisorCookie->setNoFixedSizeReply(); - auto supvHelper = new PlocSupvUartManager(objects::PLOC_SUPERVISOR_HELPER); - auto* supvHandler = new PlocSupervisorHandler(objects::PLOC_SUPERVISOR_HANDLER, supervisorCookie, - Gpio(gpioIds::ENABLE_SUPV_UART, gpioComIF), - power::PDU1_CH6_PLOC_12V, *supvHelper); - supvHandler->setPowerSwitcher(&pwrSwitch); + new PlocSupvUartManager(objects::PLOC_SUPERVISOR_HELPER); + DhbConfig dhbConf(objects::PLOC_SUPERVISOR_HANDLER); + auto* supvHandler = + new FreshSupvHandler(dhbConf, supervisorCookie, Gpio(gpioIds::ENABLE_SUPV_UART, gpioComIF), + pwrSwitcher, power::PDU1_CH6_PLOC_12V); supvHandler->connectModeTreeParent(satsystem::payload::SUBSYSTEM); #endif /* OBSW_ADD_PLOC_SUPERVISOR == 1 */ static_cast(consumer); diff --git a/bsp_q7s/scheduling.cpp b/bsp_q7s/scheduling.cpp index 3c30e91a..fd99ab3f 100644 --- a/bsp_q7s/scheduling.cpp +++ b/bsp_q7s/scheduling.cpp @@ -383,11 +383,9 @@ void scheduling::initTasks() { } #endif /* OBSW_ADD_PLOC_SUPERVISOR */ - PeriodicTaskIF* plTask = factory->createPeriodicTask( - "PL_TASK", 25, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc, &RR_SCHEDULING); - plTask->addComponent(objects::CAM_SWITCHER); - scheduling::addMpsocSupvHandlers(plTask); - scheduling::scheduleScexDev(plTask); + FixedTimeslotTaskIF* plTask = factory->createFixedTimeslotTask( + "PL_TASK", 25, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc); + pst::pstPayload(plTask); #if OBSW_ADD_SCEX_DEVICE == 1 PeriodicTaskIF* scexReaderTask; diff --git a/cmake/scripts/q7s/q7s-make-debug.sh b/cmake/scripts/q7s/q7s-make-debug.sh index 0abbc3cb..a9536c97 100755 --- a/cmake/scripts/q7s/q7s-make-debug.sh +++ b/cmake/scripts/q7s/q7s-make-debug.sh @@ -24,6 +24,8 @@ if [ ! -z "${EIVE_Q7S_EM}" ]; then build_defs="EIVE_Q7S_EM=ON" fi +build_defs="${build_defs} CMAKE_EXPORT_COMPILE_COMMANDS=ON" + os_fsfw="linux" tgt_bsp="arm/q7s" build_dir="cmake-build-debug-q7s" diff --git a/cmake/scripts/q7s/q7s-make-release.sh b/cmake/scripts/q7s/q7s-make-release.sh index b86ca873..f5e970df 100755 --- a/cmake/scripts/q7s/q7s-make-release.sh +++ b/cmake/scripts/q7s/q7s-make-release.sh @@ -24,6 +24,8 @@ if [ ! -z "${EIVE_Q7S_EM}" ]; then build_defs="EIVE_Q7S_EM=ON" fi +build_defs="${build_defs} CMAKE_EXPORT_COMPILE_COMMANDS=ON" + os_fsfw="linux" tgt_bsp="arm/q7s" build_dir="cmake-build-release-q7s" diff --git a/fsfw b/fsfw index 41d67bff..b28174db 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 41d67bff639192afa2e18a23db6801c75b4fea88 +Subproject commit b28174db249cb33b541f665270fd6af14c382351 diff --git a/generators/bsp_hosted_events.csv b/generators/bsp_hosted_events.csv index de7416f5..656843f1 100644 --- a/generators/bsp_hosted_events.csv +++ b/generators/bsp_hosted_events.csv @@ -143,14 +143,16 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 11901;0x2e7d;BOOTING_FIRMWARE_FAILED_EVENT;LOW;Failed to boot firmware;mission/acs/str/StarTrackerHandler.h 11902;0x2e7e;BOOTING_BOOTLOADER_FAILED_EVENT;LOW;Failed to boot star tracker into bootloader mode;mission/acs/str/StarTrackerHandler.h 11903;0x2e7f;COM_ERROR_REPLY_RECEIVED;LOW;Received COM error. P1: Communication Error ID (datasheet p32);mission/acs/str/StarTrackerHandler.h -12001;0x2ee1;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;linux/payload/PlocSupervisorHandler.h -12002;0x2ee2;SUPV_UNKNOWN_TM;LOW;Unhandled event. P1: APID, P2: Service ID;linux/payload/PlocSupervisorHandler.h -12003;0x2ee3;SUPV_UNINIMPLEMENTED_TM;LOW;No description;linux/payload/PlocSupervisorHandler.h -12004;0x2ee4;SUPV_ACK_FAILURE;LOW;PLOC supervisor received acknowledgment failure report;linux/payload/PlocSupervisorHandler.h -12005;0x2ee5;SUPV_EXE_FAILURE;LOW;PLOC received execution failure report P1: ID of command for which the execution failed P2: Status code sent by the supervisor handler;linux/payload/PlocSupervisorHandler.h -12006;0x2ee6;SUPV_CRC_FAILURE_EVENT;LOW;PLOC supervisor reply has invalid crc;linux/payload/PlocSupervisorHandler.h -12007;0x2ee7;SUPV_HELPER_EXECUTING;LOW;Supervisor helper currently executing a command;linux/payload/PlocSupervisorHandler.h -12008;0x2ee8;SUPV_MPSOC_SHUTDOWN_BUILD_FAILED;LOW;Failed to build the command to shutdown the MPSoC;linux/payload/PlocSupervisorHandler.h +12001;0x2ee1;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;linux/payload/plocSupvDefs.h +12002;0x2ee2;SUPV_UNKNOWN_TM;LOW;Unhandled event. P1: APID, P2: Service ID;linux/payload/plocSupvDefs.h +12003;0x2ee3;SUPV_UNINIMPLEMENTED_TM;LOW;No description;linux/payload/plocSupvDefs.h +12004;0x2ee4;SUPV_ACK_FAILURE;LOW;PLOC supervisor received acknowledgment failure report;linux/payload/plocSupvDefs.h +12005;0x2ee5;SUPV_EXE_FAILURE;LOW;PLOC received execution failure report P1: ID of command for which the execution failed P2: Status code sent by the supervisor handler;linux/payload/plocSupvDefs.h +12006;0x2ee6;SUPV_CRC_FAILURE_EVENT;LOW;PLOC supervisor reply has invalid crc;linux/payload/plocSupvDefs.h +12007;0x2ee7;SUPV_HELPER_EXECUTING;LOW;Supervisor helper currently executing a command;linux/payload/plocSupvDefs.h +12008;0x2ee8;SUPV_MPSOC_SHUTDOWN_BUILD_FAILED;LOW;Failed to build the command to shutdown the MPSoC;linux/payload/plocSupvDefs.h +12009;0x2ee9;SUPV_ACK_UNKNOWN_COMMAND;LOW;Received ACK, but no related command is unknown or has not been sent by this software instance. P1: Module APID. P2: Service ID.;linux/payload/plocSupvDefs.h +12010;0x2eea;SUPV_EXE_ACK_UNKNOWN_COMMAND;LOW;Received ACK EXE, but no related command is unknown or has not been sent by this software instance. P1: Module APID. P2: Service ID.;linux/payload/plocSupvDefs.h 12100;0x2f44;SANITIZATION_FAILED;LOW;No description;bsp_q7s/fs/SdCardManager.h 12101;0x2f45;MOUNTED_SD_CARD;INFO;No description;bsp_q7s/fs/SdCardManager.h 12300;0x300c;SEND_MRAM_DUMP_FAILED;LOW;Failed to send mram dump command to supervisor handler P1: Return value of commandAction function P2: Start address of MRAM to dump with this command;linux/payload/PlocMemoryDumper.h diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv index de7416f5..656843f1 100644 --- a/generators/bsp_q7s_events.csv +++ b/generators/bsp_q7s_events.csv @@ -143,14 +143,16 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 11901;0x2e7d;BOOTING_FIRMWARE_FAILED_EVENT;LOW;Failed to boot firmware;mission/acs/str/StarTrackerHandler.h 11902;0x2e7e;BOOTING_BOOTLOADER_FAILED_EVENT;LOW;Failed to boot star tracker into bootloader mode;mission/acs/str/StarTrackerHandler.h 11903;0x2e7f;COM_ERROR_REPLY_RECEIVED;LOW;Received COM error. P1: Communication Error ID (datasheet p32);mission/acs/str/StarTrackerHandler.h -12001;0x2ee1;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;linux/payload/PlocSupervisorHandler.h -12002;0x2ee2;SUPV_UNKNOWN_TM;LOW;Unhandled event. P1: APID, P2: Service ID;linux/payload/PlocSupervisorHandler.h -12003;0x2ee3;SUPV_UNINIMPLEMENTED_TM;LOW;No description;linux/payload/PlocSupervisorHandler.h -12004;0x2ee4;SUPV_ACK_FAILURE;LOW;PLOC supervisor received acknowledgment failure report;linux/payload/PlocSupervisorHandler.h -12005;0x2ee5;SUPV_EXE_FAILURE;LOW;PLOC received execution failure report P1: ID of command for which the execution failed P2: Status code sent by the supervisor handler;linux/payload/PlocSupervisorHandler.h -12006;0x2ee6;SUPV_CRC_FAILURE_EVENT;LOW;PLOC supervisor reply has invalid crc;linux/payload/PlocSupervisorHandler.h -12007;0x2ee7;SUPV_HELPER_EXECUTING;LOW;Supervisor helper currently executing a command;linux/payload/PlocSupervisorHandler.h -12008;0x2ee8;SUPV_MPSOC_SHUTDOWN_BUILD_FAILED;LOW;Failed to build the command to shutdown the MPSoC;linux/payload/PlocSupervisorHandler.h +12001;0x2ee1;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;linux/payload/plocSupvDefs.h +12002;0x2ee2;SUPV_UNKNOWN_TM;LOW;Unhandled event. P1: APID, P2: Service ID;linux/payload/plocSupvDefs.h +12003;0x2ee3;SUPV_UNINIMPLEMENTED_TM;LOW;No description;linux/payload/plocSupvDefs.h +12004;0x2ee4;SUPV_ACK_FAILURE;LOW;PLOC supervisor received acknowledgment failure report;linux/payload/plocSupvDefs.h +12005;0x2ee5;SUPV_EXE_FAILURE;LOW;PLOC received execution failure report P1: ID of command for which the execution failed P2: Status code sent by the supervisor handler;linux/payload/plocSupvDefs.h +12006;0x2ee6;SUPV_CRC_FAILURE_EVENT;LOW;PLOC supervisor reply has invalid crc;linux/payload/plocSupvDefs.h +12007;0x2ee7;SUPV_HELPER_EXECUTING;LOW;Supervisor helper currently executing a command;linux/payload/plocSupvDefs.h +12008;0x2ee8;SUPV_MPSOC_SHUTDOWN_BUILD_FAILED;LOW;Failed to build the command to shutdown the MPSoC;linux/payload/plocSupvDefs.h +12009;0x2ee9;SUPV_ACK_UNKNOWN_COMMAND;LOW;Received ACK, but no related command is unknown or has not been sent by this software instance. P1: Module APID. P2: Service ID.;linux/payload/plocSupvDefs.h +12010;0x2eea;SUPV_EXE_ACK_UNKNOWN_COMMAND;LOW;Received ACK EXE, but no related command is unknown or has not been sent by this software instance. P1: Module APID. P2: Service ID.;linux/payload/plocSupvDefs.h 12100;0x2f44;SANITIZATION_FAILED;LOW;No description;bsp_q7s/fs/SdCardManager.h 12101;0x2f45;MOUNTED_SD_CARD;INFO;No description;bsp_q7s/fs/SdCardManager.h 12300;0x300c;SEND_MRAM_DUMP_FAILED;LOW;Failed to send mram dump command to supervisor handler P1: Return value of commandAction function P2: Start address of MRAM to dump with this command;linux/payload/PlocMemoryDumper.h diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index 099a4c7a..d4e113af 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 315 translations. + * @brief Auto-generated event translation file. Contains 317 translations. * @details - * Generated on: 2023-10-27 14:24:05 + * Generated on: 2023-11-21 16:44:58 */ #include "translateEvents.h" @@ -157,6 +157,8 @@ const char *SUPV_EXE_FAILURE_STRING = "SUPV_EXE_FAILURE"; const char *SUPV_CRC_FAILURE_EVENT_STRING = "SUPV_CRC_FAILURE_EVENT"; const char *SUPV_HELPER_EXECUTING_STRING = "SUPV_HELPER_EXECUTING"; const char *SUPV_MPSOC_SHUTDOWN_BUILD_FAILED_STRING = "SUPV_MPSOC_SHUTDOWN_BUILD_FAILED"; +const char *SUPV_ACK_UNKNOWN_COMMAND_STRING = "SUPV_ACK_UNKNOWN_COMMAND"; +const char *SUPV_EXE_ACK_UNKNOWN_COMMAND_STRING = "SUPV_EXE_ACK_UNKNOWN_COMMAND"; const char *SANITIZATION_FAILED_STRING = "SANITIZATION_FAILED"; const char *MOUNTED_SD_CARD_STRING = "MOUNTED_SD_CARD"; const char *SEND_MRAM_DUMP_FAILED_STRING = "SEND_MRAM_DUMP_FAILED"; @@ -627,6 +629,10 @@ const char *translateEvents(Event event) { return SUPV_HELPER_EXECUTING_STRING; case (12008): return SUPV_MPSOC_SHUTDOWN_BUILD_FAILED_STRING; + case (12009): + return SUPV_ACK_UNKNOWN_COMMAND_STRING; + case (12010): + return SUPV_EXE_ACK_UNKNOWN_COMMAND_STRING; case (12100): return SANITIZATION_FAILED_STRING; case (12101): diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index 5cc157c2..d7ff5f77 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 179 translations. - * Generated on: 2023-10-27 14:24:05 + * Generated on: 2023-11-21 16:44:58 */ #include "translateObjects.h" diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index 099a4c7a..d4e113af 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 315 translations. + * @brief Auto-generated event translation file. Contains 317 translations. * @details - * Generated on: 2023-10-27 14:24:05 + * Generated on: 2023-11-21 16:44:58 */ #include "translateEvents.h" @@ -157,6 +157,8 @@ const char *SUPV_EXE_FAILURE_STRING = "SUPV_EXE_FAILURE"; const char *SUPV_CRC_FAILURE_EVENT_STRING = "SUPV_CRC_FAILURE_EVENT"; const char *SUPV_HELPER_EXECUTING_STRING = "SUPV_HELPER_EXECUTING"; const char *SUPV_MPSOC_SHUTDOWN_BUILD_FAILED_STRING = "SUPV_MPSOC_SHUTDOWN_BUILD_FAILED"; +const char *SUPV_ACK_UNKNOWN_COMMAND_STRING = "SUPV_ACK_UNKNOWN_COMMAND"; +const char *SUPV_EXE_ACK_UNKNOWN_COMMAND_STRING = "SUPV_EXE_ACK_UNKNOWN_COMMAND"; const char *SANITIZATION_FAILED_STRING = "SANITIZATION_FAILED"; const char *MOUNTED_SD_CARD_STRING = "MOUNTED_SD_CARD"; const char *SEND_MRAM_DUMP_FAILED_STRING = "SEND_MRAM_DUMP_FAILED"; @@ -627,6 +629,10 @@ const char *translateEvents(Event event) { return SUPV_HELPER_EXECUTING_STRING; case (12008): return SUPV_MPSOC_SHUTDOWN_BUILD_FAILED_STRING; + case (12009): + return SUPV_ACK_UNKNOWN_COMMAND_STRING; + case (12010): + return SUPV_EXE_ACK_UNKNOWN_COMMAND_STRING; case (12100): return SANITIZATION_FAILED_STRING; case (12101): diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index 5cc157c2..d7ff5f77 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 179 translations. - * Generated on: 2023-10-27 14:24:05 + * Generated on: 2023-11-21 16:44:58 */ #include "translateObjects.h" diff --git a/linux/payload/CMakeLists.txt b/linux/payload/CMakeLists.txt index e697fac6..48fb9d96 100644 --- a/linux/payload/CMakeLists.txt +++ b/linux/payload/CMakeLists.txt @@ -2,9 +2,9 @@ target_sources( ${OBSW_NAME} PUBLIC PlocMemoryDumper.cpp PlocMpsocHandler.cpp + FreshSupvHandler.cpp PlocMpsocSpecialComHelper.cpp plocMpsocHelpers.cpp - PlocSupervisorHandler.cpp PlocSupvUartMan.cpp ScexDleParser.cpp ScexHelper.cpp diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp new file mode 100644 index 00000000..0d34b63f --- /dev/null +++ b/linux/payload/FreshSupvHandler.cpp @@ -0,0 +1,1584 @@ +#include "FreshSupvHandler.h" + +#include +#include + +#include +#include + +#include "eive/definitions.h" +#include "eive/objects.h" +#include "fsfw/action.h" +#include "fsfw/globalfunctions/arrayprinter.h" +#include "fsfw/ipc/CommandMessage.h" +#include "fsfw/ipc/MessageQueueIF.h" +#include "fsfw/ipc/QueueFactory.h" +#include "fsfw/objectmanager/ObjectManagerIF.h" +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/tasks/TaskFactory.h" +#include "linux/payload/plocSupvDefs.h" + +using namespace supv; +using namespace returnvalue; + +std::atomic_bool supv::SUPV_ON = false; + +FreshSupvHandler::FreshSupvHandler(DhbConfig cfg, CookieIF* comCookie, Gpio uartIsolatorSwitch, + PowerSwitchIF& switchIF, power::Switch_t powerSwitch) + : FreshDeviceHandlerBase(cfg), + comCookie(comCookie), + switchIF(switchIF), + switchId(powerSwitch), + uartIsolatorSwitch(uartIsolatorSwitch), + hkSet(this), + bootStatusReport(this), + latchupStatusReport(this), + countersReport(this), + adcReport(this) { + spParams.buf = commandBuffer.data(); + spParams.maxSize = commandBuffer.size(); + eventQueue = QueueFactory::instance()->createMessageQueue(10); +} + +void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { + if (not transitionActive and mode == MODE_OFF) { + // Nothing to do for now. + return; + } + if (opCode == OpCode::DEFAULT_OPERATION) { + EventMessage event; + for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK; + result = eventQueue->receiveMessage(&event)) { + switch (event.getMessageId()) { + case EventMessage::EVENT_MESSAGE: + handleEvent(&event); + break; + default: + sif::debug + << "PlocSupervisorHandler::performOperationHook: Did not subscribe to this event" + << " message" << std::endl; + break; + } + } + if (transitionActive) { + if (targetMode == MODE_ON or targetMode == MODE_NORMAL) { + handleTransitionToOn(); + } else if (targetMode == MODE_OFF) { + handleTransitionToOff(); + } else { + // This should never happen. + sif::error << "FreshSupvHandler: Invalid transition mode: " << targetMode << std::endl; + targetMode = MODE_OFF; + targetSubmode = 0; + handleTransitionToOff(); + } + } else { + // I think the SUPV is not able to process multiple commands consecutively, so only send + // normal command if no other command is pending. We handle the action queue first, which + // should ensure that these commands take precendence. + if (mode == MODE_NORMAL and not isCommandPending()) { + auto cmdIter = activeActionCmds.find( + buildActiveCmdKey(Apid::HK, static_cast(tc::HkId::GET_REPORT))); + if (cmdIter == activeActionCmds.end() or not cmdIter->second.isPending) { + spParams.buf = commandBuffer.data(); + commandedByCached = MessageQueueIF::NO_QUEUE; + sendEmptyCmd(supv::GET_HK_REPORT, Apid::HK, static_cast(tc::HkId::GET_REPORT), + true); + } + } + } + } else if (opCode == OpCode::PARSE_TM) { + for (auto& activeCmd : activeActionCmds) { + if (activeCmd.second.isPending and activeCmd.second.cmdCountdown.hasTimedOut()) { + if (activeCmd.second.commandedBy != MessageQueueIF::NO_QUEUE) { + actionHelper.finish(false, activeCmd.second.commandedBy, activeCmd.first, + DeviceHandlerIF::TIMEOUT); + } + activeCmd.second.isPending = false; + } + } + + parseTmPackets(); + } +} + +ReturnValue_t FreshSupvHandler::performDeviceOperationPreQueueHandling(uint8_t opCode) { + if (opCode != OpCode::DEFAULT_OPERATION) { + return returnvalue::OK; + } + // We parse for TM packets shortly before handling the queue, this might complete some packets, + // which then allows the handling of new action commands. + return parseTmPackets(); +} + +ReturnValue_t FreshSupvHandler::handleCommandMessage(CommandMessage* message) { + // No custom messages. + return returnvalue::FAILED; +} + +LocalPoolDataSetBase* FreshSupvHandler::getDataSetHandle(sid_t sid) { + if (sid == hkSet.getSid()) { + return &hkSet; + } else if (sid == bootStatusReport.getSid()) { + return &bootStatusReport; + } else if (sid == latchupStatusReport.getSid()) { + return &latchupStatusReport; + } else if (sid == countersReport.getSid()) { + return &countersReport; + } else if (sid == adcReport.getSid()) { + return &adcReport; + } + return nullptr; +} + +ReturnValue_t FreshSupvHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) { + // TODO: Copy code from god handler here. + localDataPoolMap.emplace(supv::NUM_TMS, new PoolEntry({0})); + localDataPoolMap.emplace(supv::TEMP_PS, new PoolEntry({0})); + localDataPoolMap.emplace(supv::TEMP_PL, new PoolEntry({0})); + localDataPoolMap.emplace(supv::HK_SOC_STATE, new PoolEntry({0})); + localDataPoolMap.emplace(supv::NVM0_1_STATE, new PoolEntry({0})); + localDataPoolMap.emplace(supv::NVM3_STATE, new PoolEntry({0})); + localDataPoolMap.emplace(supv::MISSION_IO_STATE, new PoolEntry({0})); + localDataPoolMap.emplace(supv::FMC_STATE, &fmcStateEntry); + localDataPoolMap.emplace(supv::NUM_TCS, new PoolEntry({0})); + localDataPoolMap.emplace(supv::TEMP_SUP, &tempSupEntry); + localDataPoolMap.emplace(supv::UPTIME, new PoolEntry({0})); + localDataPoolMap.emplace(supv::CPULOAD, new PoolEntry({0})); + localDataPoolMap.emplace(supv::AVAILABLEHEAP, new PoolEntry({0})); + + localDataPoolMap.emplace(supv::BR_SOC_STATE, new PoolEntry({0})); + localDataPoolMap.emplace(supv::POWER_CYCLES, new PoolEntry({0})); + localDataPoolMap.emplace(supv::BOOT_AFTER_MS, new PoolEntry({0})); + localDataPoolMap.emplace(supv::BOOT_TIMEOUT_POOL_VAR_MS, new PoolEntry({0})); + localDataPoolMap.emplace(supv::ACTIVE_NVM, new PoolEntry({0})); + localDataPoolMap.emplace(supv::BP0_STATE, new PoolEntry({0})); + localDataPoolMap.emplace(supv::BP1_STATE, new PoolEntry({0})); + localDataPoolMap.emplace(supv::BP2_STATE, new PoolEntry({0})); + localDataPoolMap.emplace(supv::BOOT_STATE, &bootStateEntry); + localDataPoolMap.emplace(supv::BOOT_CYCLES, &bootCyclesEntry); + + localDataPoolMap.emplace(supv::LATCHUP_ID, new PoolEntry({0})); + localDataPoolMap.emplace(supv::CNT0, new PoolEntry({0})); + localDataPoolMap.emplace(supv::CNT1, new PoolEntry({0})); + localDataPoolMap.emplace(supv::CNT2, new PoolEntry({0})); + localDataPoolMap.emplace(supv::CNT3, new PoolEntry({0})); + localDataPoolMap.emplace(supv::CNT4, new PoolEntry({0})); + localDataPoolMap.emplace(supv::CNT5, new PoolEntry({0})); + localDataPoolMap.emplace(supv::CNT6, new PoolEntry({0})); + localDataPoolMap.emplace(supv::LATCHUP_RPT_TIME_MSEC, new PoolEntry({0})); + localDataPoolMap.emplace(supv::LATCHUP_RPT_TIME_SEC, new PoolEntry({0})); + localDataPoolMap.emplace(supv::LATCHUP_RPT_TIME_MIN, new PoolEntry({0})); + localDataPoolMap.emplace(supv::LATCHUP_RPT_TIME_HOUR, new PoolEntry({0})); + localDataPoolMap.emplace(supv::LATCHUP_RPT_TIME_DAY, new PoolEntry({0})); + localDataPoolMap.emplace(supv::LATCHUP_RPT_TIME_MON, new PoolEntry({0})); + localDataPoolMap.emplace(supv::LATCHUP_RPT_TIME_YEAR, new PoolEntry({0})); + localDataPoolMap.emplace(supv::LATCHUP_RPT_IS_SET, new PoolEntry({0})); + + localDataPoolMap.emplace(supv::SIGNATURE, new PoolEntry()); + localDataPoolMap.emplace(supv::LATCHUP_HAPPENED_CNTS, &latchupCounters); + localDataPoolMap.emplace(supv::ADC_DEVIATION_TRIGGERS_CNT, new PoolEntry({0})); + localDataPoolMap.emplace(supv::TC_RECEIVED_CNT, new PoolEntry({0})); + localDataPoolMap.emplace(supv::TM_AVAILABLE_CNT, new PoolEntry({0})); + localDataPoolMap.emplace(supv::SUPERVISOR_BOOTS, new PoolEntry({0})); + localDataPoolMap.emplace(supv::MPSOC_BOOTS, new PoolEntry({0})); + localDataPoolMap.emplace(supv::MPSOC_BOOT_FAILED_ATTEMPTS, new PoolEntry({0})); + localDataPoolMap.emplace(supv::MPSOC_POWER_UP, new PoolEntry({0})); + localDataPoolMap.emplace(supv::MPSOC_UPDATES, new PoolEntry({0})); + localDataPoolMap.emplace(supv::MPSOC_HEARTBEAT_RESETS, new PoolEntry({0})); + localDataPoolMap.emplace(supv::CPU_WDT_RESETS, new PoolEntry({0})); + localDataPoolMap.emplace(supv::PS_HEARTBEATS_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::PL_HEARTBEATS_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::EB_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::BM_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::LM_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::AM_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::TCTMM_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::MM_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::HK_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::DL_TASK_LOST, new PoolEntry({0})); + localDataPoolMap.emplace(supv::RWS_TASKS_LOST, new PoolEntry(3)); + + localDataPoolMap.emplace(supv::ADC_RAW, &adcRawEntry); + localDataPoolMap.emplace(supv::ADC_ENG, &adcEngEntry); + + poolManager.subscribeForRegularPeriodicPacket( + subdp::RegularHkPeriodicParams(hkSet.getSid(), false, 10.0)); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) { + using namespace supv; + // The SUPV does not have any action commands where there is no communication with the device + // involved. + if (mode != MODE_ON and mode != MODE_NORMAL) { + return HasModesIF::INVALID_MODE; + } + ReturnValue_t result; + if (uartManager->longerRequestActive()) { + return result::SUPV_HELPER_EXECUTING; + } + + switch (actionId) { + case PERFORM_UPDATE: { + if (size > config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE) { + return result::FILENAME_TOO_LONG; + } + UpdateParams params; + result = extractUpdateCommand(data, size, params); + if (result != returnvalue::OK) { + return result; + } + result = uartManager->performUpdate(params); + if (result != returnvalue::OK) { + return result; + } + return EXECUTION_FINISHED; + } + case CONTINUE_UPDATE: { + uartManager->initiateUpdateContinuation(); + return EXECUTION_FINISHED; + } + case MEMORY_CHECK_WITH_FILE: { + UpdateParams params; + result = extractBaseParams(&data, size, params); + if (result != returnvalue::OK) { + return result; + } + if (not std::filesystem::exists(params.file)) { + return HasFileSystemIF::FILE_DOES_NOT_EXIST; + } + uartManager->performMemCheck(params.file, params.memId, params.startAddr); + return EXECUTION_FINISHED; + } + default: + break; + } + // The PLOC SUPV is not able to process multiple commands consecutively. + if (isCommandPending()) { + return HasActionsIF::IS_BUSY; + } + if (isCommandAlreadyActive(actionId)) { + return HasActionsIF::IS_BUSY; + } + spParams.buf = commandBuffer.data(); + this->commandedByCached = commandedBy; + switch (actionId) { + case GET_HK_REPORT: { + sendEmptyCmd(supv::GET_HK_REPORT, Apid::HK, static_cast(tc::HkId::GET_REPORT), true); + result = returnvalue::OK; + break; + } + case START_MPSOC: { + sif::info << "PLOC SUPV: Starting MPSoC" << std::endl; + sendEmptyCmd(supv::START_MPSOC, Apid::BOOT_MAN, + static_cast(tc::BootManId::START_MPSOC), false); + result = returnvalue::OK; + break; + } + case SHUTDOWN_MPSOC: { + sif::info << "PLOC SUPV: Shutting down MPSoC" << std::endl; + sendEmptyCmd(supv::SHUTDOWN_MPSOC, Apid::BOOT_MAN, + static_cast(tc::BootManId::SHUTDOWN_MPSOC), false); + result = returnvalue::OK; + break; + } + case SEL_MPSOC_BOOT_IMAGE: { + prepareSelBootImageCmd(data); + result = returnvalue::OK; + break; + } + case RESET_MPSOC: { + sif::info << "PLOC SUPV: Resetting MPSoC" << std::endl; + sendEmptyCmd(supv::RESET_MPSOC, Apid::BOOT_MAN, + static_cast(tc::BootManId::RESET_MPSOC), false); + result = returnvalue::OK; + break; + } + case SET_TIME_REF: { + result = prepareSetTimeRefCmd(); + break; + } + case SET_BOOT_TIMEOUT: { + prepareSetBootTimeoutCmd(data, size); + result = returnvalue::OK; + break; + } + case SET_MAX_RESTART_TRIES: { + prepareRestartTriesCmd(data, size); + result = returnvalue::OK; + break; + } + case DISABLE_PERIOIC_HK_TRANSMISSION: { + prepareDisableHk(); + result = returnvalue::OK; + break; + } + case GET_BOOT_STATUS_REPORT: { + sendEmptyCmd(supv::GET_BOOT_STATUS_REPORT, Apid::BOOT_MAN, + static_cast(tc::BootManId::GET_BOOT_STATUS_REPORT), true); + result = returnvalue::OK; + break; + } + case ENABLE_LATCHUP_ALERT: { + result = prepareLatchupConfigCmd(data, actionId, size); + break; + } + case DISABLE_LATCHUP_ALERT: { + result = prepareLatchupConfigCmd(data, actionId, size); + break; + } + case SET_ALERT_LIMIT: { + result = prepareSetAlertLimitCmd(data, size); + break; + } + case GET_LATCHUP_STATUS_REPORT: { + sendEmptyCmd(supv::GET_LATCHUP_STATUS_REPORT, Apid::LATCHUP_MON, + static_cast(tc::LatchupMonId::GET_STATUS_REPORT), true); + result = returnvalue::OK; + break; + } + case SET_GPIO: { + result = prepareSetGpioCmd(data, size); + break; + } + case FACTORY_RESET: { + result = prepareFactoryResetCmd(data, size); + break; + } + case READ_GPIO: { + result = prepareReadGpioCmd(data, size); + break; + } + case SET_SHUTDOWN_TIMEOUT: { + prepareSetShutdownTimeoutCmd(data, size); + result = returnvalue::OK; + break; + } + case FACTORY_FLASH: { + sendEmptyCmd(supv::FACTORY_FLASH, Apid::BOOT_MAN, + static_cast(tc::BootManId::FACTORY_FLASH), false); + result = returnvalue::OK; + break; + } + case RESET_PL: { + sendEmptyCmd(supv::RESET_PL, Apid::BOOT_MAN, static_cast(tc::BootManId::RESET_PL), + false); + result = returnvalue::OK; + break; + } + case SET_ADC_ENABLED_CHANNELS: { + prepareSetAdcEnabledChannelsCmd(data); + result = returnvalue::OK; + break; + } + case SET_ADC_WINDOW_AND_STRIDE: { + prepareSetAdcWindowAndStrideCmd(data); + result = returnvalue::OK; + break; + } + case SET_ADC_THRESHOLD: { + prepareSetAdcThresholdCmd(data); + result = returnvalue::OK; + break; + } + case WIPE_MRAM: { + result = prepareWipeMramCmd(data, size); + break; + } + case REQUEST_ADC_REPORT: { + sendEmptyCmd(supv::REQUEST_ADC_REPORT, Apid::ADC_MON, + static_cast(tc::AdcMonId::REQUEST_ADC_SAMPLE), true); + result = returnvalue::OK; + break; + } + case REQUEST_LOGGING_COUNTERS: { + sendEmptyCmd(supv::REQUEST_LOGGING_COUNTERS, Apid::DATA_LOGGER, + static_cast(tc::DataLoggerServiceId::REQUEST_COUNTERS), true); + result = returnvalue::OK; + break; + } + default: + sif::debug << "PlocSupervisorHandler::buildCommandFromCommand: Command not implemented" + << std::endl; + result = DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; + break; + } + return result; +} + +ReturnValue_t FreshSupvHandler::prepareSetTimeRefCmd() { + Clock::TimeOfDay_t time; + ReturnValue_t result = Clock::getDateAndTime(&time); + if (result != returnvalue::OK) { + sif::warning << "PlocSupervisorHandler::prepareSetTimeRefCmd: Failed to get current time" + << std::endl; + return result::GET_TIME_FAILURE; + } + supv::SetTimeRef packet(spParams); + result = packet.buildPacket(&time); + if (result != returnvalue::OK) { + return result; + } + sendCommand(supv::SET_TIME_REF, packet, false); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::checkModeCommand(Mode_t commandedMode, Submode_t commandedSubmode, + uint32_t* msToReachTheMode) { + if (commandedMode != MODE_OFF) { + PoolReadGuard pg(&enablePl); + if (pg.getReadResult() == returnvalue::OK) { + if (enablePl.plUseAllowed.isValid() and not enablePl.plUseAllowed.value) { + return NON_OP_STATE_OF_CHARGE; + } + } + } + if (commandedMode != HasModesIF::MODE_OFF and commandedMode != HasModesIF::MODE_ON and + commandedMode != MODE_NORMAL) { + return returnvalue::FAILED; + } + if (commandedMode != mode and msToReachTheMode != nullptr) { + if (commandedMode == MODE_OFF) { + *msToReachTheMode = supv::MAX_TRANSITION_TIME_TO_OFF_MS; + } else { + *msToReachTheMode = supv::MAX_TRANSITION_TIME_TO_ON_MS; + } + } + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::prepareSelBootImageCmd(const uint8_t* commandData) { + supv::MPSoCBootSelect packet(spParams); + ReturnValue_t result = + packet.buildPacket(commandData[0], commandData[1], commandData[2], commandData[3]); + if (result != returnvalue::OK) { + return result; + } + sendCommand(supv::SEL_MPSOC_BOOT_IMAGE, packet, false); + return returnvalue::OK; +} + +void FreshSupvHandler::startTransition(Mode_t newMode, Submode_t newSubmode) { + if (newMode == mode or (mode == MODE_ON and newMode == MODE_NORMAL) or + (newMode == MODE_ON and mode == MODE_NORMAL)) { + // Can finish immediately. + setMode(newMode, newSubmode); + return; + } + // Transition for both OFF to ON/NORMAL and ON/NORMAL to OFF require small state machine. + transitionActive = true; + targetMode = newMode; + targetSubmode = newSubmode; + if (targetMode == MODE_ON or targetMode == MODE_NORMAL) { + startupState = StartupState::IDLE; + } else if (targetMode == MODE_OFF) { + shutdownState = ShutdownState::IDLE; + } +} + +void FreshSupvHandler::handleTransitionToOn() { + if (startupState == StartupState::IDLE) { + startupState = StartupState::POWER_SWITCHING; + switchIF.sendSwitchCommand(switchId, PowerSwitchIF::SWITCH_ON); + switchTimeout.resetTimer(); + } else if (modeHelper.isTimedOut()) { + targetMode = MODE_OFF; + shutdownState = ShutdownState::IDLE; + handleTransitionToOff(); + return; + } + if (startupState == StartupState::POWER_SWITCHING) { + if (switchIF.getSwitchState(switchId) == PowerSwitchIF::SWITCH_ON) { + startupState = StartupState::BOOTING; + bootTimeout.resetTimer(); + } else if (switchTimeout.hasTimedOut()) { + targetMode = MODE_OFF; + shutdownState = ShutdownState::IDLE; + handleTransitionToOff(); + return; + } + } + if (startupState == StartupState::BOOTING and bootTimeout.hasTimedOut()) { + uartIsolatorSwitch.pullHigh(); + uartManager->start(); + if (SET_TIME_DURING_BOOT) { + startupState = StartupState::SET_TIME; + } else { + startupState = StartupState::ON; + } + } + if (startupState == StartupState::SET_TIME) { + spParams.buf = commandBuffer.data(); + ReturnValue_t result = prepareSetTimeRefCmd(); + if (result != returnvalue::OK) { + sif::error << "FreshSupvHandler: Setting time command prepration failed" << std::endl; + startupState = StartupState::ON; + } else { + startupState = StartupState::WAIT_FOR_TIME_REPLY; + } + } + if (startupState == StartupState::TIME_WAS_SET) { + startupState = StartupState::ON; + } + if (startupState == StartupState::ON) { + hkSet.setReportingEnabled(true); + supv::SUPV_ON = true; + transitionActive = false; + setMode(targetMode); + } +} + +void FreshSupvHandler::handleTransitionToOff() { + if (shutdownState == ShutdownState::IDLE) { + hkSet.setReportingEnabled(false); + hkSet.setValidity(false, true); + uartManager->stop(); + activeActionCmds.clear(); + uartIsolatorSwitch.pullLow(); + switchIF.sendSwitchCommand(switchId, PowerSwitchIF::SWITCH_OFF); + shutdownState = ShutdownState::POWER_SWITCHING; + } + if (shutdownState == ShutdownState::POWER_SWITCHING) { + if (switchIF.getSwitchState(switchId) == PowerSwitchIF::SWITCH_OFF or modeHelper.isTimedOut()) { + supv::SUPV_ON = false; + transitionActive = false; + setMode(MODE_OFF); + } + } +} + +ReturnValue_t FreshSupvHandler::sendCommand(DeviceCommandId_t commandId, TcBase& tc, + bool replyExpected, uint32_t cmdCountdownMs) { + if (supv::DEBUG_PLOC_SUPV) { + if (not(supv::REDUCE_NORMAL_MODE_PRINTOUT and mode == MODE_NORMAL and + commandId == supv::GET_HK_REPORT)) { + sif::debug << "PLOC SUPV: SEND PACKET Size " << tc.getFullPacketLen() << " Module APID " + << (int)tc.getModuleApid() << " Service ID " << (int)tc.getServiceId() + << std::endl; + } + } + ActiveCmdInfo info(commandId, cmdCountdownMs); + auto activeCmdIter = + activeActionCmds.find(buildActiveCmdKey(tc.getModuleApid(), tc.getServiceId())); + if (activeCmdIter == activeActionCmds.end()) { + info.isPending = true; + info.replyPacketExpected = replyExpected; + info.commandedBy = commandedByCached; + info.cmdCountdown.resetTimer(); + activeActionCmds.emplace(buildActiveCmdKey(tc.getModuleApid(), tc.getServiceId()), info); + } else { + if (activeCmdIter->second.isPending) { + return HasActionsIF::IS_BUSY; + } + activeCmdIter->second.isPending = true; + activeCmdIter->second.commandId = commandId; + activeCmdIter->second.commandedBy = commandedByCached; + activeCmdIter->second.ackRecv = false; + activeCmdIter->second.ackExeRecv = false; + activeCmdIter->second.replyPacketExpected = replyExpected; + activeCmdIter->second.replyPacketReceived = false; + activeCmdIter->second.cmdCountdown.setTimeout(cmdCountdownMs); + activeCmdIter->second.cmdCountdown.resetTimer(); + } + ReturnValue_t result = + uartManager->sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen()); + return result; +} + +ReturnValue_t FreshSupvHandler::initialize() { + uartManager = + ObjectManager::instance()->get(objects::PLOC_SUPERVISOR_HELPER); + if (uartManager == nullptr) { + return returnvalue::FAILED; + } + uartManager->initializeInterface(comCookie); + + ReturnValue_t result = eventSubscription(); + if (result != returnvalue::OK) { + return result; + } + return FreshDeviceHandlerBase::initialize(); +} + +ReturnValue_t FreshSupvHandler::sendEmptyCmd(DeviceCommandId_t commandId, uint16_t apid, + uint8_t serviceId, bool replyExpected) { + supv::NoPayloadPacket packet(spParams, apid, serviceId); + ReturnValue_t result = packet.buildPacket(); + if (result != returnvalue::OK) { + return result; + } + sendCommand(commandId, packet, replyExpected); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::prepareSetBootTimeoutCmd(const uint8_t* commandData, + size_t cmdDataLen) { + if (cmdDataLen < 4) { + return HasActionsIF::INVALID_PARAMETERS; + } + supv::SetBootTimeout packet(spParams); + uint32_t timeout = *(commandData) << 24 | *(commandData + 1) << 16 | *(commandData + 2) << 8 | + *(commandData + 3); + ReturnValue_t result = packet.buildPacket(timeout); + if (result != returnvalue::OK) { + return result; + } + sendCommand(supv::SET_BOOT_TIMEOUT, packet, false); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::prepareRestartTriesCmd(const uint8_t* commandData, + size_t cmdDataLen) { + if (cmdDataLen < 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + uint8_t restartTries = *(commandData); + supv::SetRestartTries packet(spParams); + ReturnValue_t result = packet.buildPacket(restartTries); + if (result != returnvalue::OK) { + return result; + } + sendCommand(supv::ENABLE_AUTO_TM, packet, false); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::prepareDisableHk() { + supv::DisablePeriodicHkTransmission packet(spParams); + ReturnValue_t result = packet.buildPacket(); + if (result != returnvalue::OK) { + return result; + } + sendCommand(supv::DISABLE_AUTO_TM, packet, false); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::prepareLatchupConfigCmd(const uint8_t* commandData, + DeviceCommandId_t deviceCommand, + size_t cmdDataLen) { + ReturnValue_t result = returnvalue::OK; + if (cmdDataLen < 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + uint8_t latchupId = *commandData; + if (latchupId > 6) { + return result::INVALID_LATCHUP_ID; + } + switch (deviceCommand) { + case (supv::ENABLE_LATCHUP_ALERT): { + supv::LatchupAlert packet(spParams); + result = packet.buildPacket(true, latchupId); + if (result != returnvalue::OK) { + return result; + } + sendCommand(deviceCommand, packet, false); + break; + } + case (supv::DISABLE_LATCHUP_ALERT): { + supv::LatchupAlert packet(spParams); + result = packet.buildPacket(false, latchupId); + if (result != returnvalue::OK) { + return result; + } + sendCommand(deviceCommand, packet, false); + break; + } + default: { + sif::debug << "PlocSupervisorHandler::prepareLatchupConfigCmd: Invalid command id" + << std::endl; + result = returnvalue::FAILED; + break; + } + } + return result; +} + +ReturnValue_t FreshSupvHandler::prepareSetAlertLimitCmd(const uint8_t* commandData, + size_t cmdDataLen) { + if (cmdDataLen < 5) { + return HasActionsIF::INVALID_PARAMETERS; + } + uint8_t offset = 0; + uint8_t latchupId = *commandData; + offset += 1; + uint32_t dutycycle = *(commandData + offset) << 24 | *(commandData + offset + 1) << 16 | + *(commandData + offset + 2) << 8 | *(commandData + offset + 3); + if (latchupId > 6) { + return result::INVALID_LATCHUP_ID; + } + supv::SetAlertlimit packet(spParams); + ReturnValue_t result = packet.buildPacket(latchupId, dutycycle); + if (result != returnvalue::OK) { + return result; + } + sendCommand(supv::SET_ALERT_LIMIT, packet, false); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::prepareSetShutdownTimeoutCmd(const uint8_t* commandData, + size_t cmdDataLen) { + if (cmdDataLen < 4) { + return HasActionsIF::INVALID_PARAMETERS; + } + uint32_t timeout = 0; + ReturnValue_t result = returnvalue::OK; + size_t size = sizeof(timeout); + result = + SerializeAdapter::deSerialize(&timeout, &commandData, &size, SerializeIF::Endianness::BIG); + if (result != returnvalue::OK) { + sif::warning + << "PlocSupervisorHandler::prepareSetShutdownTimeoutCmd: Failed to deserialize timeout" + << std::endl; + return result; + } + supv::SetShutdownTimeout packet(spParams); + result = packet.buildPacket(timeout); + if (result != returnvalue::OK) { + return result; + } + sendCommand(supv::SET_SHUTDOWN_TIMEOUT, packet, false); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::prepareSetGpioCmd(const uint8_t* commandData, + size_t commandDataLen) { + if (commandDataLen < 3) { + return HasActionsIF::INVALID_PARAMETERS; + } + uint8_t port = *commandData; + uint8_t pin = *(commandData + 1); + uint8_t val = *(commandData + 2); + supv::SetGpio packet(spParams); + ReturnValue_t result = packet.buildPacket(port, pin, val); + if (result != returnvalue::OK) { + return result; + } + sendCommand(supv::SET_GPIO, packet, false); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::prepareReadGpioCmd(const uint8_t* commandData, + size_t commandDataLen) { + if (commandDataLen < 2) { + return HasActionsIF::INVALID_PARAMETERS; + } + uint8_t port = *commandData; + uint8_t pin = *(commandData + 1); + supv::ReadGpio packet(spParams); + ReturnValue_t result = packet.buildPacket(port, pin); + if (result != returnvalue::OK) { + return result; + } + sendCommand(supv::READ_GPIO, packet, false); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::prepareFactoryResetCmd(const uint8_t* commandData, size_t len) { + FactoryReset resetCmd(spParams); + if (len < 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + ReturnValue_t result = resetCmd.buildPacket(commandData[0]); + if (result != returnvalue::OK) { + return result; + } + sendCommand(supv::FACTORY_RESET, resetCmd, false); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::prepareSetAdcEnabledChannelsCmd(const uint8_t* commandData) { + uint16_t ch = *(commandData) << 8 | *(commandData + 1); + supv::SetAdcEnabledChannels packet(spParams); + ReturnValue_t result = packet.buildPacket(ch); + if (result != returnvalue::OK) { + return result; + } + sendCommand(supv::SET_ADC_ENABLED_CHANNELS, packet, false); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::prepareSetAdcWindowAndStrideCmd(const uint8_t* commandData) { + uint8_t offset = 0; + uint16_t windowSize = *(commandData + offset) << 8 | *(commandData + offset + 1); + offset += 2; + uint16_t stridingStepSize = *(commandData + offset) << 8 | *(commandData + offset + 1); + supv::SetAdcWindowAndStride packet(spParams); + ReturnValue_t result = packet.buildPacket(windowSize, stridingStepSize); + if (result != returnvalue::OK) { + return result; + } + sendCommand(supv::SET_ADC_WINDOW_AND_STRIDE, packet, false); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::prepareSetAdcThresholdCmd(const uint8_t* commandData) { + uint32_t threshold = *(commandData) << 24 | *(commandData + 1) << 16 | *(commandData + 2) << 8 | + *(commandData + 3); + supv::SetAdcThreshold packet(spParams); + ReturnValue_t result = packet.buildPacket(threshold); + if (result != returnvalue::OK) { + return result; + } + sendCommand(supv::SET_ADC_THRESHOLD, packet, false); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::prepareWipeMramCmd(const uint8_t* commandData, size_t cmdDataLen) { + if (cmdDataLen < 8) { + return HasActionsIF::INVALID_PARAMETERS; + } + uint32_t start = 0; + uint32_t stop = 0; + size_t size = sizeof(start) + sizeof(stop); + SerializeAdapter::deSerialize(&start, &commandData, &size, SerializeIF::Endianness::BIG); + SerializeAdapter::deSerialize(&stop, &commandData, &size, SerializeIF::Endianness::BIG); + if ((stop - start) <= 0) { + return result::INVALID_MRAM_ADDRESSES; + } + supv::MramCmd packet(spParams); + ReturnValue_t result = packet.buildPacket(start, stop, supv::MramCmd::MramAction::WIPE); + if (result != returnvalue::OK) { + return result; + } + sendCommand(supv::WIPE_MRAM, packet, false); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::parseTmPackets() { + uint8_t* receivedData = nullptr; + size_t receivedSize = 0; + while (true) { + ReturnValue_t result = + uartManager->readReceivedMessage(comCookie, &receivedData, &receivedSize); + if (result != returnvalue::OK or receivedSize == 0) { + break; + } + tmReader.setReadOnlyData(receivedData, receivedSize); + if (tmReader.checkCrc() != returnvalue::OK) { + sif::warning << "PlocSupervisorHandler::parseTmPackets: CRC failure for packet with size " + << receivedSize << std::endl; + arrayprinter::print(receivedData, receivedSize); + continue; + } + if (supv::DEBUG_PLOC_SUPV) { + handlePacketPrint(); + } + uint16_t apid = tmReader.getModuleApid(); + switch (apid) { + case (Apid::TMTC_MAN): { + switch (tmReader.getServiceId()) { + case (static_cast(supv::tm::TmtcId::ACK)): + case (static_cast(supv::tm::TmtcId::NAK)): { + handleAckReport(receivedData); + continue; + } + case (static_cast(supv::tm::TmtcId::EXEC_ACK)): + case (static_cast(supv::tm::TmtcId::EXEC_NAK)): { + handleExecutionReport(receivedData); + continue; + } + } + break; + } + case (Apid::HK): { + if (tmReader.getServiceId() == static_cast(supv::tm::HkId::REPORT)) { + handleHkReport(receivedData); + continue; + } else if (tmReader.getServiceId() == static_cast(supv::tm::HkId::HARDFAULTS)) { + handleBadApidServiceCombination(SUPV_UNINIMPLEMENTED_TM, apid, tmReader.getServiceId()); + return INVALID_DATA; + } + break; + } + case (Apid::BOOT_MAN): { + if (tmReader.getServiceId() == + static_cast(supv::tm::BootManId::BOOT_STATUS_REPORT)) { + handleBootStatusReport(receivedData); + continue; + } + break; + } + case (Apid::ADC_MON): { + if (tmReader.getServiceId() == static_cast(supv::tm::AdcMonId::ADC_REPORT)) { + genericHandleTm("ADC", receivedData, adcReport, supv::Apid::ADC_MON, + static_cast(supv::tc::AdcMonId::REQUEST_ADC_SAMPLE)); + continue; + } + break; + } + case (Apid::MEM_MAN): { + if (tmReader.getServiceId() == + static_cast(supv::tm::MemManId::UPDATE_STATUS_REPORT)) { + sif::warning << "FreshSupvHandler: Update status report parsing not implemented" + << std::endl; + // confirmReplyPacketReceived(supv::Apid::MEM_MAN, + // supv::tc::MemManId::UPDATE_STATUS_REPORT); + continue; + } + break; + } + case (Apid::DATA_LOGGER): { + if (tmReader.getServiceId() == + static_cast(supv::tm::DataLoggerId::COUNTERS_REPORT)) { + genericHandleTm("COUNTERS", receivedData, countersReport, supv::Apid::DATA_LOGGER, + static_cast(supv::tc::DataLoggerServiceId::REQUEST_COUNTERS)); + continue; + } + } + } + handleBadApidServiceCombination(SUPV_UNKNOWN_TM, apid, tmReader.getServiceId()); + } + return returnvalue::OK; +} + +void FreshSupvHandler::handleBadApidServiceCombination(Event event, unsigned int apid, + unsigned int serviceId) { + const char* printString = ""; + if (event == SUPV_UNKNOWN_TM) { + printString = "PlocSupervisorHandler: Unknown"; + } else if (event == SUPV_UNINIMPLEMENTED_TM) { + printString = "PlocSupervisorHandler: Unimplemented"; + } + triggerEvent(event, apid, tmReader.getServiceId()); + sif::warning << printString << " APID service combination 0x" << std::setw(2) << std::setfill('0') + << std::hex << apid << ", 0x" << std::setw(2) << serviceId << std::endl; +} + +void FreshSupvHandler::handlePacketPrint() { + if (tmReader.getModuleApid() == Apid::TMTC_MAN) { + if ((tmReader.getServiceId() == static_cast(supv::tm::TmtcId::ACK)) or + (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::NAK))) { + AcknowledgmentReport ack(tmReader); + ReturnValue_t result = ack.parse(false); + if (result != returnvalue::OK) { + sif::warning << "PlocSupervisorHandler: Parsing ACK failed. "; + if (result == result::INVALID_SERVICE_ID) { + sif::warning << "Invalid service ID" << std::endl; + } else if (result == result::CRC_FAILURE) { + sif::warning << "CRC check failed" << std::endl; + } else { + sif::warning << "Returncode 0x" << std::hex << std::setw(4) << result << std::dec + << std::endl; + } + } + if (mode == MODE_NORMAL and supv::REDUCE_NORMAL_MODE_PRINTOUT and + ack.getRefModuleApid() == (uint8_t)supv::Apid::HK and + ack.getRefServiceId() == (uint8_t)supv::tc::HkId::GET_REPORT) { + return; + } + const char* printStr = "???"; + if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::ACK)) { + printStr = "ACK"; + + } else if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::NAK)) { + printStr = "NAK"; + } + sif::debug << "PlocSupervisorHandler: RECV " << printStr << " for APID Module ID " + << (int)ack.getRefModuleApid() << " Service ID " << (int)ack.getRefServiceId() + << " Seq Count " << ack.getRefSequenceCount() << std::endl; + return; + } else if ((tmReader.getServiceId() == static_cast(supv::tm::TmtcId::EXEC_ACK)) or + (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::EXEC_NAK))) { + ExecutionReport exe(tmReader); + ReturnValue_t result = exe.parse(false); + if (result != returnvalue::OK) { + sif::warning << "PlocSupervisorHandler: Parsing EXE failed" << std::endl; + } + const char* printStr = "???"; + if (mode == MODE_NORMAL and supv::REDUCE_NORMAL_MODE_PRINTOUT and + exe.getRefModuleApid() == (uint8_t)supv::Apid::HK and + exe.getRefServiceId() == (uint8_t)supv::tc::HkId::GET_REPORT) { + return; + } + if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::EXEC_ACK)) { + printStr = "ACK EXE"; + + } else if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::EXEC_NAK)) { + printStr = "NAK EXE"; + } + sif::debug << "PlocSupervisorHandler: RECV " << printStr << " for APID Module ID " + << (int)exe.getRefModuleApid() << " Service ID " << (int)exe.getRefServiceId() + << " Seq Count " << exe.getRefSequenceCount() << std::endl; + return; + } + } + if (mode == MODE_NORMAL and supv::REDUCE_NORMAL_MODE_PRINTOUT and + tmReader.getModuleApid() == supv::Apid::HK and + tmReader.getServiceId() == static_cast(supv::tm::HkId::REPORT)) { + return; + } + sif::debug << "PlocSupervisorHandler: RECV PACKET Size " << tmReader.getFullPacketLen() + << " Module APID " << (int)tmReader.getModuleApid() << " Service ID " + << (int)tmReader.getServiceId() << std::endl; +} + +bool FreshSupvHandler::isCommandAlreadyActive(ActionId_t actionId) const { + // Not the most efficient implementation but who cares. It's not like this map is going + // to be huge in the nominal case.. + for (const auto& info : activeActionCmds) { + if (info.second.commandId == actionId and info.second.isPending) { + return true; + } + } + return false; +} + +ReturnValue_t FreshSupvHandler::extractUpdateCommand(const uint8_t* commandData, size_t size, + supv::UpdateParams& params) { + size_t remSize = size; + if (size > (config::MAX_FILENAME_SIZE + config::MAX_PATH_SIZE + sizeof(params.memId)) + + sizeof(params.startAddr) + sizeof(params.bytesWritten) + sizeof(params.seqCount) + + sizeof(uint8_t)) { + sif::warning << "PlocSupervisorHandler::extractUpdateCommand: Data size too big" << std::endl; + return result::INVALID_LENGTH; + } + ReturnValue_t result = returnvalue::OK; + result = extractBaseParams(&commandData, size, params); + result = SerializeAdapter::deSerialize(¶ms.bytesWritten, &commandData, &remSize, + SerializeIF::Endianness::BIG); + if (result != returnvalue::OK) { + sif::warning << "PlocSupervisorHandler::extractUpdateCommand: Failed to deserialize bytes " + "already written" + << std::endl; + return result; + } + result = SerializeAdapter::deSerialize(¶ms.seqCount, &commandData, &remSize, + SerializeIF::Endianness::BIG); + if (result != returnvalue::OK) { + sif::warning + << "PlocSupervisorHandler::extractUpdateCommand: Failed to deserialize start sequence count" + << std::endl; + return result; + } + uint8_t delMemRaw = 0; + result = SerializeAdapter::deSerialize(&delMemRaw, &commandData, &remSize, + SerializeIF::Endianness::BIG); + if (result != returnvalue::OK) { + sif::warning + << "PlocSupervisorHandler::extractUpdateCommand: Failed to deserialize whether to delete " + "memory" + << std::endl; + return result; + } + params.deleteMemory = delMemRaw; + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::extractBaseParams(const uint8_t** commandData, size_t& remSize, + supv::UpdateParams& params) { + bool nullTermFound = false; + for (size_t idx = 0; idx < remSize; idx++) { + if ((*commandData)[idx] == '\0') { + nullTermFound = true; + break; + } + } + if (not nullTermFound) { + return returnvalue::FAILED; + } + params.file = std::string(reinterpret_cast(*commandData)); + if (params.file.size() > (config::MAX_FILENAME_SIZE + config::MAX_PATH_SIZE)) { + sif::warning << "PlocSupervisorHandler::extractUpdateCommand: Filename too long" << std::endl; + return result::FILENAME_TOO_LONG; + } + *commandData += params.file.size() + SIZE_NULL_TERMINATOR; + remSize -= (params.file.size() + SIZE_NULL_TERMINATOR); + params.memId = **commandData; + *commandData += 1; + remSize -= 1; + ReturnValue_t result = SerializeAdapter::deSerialize(¶ms.startAddr, commandData, &remSize, + SerializeIF::Endianness::BIG); + if (result != returnvalue::OK) { + sif::warning << "PlocSupervisorHandler::extractBaseParams: Failed to deserialize start address" + << std::endl; + return result; + } + return result; +} + +void FreshSupvHandler::handleEvent(EventMessage* eventMessage) { + ReturnValue_t result = returnvalue::OK; + object_id_t objectId = eventMessage->getReporter(); + Event event = eventMessage->getEvent(); + switch (objectId) { + case objects::PLOC_SUPERVISOR_HELPER: { + // After execution of update procedure, PLOC is in a state where it draws approx. 700 mA of + // current. To leave this state the shutdown MPSoC command must be sent here. + if (event == PlocSupvUartManager::SUPV_UPDATE_FAILED || + event == PlocSupvUartManager::SUPV_UPDATE_SUCCESSFUL || + event == PlocSupvUartManager::SUPV_CONTINUE_UPDATE_FAILED || + event == PlocSupvUartManager::SUPV_CONTINUE_UPDATE_SUCCESSFUL || + event == PlocSupvUartManager::SUPV_MEM_CHECK_FAIL || + event == PlocSupvUartManager::SUPV_MEM_CHECK_OK) { + if (not isCommandAlreadyActive(supv::SHUTDOWN_MPSOC)) { + CommandMessage actionMsg; + ActionMessage::setCommand(&actionMsg, supv::SHUTDOWN_MPSOC, store_address_t::invalid()); + result = messageQueue->sendMessage(getCommandQueue(), &actionMsg); + if (result != returnvalue::OK) { + triggerEvent(supv::SUPV_MPSOC_SHUTDOWN_BUILD_FAILED); + sif::warning << "PlocSupervisorHandler::handleEvent: Failed to build MPSoC shutdown " + "command" + << std::endl; + return; + } + } + } + break; + } + default: + sif::debug << "PlocMPSoCHandler::handleEvent: Did not subscribe to this event" << std::endl; + break; + } +} + +ReturnValue_t FreshSupvHandler::eventSubscription() { + ReturnValue_t result = returnvalue::OK; + EventManagerIF* manager = ObjectManager::instance()->get(objects::EVENT_MANAGER); + if (manager == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "PlocSupervisorHandler::eventSubscritpion: Invalid event manager" << std::endl; +#endif + return ObjectManagerIF::CHILD_INIT_FAILED; + ; + } + result = manager->registerListener(eventQueue->getId()); + if (result != returnvalue::OK) { + return result; + } + result = manager->subscribeToEventRange( + eventQueue->getId(), event::getEventId(PlocSupvUartManager::SUPV_UPDATE_FAILED), + event::getEventId(PlocSupvUartManager::SUPV_MEM_CHECK_FAIL)); + if (result != returnvalue::OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "PlocSupervisorHandler::eventSubscritpion: Failed to subscribe to events from " + " ploc supervisor helper" + << std::endl; +#endif + return ObjectManagerIF::CHILD_INIT_FAILED; + } + return result; +} + +ReturnValue_t FreshSupvHandler::handleAckReport(const uint8_t* data) { + using namespace supv; + ReturnValue_t result = returnvalue::OK; + AcknowledgmentReport ack(tmReader); + result = ack.parse(false); + if (result != returnvalue::OK) { + return result; + } + auto infoIter = + activeActionCmds.find(buildActiveCmdKey(ack.getRefModuleApid(), ack.getRefServiceId())); + if (infoIter == activeActionCmds.end()) { + triggerEvent(SUPV_ACK_UNKNOWN_COMMAND, ack.getRefModuleApid(), ack.getRefServiceId()); + return result; + } + ActiveCmdInfo& info = infoIter->second; + if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::NAK)) { + triggerEvent(SUPV_ACK_FAILURE, info.commandId, static_cast(ack.getStatusCode())); + ack.printStatusInformationAck(); + printAckFailureInfo(ack.getStatusCode(), info.commandId); + if (info.commandedBy != MessageQueueIF::NO_QUEUE) { + actionHelper.finish(false, info.commandedBy, info.commandId, result::RECEIVED_ACK_FAILURE); + } + info.isPending = false; + return returnvalue::OK; + } + info.ackRecv = true; + performCommandCompletionHandling(static_cast((infoIter->first >> 16) & 0xffff), + infoIter->first & 0xff, info); + return result; +} + +void FreshSupvHandler::performCommandCompletionHandling(supv::Apid apid, uint8_t serviceId, + ActiveCmdInfo& info) { + if (info.ackRecv and info.ackExeRecv and + (not info.replyPacketExpected or info.replyPacketReceived)) { + if (info.commandedBy != MessageQueueIF::NO_QUEUE) { + actionHelper.finish(true, info.commandedBy, info.commandId, returnvalue::OK); + } + info.isPending = false; + } +} + +void FreshSupvHandler::printAckFailureInfo(uint16_t statusCode, DeviceCommandId_t commandId) { + switch (commandId) { + case (supv::SET_TIME_REF): { + sif::warning + << "PlocSupervisoHandler: Setting time failed. Make sure the OBC has a valid time" + << std::endl; + break; + } + default: + break; + } +} + +uint32_t FreshSupvHandler::buildActiveCmdKey(uint16_t moduleApid, uint8_t serviceId) { + return (moduleApid << 16) | serviceId; +} + +ReturnValue_t FreshSupvHandler::handleExecutionReport(const uint8_t* data) { + using namespace supv; + ReturnValue_t result = returnvalue::OK; + ExecutionReport exe(tmReader); + result = exe.parse(false); + if (result != OK) { + sif::warning << "FreshSupvHandler::handleExecutionReport: Parsing ACK EXE failed" << std::endl; + return result; + } + auto infoIter = + activeActionCmds.find(buildActiveCmdKey(exe.getRefModuleApid(), exe.getRefServiceId())); + if (infoIter == activeActionCmds.end()) { + triggerEvent(SUPV_EXE_ACK_UNKNOWN_COMMAND, exe.getRefModuleApid(), exe.getRefServiceId()); + return result; + } + ActiveCmdInfo& info = infoIter->second; + if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::EXEC_ACK)) { + result = handleExecutionSuccessReport(info, exe); + } else if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::EXEC_NAK)) { + handleExecutionFailureReport(info, exe); + return returnvalue::OK; + } + info.ackExeRecv = true; + performCommandCompletionHandling(static_cast((infoIter->first >> 16) & 0xffff), + infoIter->first & 0xff, info); + + return result; +} + +ReturnValue_t FreshSupvHandler::handleExecutionSuccessReport(ActiveCmdInfo& info, + ExecutionReport& report) { + switch (info.commandId) { + case supv::READ_GPIO: { + // TODO: Fix + uint16_t gpioState = report.getStatusCode(); +#if OBSW_DEBUG_PLOC_SUPERVISOR == 1 + sif::info << "PlocSupervisorHandler: Read GPIO TM, State: " << gpioState << std::endl; +#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */ + uint8_t data[sizeof(gpioState)]; + size_t size = 0; + ReturnValue_t result = SerializeAdapter::serialize(&gpioState, data, &size, sizeof(gpioState), + SerializeIF::Endianness::BIG); + if (result != returnvalue::OK) { + sif::debug << "PlocSupervisorHandler: Failed to deserialize GPIO state" << std::endl; + } + result = actionHelper.reportData(info.commandedBy, info.commandId, data, sizeof(data)); + if (result != returnvalue::OK) { + sif::warning << "PlocSupervisorHandler: Read GPIO, failed to report data" << std::endl; + } + break; + } + case supv::SET_TIME_REF: { + if (startupState == StartupState::WAIT_FOR_TIME_REPLY) { + startupState = StartupState::TIME_WAS_SET; + } + break; + } + default: + break; + } + return returnvalue::OK; +} + +void FreshSupvHandler::handleExecutionFailureReport(ActiveCmdInfo& info, ExecutionReport& report) { + using namespace supv; + report.printStatusInformationExe(); + if (info.commandId != DeviceHandlerIF::NO_COMMAND_ID) { + triggerEvent(SUPV_EXE_FAILURE, info.commandId, static_cast(report.getStatusCode())); + } + if (info.commandedBy) { + actionHelper.finish(false, info.commandedBy, info.commandId, report.getStatusCode()); + } + info.isPending = false; +} + +void FreshSupvHandler::confirmReplyPacketReceived(supv::Apid apid, uint8_t serviceId) { + auto infoIter = activeActionCmds.find(buildActiveCmdKey(apid, serviceId)); + if (infoIter != activeActionCmds.end()) { + ActiveCmdInfo& info = infoIter->second; + info.replyPacketReceived = true; + performCommandCompletionHandling(static_cast((infoIter->first >> 16) & 0xffff), + infoIter->first & 0xff, info); + } +} + +ReturnValue_t FreshSupvHandler::handleHkReport(const uint8_t* data) { + ReturnValue_t result = returnvalue::OK; + + result = verifyPacket(data, tmReader.getFullPacketLen()); + + if (result == result::CRC_FAILURE) { + sif::error << "PlocSupervisorHandler::handleHkReport: Hk report has invalid crc" << std::endl; + return result; + } + + uint16_t offset = supv::PAYLOAD_OFFSET; + hkSet.tempPs = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | + *(data + offset + 3); + offset += 4; + hkSet.tempPl = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | + *(data + offset + 3); + offset += 4; + hkSet.tempSup = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | + *(data + offset + 3); + offset += 4; + size_t size = sizeof(hkSet.uptime.value); + result = SerializeAdapter::deSerialize(&hkSet.uptime, data + offset, &size, + SerializeIF::Endianness::BIG); + offset += 8; + hkSet.cpuLoad = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | + *(data + offset + 3); + offset += 4; + hkSet.availableHeap = *(data + offset) << 24 | *(data + offset + 1) << 16 | + *(data + offset + 2) << 8 | *(data + offset + 3); + offset += 4; + hkSet.numTcs = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | + *(data + offset + 3); + offset += 4; + hkSet.numTms = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | + *(data + offset + 3); + offset += 4; + hkSet.socState = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | + *(data + offset + 3); + offset += 4; + hkSet.nvm0_1_state = *(data + offset); + offset += 1; + hkSet.nvm3_state = *(data + offset); + offset += 1; + hkSet.missionIoState = *(data + offset); + offset += 1; + hkSet.fmcState = *(data + offset); + offset += 1; + + hkSet.setValidity(true, true); + confirmReplyPacketReceived(supv::Apid::HK, static_cast(supv::tc::HkId::GET_REPORT)); + +#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_PLOC_SUPERVISOR == 1 + sif::info << "PlocSupervisorHandler::handleHkReport: temp_ps: " << hkSet.tempPs << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: temp_pl: " << hkSet.tempPl << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: temp_sup: " << hkSet.tempSup << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: uptime: " << hkSet.uptime << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: cpu_load: " << hkSet.cpuLoad << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: available_heap: " << hkSet.availableHeap + << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: num_tcs: " << hkSet.numTcs << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: num_tms: " << hkSet.numTms << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: soc_state: " << hkSet.socState << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: nvm0_1_state: " + << static_cast(hkSet.nvm0_1_state.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: nvm3_state: " + << static_cast(hkSet.nvm3_state.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: mission_io_state: " + << static_cast(hkSet.missionIoState.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: fmc_state: " + << static_cast(hkSet.fmcState.value) << std::endl; + +#endif + + return result; +} + +ReturnValue_t FreshSupvHandler::verifyPacket(const uint8_t* start, size_t foundLen) { + if (CRC::crc16ccitt(start, foundLen) != 0) { + return result::CRC_FAILURE; + } + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::handleBootStatusReport(const uint8_t* data) { + ReturnValue_t result = returnvalue::OK; + + result = verifyPacket(data, tmReader.getFullPacketLen()); + + if (result == result::CRC_FAILURE) { + sif::error << "PlocSupervisorHandler::handleBootStatusReport: Boot status report has invalid" + " crc" + << std::endl; + return result; + } + + const uint8_t* payloadStart = tmReader.getPayloadStart(); + uint16_t offset = 0; + bootStatusReport.socState = payloadStart[0]; + offset += 1; + bootStatusReport.powerCycles = payloadStart[1]; + offset += 1; + bootStatusReport.bootAfterMs = *(payloadStart + offset) << 24 | + *(payloadStart + offset + 1) << 16 | + *(payloadStart + offset + 2) << 8 | *(payloadStart + offset + 3); + offset += 4; + bootStatusReport.bootTimeoutMs = *(payloadStart + offset) << 24 | + *(payloadStart + offset + 1) << 16 | + *(payloadStart + offset + 2) << 8 | *(payloadStart + offset + 3); + offset += 4; + bootStatusReport.activeNvm = *(payloadStart + offset); + offset += 1; + bootStatusReport.bp0State = *(payloadStart + offset); + offset += 1; + bootStatusReport.bp1State = *(payloadStart + offset); + offset += 1; + bootStatusReport.bp2State = *(payloadStart + offset); + offset += 1; + bootStatusReport.bootState = *(payloadStart + offset); + offset += 1; + bootStatusReport.bootCycles = *(payloadStart + offset); + + bootStatusReport.setValidity(true, true); + confirmReplyPacketReceived(supv::Apid::BOOT_MAN, + static_cast(supv::tc::BootManId::GET_BOOT_STATUS_REPORT)); + +#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_PLOC_SUPERVISOR == 1 + sif::info << "PlocSupervisorHandler::handleBootStatusReport: SoC State (0 - off, 1 - booting, 2 " + "- Update, 3 " + "- operating, 4 - Shutdown, 5 - Reset): " + << static_cast(bootStatusReport.socState.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleBootStatusReport: Power Cycles: " + << static_cast(bootStatusReport.powerCycles.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleBootStatusReport: BootAfterMs: " + << bootStatusReport.bootAfterMs << " ms" << std::endl; + sif::info << "PlocSupervisorHandler::handleBootStatusReport: BootTimeoutMs: " << std::dec + << bootStatusReport.bootTimeoutMs << " ms" << std::endl; + sif::info << "PlocSupervisorHandler::handleBootStatusReport: Active NVM: " + << static_cast(bootStatusReport.activeNvm.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleBootStatusReport: BP0: " + << static_cast(bootStatusReport.bp0State.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleBootStatusReport: BP1: " + << static_cast(bootStatusReport.bp1State.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleBootStatusReport: BP2: " + << static_cast(bootStatusReport.bp2State.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleBootStatusReport: Boot state: " + << static_cast(bootStatusReport.bootState.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleBootStatusReport: Boot cycles: " + << static_cast(bootStatusReport.bootCycles.value) << std::endl; +#endif + + return result; +} + +ReturnValue_t FreshSupvHandler::handleLatchupStatusReport(const uint8_t* data) { + ReturnValue_t result = returnvalue::OK; + + result = verifyPacket(data, tmReader.getFullPacketLen()); + + if (result == result::CRC_FAILURE) { + sif::error << "PlocSupervisorHandler::handleLatchupStatusReport: Latchup status report has " + << "invalid crc" << std::endl; + return result; + } + + const uint8_t* payloadData = tmReader.getPayloadStart(); + uint16_t offset = 0; + latchupStatusReport.id = *(payloadData + offset); + offset += 1; + latchupStatusReport.cnt0 = *(payloadData + offset) << 8 | *(payloadData + offset + 1); + offset += 2; + latchupStatusReport.cnt1 = *(payloadData + offset) << 8 | *(payloadData + offset + 1); + offset += 2; + latchupStatusReport.cnt2 = *(payloadData + offset) << 8 | *(payloadData + offset + 1); + offset += 2; + latchupStatusReport.cnt3 = *(payloadData + offset) << 8 | *(payloadData + offset + 1); + offset += 2; + latchupStatusReport.cnt4 = *(payloadData + offset) << 8 | *(payloadData + offset + 1); + offset += 2; + latchupStatusReport.cnt5 = *(payloadData + offset) << 8 | *(payloadData + offset + 1); + offset += 2; + latchupStatusReport.cnt6 = *(payloadData + offset) << 8 | *(data + offset + 1); + offset += 2; + uint16_t msec = *(payloadData + offset) << 8 | *(payloadData + offset + 1); + latchupStatusReport.isSet = msec >> supv::LatchupStatusReport::IS_SET_BIT_POS; + latchupStatusReport.timeMsec = msec & (~(1 << latchupStatusReport.IS_SET_BIT_POS)); + offset += 2; + latchupStatusReport.timeSec = *(payloadData + offset); + offset += 1; + latchupStatusReport.timeMin = *(payloadData + offset); + offset += 1; + latchupStatusReport.timeHour = *(payloadData + offset); + offset += 1; + latchupStatusReport.timeDay = *(payloadData + offset); + offset += 1; + latchupStatusReport.timeMon = *(payloadData + offset); + offset += 1; + latchupStatusReport.timeYear = *(payloadData + offset); + + latchupStatusReport.setValidity(true, true); + confirmReplyPacketReceived(supv::Apid::LATCHUP_MON, + static_cast(supv::tc::LatchupMonId::GET_STATUS_REPORT)); +#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_PLOC_SUPERVISOR == 1 + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Latchup ID: " + << static_cast(latchupStatusReport.id.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: CNT0: " + << latchupStatusReport.cnt0 << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: CNT1: " + << latchupStatusReport.cnt1 << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: CNT2: " + << latchupStatusReport.cnt2 << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: CNT3: " + << latchupStatusReport.cnt3 << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: CNT4: " + << latchupStatusReport.cnt4 << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: CNT5: " + << latchupStatusReport.cnt5 << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: CNT6: " + << latchupStatusReport.cnt6 << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Sec: " + << static_cast(latchupStatusReport.timeSec.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Min: " + << static_cast(latchupStatusReport.timeMin.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Hour: " + << static_cast(latchupStatusReport.timeHour.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Day: " + << static_cast(latchupStatusReport.timeDay.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Mon: " + << static_cast(latchupStatusReport.timeMon.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Year: " + << static_cast(latchupStatusReport.timeYear.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Msec: " + << static_cast(latchupStatusReport.timeMsec.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: isSet: " + << static_cast(latchupStatusReport.isSet.value) << std::endl; +#endif + + return result; +} + +ReturnValue_t FreshSupvHandler::genericHandleTm(const char* contextString, const uint8_t* data, + LocalPoolDataSetBase& set, supv::Apid apid, + uint8_t serviceId) { + ReturnValue_t result = returnvalue::OK; + + result = verifyPacket(data, tmReader.getFullPacketLen()); + + if (result == result::CRC_FAILURE) { + sif::warning << "PlocSupervisorHandler: " << contextString << " report has " + << "invalid CRC" << std::endl; + return result; + } + + const uint8_t* dataField = data + supv::PAYLOAD_OFFSET; + PoolReadGuard pg(&set); + if (pg.getReadResult() != returnvalue::OK) { + return result; + } + set.setValidityBufferGeneration(false); + size_t size = set.getSerializedSize(); + result = set.deSerialize(&dataField, &size, SerializeIF::Endianness::BIG); + if (result != returnvalue::OK) { + sif::warning << "PlocSupervisorHandler: Deserialization failed" << std::endl; + } + set.setValidityBufferGeneration(true); + set.setValidity(true, true); + confirmReplyPacketReceived(apid, serviceId); + return result; +} + +bool FreshSupvHandler::isCommandPending() const { + for (const auto& info : activeActionCmds) { + if (info.second.isPending) { + return true; + } + } + return false; +} diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h new file mode 100644 index 00000000..2c700deb --- /dev/null +++ b/linux/payload/FreshSupvHandler.h @@ -0,0 +1,188 @@ +#ifndef LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ +#define LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ + +#include +#include + +#include + +#include "PlocSupvUartMan.h" +#include "fsfw/devicehandlers/FreshDeviceHandlerBase.h" +#include "fsfw/power/definitions.h" +#include "fsfw_hal/linux/gpio/Gpio.h" +#include "plocSupvDefs.h" + +using supv::TcBase; + +class FreshSupvHandler : public FreshDeviceHandlerBase { + public: + enum OpCode { DEFAULT_OPERATION = 0, PARSE_TM = 1 }; + + FreshSupvHandler(DhbConfig cfg, CookieIF* comCookie, Gpio uartIsolatorSwitch, + PowerSwitchIF& switchIF, power::Switch_t powerSwitch); + /** + * Periodic helper executed function, implemented by child class. + */ + void performDeviceOperation(uint8_t opCode) override; + + /** + * Implemented by child class. Handle all command messages which are + * not health, mode, action or housekeeping messages. + * @param message + * @return + */ + ReturnValue_t handleCommandMessage(CommandMessage* message) override; + + ReturnValue_t initialize() override; + + private: + // HK manager abstract functions. + LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; + ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; + + // Mode abstract functions + ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, + uint32_t* msToReachTheMode) override; + // Action override. Forward to user. + ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) override; + + /** + * @overload + * @param submode + */ + void startTransition(Mode_t newMode, Submode_t submode) override; + + ReturnValue_t performDeviceOperationPreQueueHandling(uint8_t opCode) override; + void handleTransitionToOn(); + void handleTransitionToOff(); + + private: + static constexpr bool SET_TIME_DURING_BOOT = true; + static const uint8_t SIZE_NULL_TERMINATOR = 1; + + enum class StartupState : uint8_t { + IDLE, + POWER_SWITCHING, + BOOTING, + SET_TIME, + WAIT_FOR_TIME_REPLY, + TIME_WAS_SET, + ON + }; + + StartupState startupState = StartupState::IDLE; + MessageQueueIF* eventQueue = nullptr; + supv::TmBase tmReader; + + enum class ShutdownState : uint8_t { IDLE, POWER_SWITCHING }; + ShutdownState shutdownState = ShutdownState::IDLE; + + PlocSupvUartManager* uartManager; + CookieIF* comCookie; + PowerSwitchIF& switchIF; + power::Switch_t switchId; + Gpio uartIsolatorSwitch; + + supv::HkSet hkSet; + supv::BootStatusReport bootStatusReport; + supv::LatchupStatusReport latchupStatusReport; + supv::CountersReport countersReport; + supv::AdcReport adcReport; + + bool transitionActive = false; + + Mode_t targetMode = HasModesIF::MODE_INVALID; + Submode_t targetSubmode = 0; + + Countdown switchTimeout = Countdown(2000); + // Vorago nees some time to boot properly + Countdown bootTimeout = Countdown(supv::BOOT_TIMEOUT_MS); + // Countdown interCmdCd = Countdown(supv::INTER_COMMAND_DELAY); + + PoolEntry adcRawEntry = PoolEntry(16); + PoolEntry adcEngEntry = PoolEntry(16); + PoolEntry latchupCounters = PoolEntry(7); + PoolEntry fmcStateEntry = PoolEntry(1); + PoolEntry bootStateEntry = PoolEntry(1); + PoolEntry bootCyclesEntry = PoolEntry(1); + PoolEntry tempSupEntry = PoolEntry(1); + + pwrctrl::EnablePl enablePl = pwrctrl::EnablePl(objects::POWER_CONTROLLER); + + struct ActiveCmdInfo { + ActiveCmdInfo(DeviceCommandId_t commandId, uint32_t cmdCountdownMs) + : commandId(commandId), cmdCountdown(cmdCountdownMs) {} + + DeviceCommandId_t commandId = DeviceHandlerIF::NO_COMMAND_ID; + bool isPending = false; + bool ackRecv = false; + bool ackExeRecv = false; + bool replyPacketExpected = false; + bool replyPacketReceived = false; + MessageQueueId_t commandedBy = MessageQueueIF::NO_QUEUE; + bool requiresActionReply = false; + Countdown cmdCountdown; + }; + + uint32_t buildActiveCmdKey(uint16_t moduleApid, uint8_t serviceId); + + // Map for Action commands. For normal commands, a separate static structure will be used. + std::map activeActionCmds; + + std::array commandBuffer{}; + SpacePacketCreator creator; + supv::TcParams spParams = supv::TcParams(creator); + DeviceCommandId_t commandedByCached = MessageQueueIF::NO_QUEUE; + + ReturnValue_t parseTmPackets(); + + ReturnValue_t sendCommand(DeviceCommandId_t commandId, TcBase& tc, bool replyPacketExpected, + uint32_t cmdCountdownMs = 1000); + ReturnValue_t sendEmptyCmd(DeviceCommandId_t commandId, uint16_t apid, uint8_t serviceId, + bool replyPacketExpected); + ReturnValue_t prepareSelBootImageCmd(const uint8_t* commandData); + ReturnValue_t prepareSetTimeRefCmd(); + ReturnValue_t prepareSetBootTimeoutCmd(const uint8_t* commandData, size_t cmdDataLen); + ReturnValue_t prepareRestartTriesCmd(const uint8_t* commandData, size_t cmdDataLen); + ReturnValue_t prepareDisableHk(); + ReturnValue_t prepareLatchupConfigCmd(const uint8_t* commandData, DeviceCommandId_t deviceCommand, + size_t cmdDataLen); + ReturnValue_t prepareSetAlertLimitCmd(const uint8_t* commandData, size_t cmdDataLen); + ReturnValue_t prepareFactoryResetCmd(const uint8_t* commandData, size_t len); + ReturnValue_t prepareSetShutdownTimeoutCmd(const uint8_t* commandData, size_t cmdDataLen); + ReturnValue_t prepareSetGpioCmd(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t prepareReadGpioCmd(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t prepareSetAdcEnabledChannelsCmd(const uint8_t* commandData); + ReturnValue_t prepareSetAdcWindowAndStrideCmd(const uint8_t* commandData); + ReturnValue_t prepareSetAdcThresholdCmd(const uint8_t* commandData); + ReturnValue_t prepareWipeMramCmd(const uint8_t* commandData, size_t cmdDataLen); + ReturnValue_t extractUpdateCommand(const uint8_t* commandData, size_t size, + supv::UpdateParams& params); + ReturnValue_t extractBaseParams(const uint8_t** commandData, size_t& remSize, + supv::UpdateParams& params); + void handleEvent(EventMessage* eventMessage); + + void handleBadApidServiceCombination(Event event, unsigned int apid, unsigned int serviceId); + ReturnValue_t eventSubscription(); + void handlePacketPrint(); + bool isCommandAlreadyActive(ActionId_t actionId) const; + ReturnValue_t handleAckReport(const uint8_t* data); + void printAckFailureInfo(uint16_t statusCode, DeviceCommandId_t commandId); + ReturnValue_t handleExecutionReport(const uint8_t* data); + ReturnValue_t handleExecutionSuccessReport(ActiveCmdInfo& info, supv::ExecutionReport& report); + void handleExecutionFailureReport(ActiveCmdInfo& info, supv::ExecutionReport& report); + ReturnValue_t handleHkReport(const uint8_t* data); + ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen); + void confirmReplyPacketReceived(supv::Apid apid, uint8_t serviceId); + void performCommandCompletionHandling(supv::Apid apid, uint8_t serviceId, ActiveCmdInfo& info); + ReturnValue_t handleBootStatusReport(const uint8_t* data); + ReturnValue_t genericHandleTm(const char* contextString, const uint8_t* data, + LocalPoolDataSetBase& set, supv::Apid apid, uint8_t serviceId); + ReturnValue_t handleLatchupStatusReport(const uint8_t* data); + + bool isCommandPending() const; +}; + +#endif /* LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ */ diff --git a/linux/payload/PlocMpsocHandler.cpp b/linux/payload/PlocMpsocHandler.cpp index 34053c70..05b3a04e 100644 --- a/linux/payload/PlocMpsocHandler.cpp +++ b/linux/payload/PlocMpsocHandler.cpp @@ -20,9 +20,8 @@ PlocMpsocHandler::PlocMpsocHandler(object_id_t objectId, object_id_t uartComIFid if (comCookie == nullptr) { sif::error << "PlocMPSoCHandler: Invalid communication cookie" << std::endl; } - eventQueue = QueueFactory::instance()->createMessageQueue(EventMessage::EVENT_MESSAGE_SIZE * 5); - commandActionHelperQueue = - QueueFactory::instance()->createMessageQueue(EventMessage::EVENT_MESSAGE_SIZE * 5); + eventQueue = QueueFactory::instance()->createMessageQueue(10); + commandActionHelperQueue = QueueFactory::instance()->createMessageQueue(10); spParams.maxSize = sizeof(commandBuffer); spParams.buf = commandBuffer; } diff --git a/linux/payload/PlocMpsocSpecialComHelper.cpp b/linux/payload/PlocMpsocSpecialComHelper.cpp index acf88abd..66712a90 100644 --- a/linux/payload/PlocMpsocSpecialComHelper.cpp +++ b/linux/payload/PlocMpsocSpecialComHelper.cpp @@ -504,7 +504,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::checkReceivedTm() { triggerEvent(MPSOC_TM_SIZE_ERROR); return result; } - spReader.checkCrc(); + result = spReader.checkCrc(); if (result != returnvalue::OK) { sif::warning << "PLOC MPSoC: CRC check failed" << std::endl; triggerEvent(MPSOC_TM_CRC_MISSMATCH, *sequenceCount); diff --git a/linux/payload/PlocSupvUartMan.cpp b/linux/payload/PlocSupvUartMan.cpp index 1a129927..f73ca560 100644 --- a/linux/payload/PlocSupvUartMan.cpp +++ b/linux/payload/PlocSupvUartMan.cpp @@ -24,6 +24,7 @@ #include "mission/utility/Filenaming.h" #include "mission/utility/ProgressPrinter.h" #include "mission/utility/Timestamp.h" +#include "tas/crc.h" using namespace returnvalue; using namespace supv; @@ -96,9 +97,10 @@ ReturnValue_t PlocSupvUartManager::initialize() { ReturnValue_t PlocSupvUartManager::performOperation(uint8_t operationCode) { bool putTaskToSleep = false; while (true) { - lock->lockMutex(); - state = InternalState::SLEEPING; - lock->unlockMutex(); + { + MutexGuard mg(lock); + state = InternalState::SLEEPING; + } semaphore->acquire(); putTaskToSleep = false; #if OBSW_THREAD_TRACING == 1 @@ -110,9 +112,11 @@ ReturnValue_t PlocSupvUartManager::performOperation(uint8_t operationCode) { break; } handleUartReception(); - lock->lockMutex(); - InternalState currentState = state; - lock->unlockMutex(); + InternalState currentState; + { + MutexGuard mg(lock); + currentState = state; + } switch (currentState) { case InternalState::SLEEPING: case InternalState::GO_TO_SLEEP: { @@ -156,7 +160,7 @@ ReturnValue_t PlocSupvUartManager::handleUartReception() { << " bytes" << std::endl; return FAILED; } else if (bytesRead > 0) { - if (debugMode) { + if (DEBUG_MODE) { sif::info << "Received " << bytesRead << " bytes from the PLOC Supervisor:" << std::endl; arrayprinter::print(recBuf.data(), bytesRead); } @@ -571,7 +575,7 @@ ReturnValue_t PlocSupvUartManager::handlePacketTransmissionNoReply( size_t packetLen = 0; decodedQueue.retrieve(&packetLen); decodedRingBuf.readData(decodedBuf.data(), packetLen, true); - tmReader.setData(decodedBuf.data(), packetLen); + tmReader.setReadOnlyData(decodedBuf.data(), packetLen); result = checkReceivedTm(); if (result != returnvalue::OK) { continue; @@ -617,7 +621,7 @@ int PlocSupvUartManager::handleAckReception(supv::TcBase& tc, size_t packetLen) if (serviceId == static_cast(supv::tm::TmtcId::ACK) or serviceId == static_cast(supv::tm::TmtcId::NAK)) { AcknowledgmentReport ackReport(tmReader); - ReturnValue_t result = ackReport.parse(); + ReturnValue_t result = ackReport.parse(false); if (result != returnvalue::OK) { triggerEvent(ACK_RECEPTION_FAILURE); return -1; @@ -627,7 +631,7 @@ int PlocSupvUartManager::handleAckReception(supv::TcBase& tc, size_t packetLen) if (serviceId == static_cast(supv::tm::TmtcId::ACK)) { return 1; } else if (serviceId == static_cast(supv::tm::TmtcId::NAK)) { - ackReport.printStatusInformation(); + ackReport.printStatusInformationAck(); triggerEvent( SUPV_ACK_FAILURE_REPORT, buildApidServiceParam1(ackReport.getRefModuleApid(), ackReport.getRefServiceId()), @@ -649,7 +653,7 @@ int PlocSupvUartManager::handleExeAckReception(supv::TcBase& tc, size_t packetLe if (serviceId == static_cast(supv::tm::TmtcId::EXEC_ACK) or serviceId == static_cast(supv::tm::TmtcId::EXEC_NAK)) { ExecutionReport exeReport(tmReader); - ReturnValue_t result = exeReport.parse(); + ReturnValue_t result = exeReport.parse(false); if (result != returnvalue::OK) { triggerEvent(EXE_RECEPTION_FAILURE); return -1; @@ -659,7 +663,7 @@ int PlocSupvUartManager::handleExeAckReception(supv::TcBase& tc, size_t packetLe if (serviceId == static_cast(supv::tm::TmtcId::EXEC_ACK)) { return 1; } else if (serviceId == static_cast(supv::tm::TmtcId::EXEC_NAK)) { - exeReport.printStatusInformation(); + exeReport.printStatusInformationExe(); triggerEvent( SUPV_EXE_FAILURE_REPORT, buildApidServiceParam1(exeReport.getRefModuleApid(), exeReport.getRefServiceId()), @@ -682,7 +686,7 @@ ReturnValue_t PlocSupvUartManager::checkReceivedTm() { triggerEvent(SUPV_REPLY_SIZE_MISSMATCH, rememberApid); return result; } - if (not tmReader.verifyCrc()) { + if (tmReader.checkCrc() != returnvalue::OK) { triggerEvent(SUPV_REPLY_CRC_MISSMATCH, rememberApid); return result; } @@ -758,7 +762,7 @@ ReturnValue_t PlocSupvUartManager::handleCheckMemoryCommand(uint8_t failStep) { size_t packetLen = 0; decodedQueue.retrieve(&packetLen); decodedRingBuf.readData(decodedBuf.data(), packetLen, true); - tmReader.setData(decodedBuf.data(), packetLen); + tmReader.setReadOnlyData(decodedBuf.data(), packetLen); result = checkReceivedTm(); if (result != returnvalue::OK) { continue; @@ -786,7 +790,7 @@ ReturnValue_t PlocSupvUartManager::handleCheckMemoryCommand(uint8_t failStep) { } else if (tmReader.getModuleApid() == Apid::MEM_MAN) { if (ackReceived) { supv::UpdateStatusReport report(tmReader); - result = report.parse(); + result = report.parse(false); if (result != returnvalue::OK) { return result; } @@ -962,7 +966,7 @@ ReturnValue_t PlocSupvUartManager::handleRunningLongerRequest() { ReturnValue_t PlocSupvUartManager::encodeAndSendPacket(const uint8_t* sendData, size_t sendLen) { size_t encodedLen = 0; addHdlcFraming(sendData, sendLen, encodedSendBuf.data(), &encodedLen, encodedSendBuf.size()); - if (printTc) { + if (PRINT_TC) { sif::debug << "Sending TC" << std::endl; arrayprinter::print(encodedSendBuf.data(), encodedLen); } @@ -984,6 +988,9 @@ ReturnValue_t PlocSupvUartManager::readReceivedMessage(CookieIF* cookie, uint8_t return OK; } ipcQueue.retrieve(size); + if (*size > ipcBuffer.size()) { + return FAILED; + } *buffer = ipcBuffer.data(); ReturnValue_t result = ipcRingBuf.readData(ipcBuffer.data(), *size, true); if (result != OK) { @@ -1054,6 +1061,7 @@ ReturnValue_t PlocSupvUartManager::parseRecRingBufForHdlc(size_t& readSize, size triggerEvent(HDLC_CRC_ERROR); } if (retval != 0) { + readSize = ++idx; return HDLC_ERROR; } return returnvalue::OK; @@ -1084,11 +1092,14 @@ void PlocSupvUartManager::performUartShutdown() { while (not decodedQueue.empty()) { decodedQueue.pop(); } - MutexGuard mg(ipcLock); - ipcRingBuf.clear(); - while (not ipcQueue.empty()) { - ipcQueue.pop(); + { + MutexGuard mg0(ipcLock); + ipcRingBuf.clear(); + while (not ipcQueue.empty()) { + ipcQueue.pop(); + } } + MutexGuard mg1(lock); state = InternalState::GO_TO_SLEEP; } diff --git a/linux/payload/PlocSupvUartMan.h b/linux/payload/PlocSupvUartMan.h index 61d4b284..562bd3bd 100644 --- a/linux/payload/PlocSupvUartMan.h +++ b/linux/payload/PlocSupvUartMan.h @@ -16,7 +16,6 @@ #include "fsfw/returnvalues/returnvalue.h" #include "fsfw/tasks/ExecutableObjectIF.h" #include "fsfw_hal/linux/serial/SerialComIF.h" -#include "tas/crc.h" #ifdef XIPHOS_Q7S #include "bsp_q7s/fs/SdCardManager.h" @@ -121,6 +120,32 @@ class PlocSupvUartManager : public DeviceCommunicationIF, PlocSupvUartManager(object_id_t objectId); virtual ~PlocSupvUartManager(); + /** + * @brief Device specific initialization, using the cookie. + * @details + * The cookie is already prepared in the factory. If the communication + * interface needs to be set up in some way and requires cookie information, + * this can be performed in this function, which is called on device handler + * initialization. + * @param cookie + * @return + * - @c returnvalue::OK if initialization was successfull + * - Everything else triggers failure event with returnvalue as parameter 1 + */ + ReturnValue_t initializeInterface(CookieIF* cookie) override; + /** + * Called by DHB in the SEND_WRITE doSendWrite(). + * This function is used to send data to the physical device + * by implementing and calling related drivers or wrapper functions. + * @param cookie + * @param data + * @param len If this is 0, nothing shall be sent. + * @return + * - @c returnvalue::OK for successfull send + * - Everything else triggers failure event with returnvalue as parameter 1 + */ + ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override; + ReturnValue_t readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) override; ReturnValue_t initialize() override; ReturnValue_t performOperation(uint8_t operationCode = 0) override; @@ -206,11 +231,11 @@ class PlocSupvUartManager : public DeviceCommunicationIF, struct Update update; + int serialPort = 0; SemaphoreIF* semaphore; MutexIF* lock; MutexIF* ipcLock; supv::TmBase tmReader; - int serialPort = 0; struct termios tty = {}; #if OBSW_THREAD_TRACING == 1 uint32_t opCounter = 0; @@ -257,8 +282,8 @@ class PlocSupvUartManager : public DeviceCommunicationIF, std::array tmBuf{}; - bool printTc = false; - bool debugMode = false; + static constexpr bool PRINT_TC = false; + static constexpr bool DEBUG_MODE = false; bool timestamping = true; // Remembers APID to know at which command a procedure failed @@ -319,32 +344,6 @@ class PlocSupvUartManager : public DeviceCommunicationIF, void resetSpParams(); void pushIpcData(const uint8_t* data, size_t len); - /** - * @brief Device specific initialization, using the cookie. - * @details - * The cookie is already prepared in the factory. If the communication - * interface needs to be set up in some way and requires cookie information, - * this can be performed in this function, which is called on device handler - * initialization. - * @param cookie - * @return - * - @c returnvalue::OK if initialization was successfull - * - Everything else triggers failure event with returnvalue as parameter 1 - */ - ReturnValue_t initializeInterface(CookieIF* cookie) override; - - /** - * Called by DHB in the SEND_WRITE doSendWrite(). - * This function is used to send data to the physical device - * by implementing and calling related drivers or wrapper functions. - * @param cookie - * @param data - * @param len If this is 0, nothing shall be sent. - * @return - * - @c returnvalue::OK for successfull send - * - Everything else triggers failure event with returnvalue as parameter 1 - */ - ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override; /** * Called by DHB in the GET_WRITE doGetWrite(). * Get send confirmation that the data in sendMessage() was sent successfully. @@ -369,7 +368,6 @@ class PlocSupvUartManager : public DeviceCommunicationIF, * returnvalue as parameter 1 */ ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override; - ReturnValue_t readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) override; void performUartShutdown(); void updateVtime(uint8_t vtime); diff --git a/linux/payload/plocSupvDefs.h b/linux/payload/plocSupvDefs.h index 115cfe60..a770fb49 100644 --- a/linux/payload/plocSupvDefs.h +++ b/linux/payload/plocSupvDefs.h @@ -11,13 +11,46 @@ #include #include -#include +#include "eive/eventSubsystemIds.h" #include "eive/resultClassIds.h" namespace supv { +static constexpr bool DEBUG_PLOC_SUPV = false; +static constexpr bool REDUCE_NORMAL_MODE_PRINTOUT = true; + +static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_SUPERVISOR_HANDLER; + +//! [EXPORT] : [COMMENT] PLOC supervisor crc failure in telemetry packet +static const Event SUPV_MEMORY_READ_RPT_CRC_FAILURE = MAKE_EVENT(1, severity::LOW); +//! [EXPORT] : [COMMENT] Unhandled event. P1: APID, P2: Service ID +static constexpr Event SUPV_UNKNOWN_TM = MAKE_EVENT(2, severity::LOW); +static constexpr Event SUPV_UNINIMPLEMENTED_TM = MAKE_EVENT(3, severity::LOW); +//! [EXPORT] : [COMMENT] PLOC supervisor received acknowledgment failure report +static const Event SUPV_ACK_FAILURE = MAKE_EVENT(4, severity::LOW); +//! [EXPORT] : [COMMENT] PLOC received execution failure report +//! P1: ID of command for which the execution failed +//! P2: Status code sent by the supervisor handler +static const Event SUPV_EXE_FAILURE = MAKE_EVENT(5, severity::LOW); +//! [EXPORT] : [COMMENT] PLOC supervisor reply has invalid crc +static const Event SUPV_CRC_FAILURE_EVENT = MAKE_EVENT(6, severity::LOW); +//! [EXPORT] : [COMMENT] Supervisor helper currently executing a command +static const Event SUPV_HELPER_EXECUTING = MAKE_EVENT(7, severity::LOW); +//! [EXPORT] : [COMMENT] Failed to build the command to shutdown the MPSoC +static const Event SUPV_MPSOC_SHUTDOWN_BUILD_FAILED = MAKE_EVENT(8, severity::LOW); +//! [EXPORT] : [COMMENT] Received ACK, but no related command is unknown or has not been sent +// by this software instance. P1: Module APID. P2: Service ID. +static const Event SUPV_ACK_UNKNOWN_COMMAND = MAKE_EVENT(9, severity::LOW); +//! [EXPORT] : [COMMENT] Received ACK EXE, but no related command is unknown or has not been sent +// by this software instance. P1: Module APID. P2: Service ID. +static const Event SUPV_EXE_ACK_UNKNOWN_COMMAND = MAKE_EVENT(10, severity::LOW); + extern std::atomic_bool SUPV_ON; +static constexpr uint32_t INTER_COMMAND_DELAY = 20; +static constexpr uint32_t BOOT_TIMEOUT_MS = 4000; +static constexpr uint32_t MAX_TRANSITION_TIME_TO_ON_MS = BOOT_TIMEOUT_MS + 2000; +static constexpr uint32_t MAX_TRANSITION_TIME_TO_OFF_MS = 1000; namespace result { static const uint8_t INTERFACE_ID = CLASS_ID::SUPV_RETURN_VALUES_IF; @@ -107,7 +140,7 @@ static const DeviceCommandId_t FIRST_MRAM_DUMP = 30; static const DeviceCommandId_t SET_GPIO = 34; static const DeviceCommandId_t READ_GPIO = 35; static const DeviceCommandId_t RESTART_SUPERVISOR = 36; -static const DeviceCommandId_t LOGGING_REQUEST_COUNTERS = 38; +static const DeviceCommandId_t REQUEST_LOGGING_COUNTERS = 38; static constexpr DeviceCommandId_t FACTORY_RESET = 39; static const DeviceCommandId_t CONSECUTIVE_MRAM_DUMP = 43; static const DeviceCommandId_t START_MPSOC_QUIET = 45; @@ -120,7 +153,7 @@ static const DeviceCommandId_t DISABLE_AUTO_TM = 51; static const DeviceCommandId_t LOGGING_REQUEST_EVENT_BUFFERS = 54; static const DeviceCommandId_t LOGGING_CLEAR_COUNTERS = 55; static const DeviceCommandId_t LOGGING_SET_TOPIC = 56; -static const DeviceCommandId_t REQUEST_ADC_REPORT = 57; +static constexpr DeviceCommandId_t REQUEST_ADC_REPORT = 57; static const DeviceCommandId_t RESET_PL = 58; static const DeviceCommandId_t ENABLE_NVMS = 59; static const DeviceCommandId_t CONTINUE_UPDATE = 60; @@ -134,7 +167,7 @@ enum ReplyId : DeviceCommandId_t { HK_REPORT = 102, BOOT_STATUS_REPORT = 103, LATCHUP_REPORT = 104, - LOGGING_REPORT = 105, + COUNTERS_REPORT = 105, ADC_REPORT = 106, UPDATE_STATUS_REPORT = 107, }; @@ -144,7 +177,7 @@ static const uint16_t SIZE_ACK_REPORT = 14; static const uint16_t SIZE_EXE_REPORT = 14; static const uint16_t SIZE_BOOT_STATUS_REPORT = 24; static const uint16_t SIZE_LATCHUP_STATUS_REPORT = 31; -static const uint16_t SIZE_LOGGING_REPORT = 73; +static const uint16_t SIZE_COUNTERS_REPORT = 120; static const uint16_t SIZE_ADC_REPORT = 72; // 2 bits APID SRC, 00 for OBC, 2 bits APID DEST, 01 for SUPV, 7 bits CMD ID -> Mask 0x080 @@ -207,12 +240,18 @@ enum class AdcMonId : uint8_t { SET_ENABLED_CHANNELS = 0x02, SET_WINDOW_STRIDE = 0x03, SET_ADC_THRESHOLD = 0x04, - COPY_ADC_DATA_TO_MRAM = 0x05 + COPY_ADC_DATA_TO_MRAM = 0x05, + REQUEST_ADC_SAMPLE = 0x06 }; enum class MemManId : uint8_t { ERASE = 0x01, WRITE = 0x02, CHECK = 0x03 }; enum class DataLoggerServiceId : uint8_t { + // Not implemented. + READ_MRAM_CFG_DATA_LOGGER = 0x00, + REQUEST_COUNTERS = 0x01, + // Not implemented. + EVENT_BUFFER_DOWNLOAD = 0x02, WIPE_MRAM = 0x05, DUMP_MRAM = 0x06, FACTORY_RESET = 0x07 @@ -231,10 +270,12 @@ enum class TmtcId : uint8_t { ACK = 0x01, NAK = 0x02, EXEC_ACK = 0x03, EXEC_NAK enum class HkId : uint8_t { REPORT = 0x01, HARDFAULTS = 0x02 }; enum class BootManId : uint8_t { BOOT_STATUS_REPORT = 0x01 }; +enum class AdcMonId : uint8_t { ADC_REPORT = 0x01 }; enum class MemManId : uint8_t { UPDATE_STATUS_REPORT = 0x01 }; enum class LatchupMonId : uint8_t { LATCHUP_STATUS_REPORT = 0x01 }; +enum class DataLoggerId : uint8_t { COUNTERS_REPORT = 0x01 }; } // namespace tm @@ -321,13 +362,13 @@ static const uint16_t SEQUENCE_COUNT_MASK = 0xFFF; static const uint8_t HK_SET_ENTRIES = 13; static const uint8_t BOOT_REPORT_SET_ENTRIES = 10; static const uint8_t LATCHUP_RPT_SET_ENTRIES = 16; -static const uint8_t LOGGING_RPT_SET_ENTRIES = 16; +static const uint8_t LOGGING_RPT_SET_ENTRIES = 30; static const uint8_t ADC_RPT_SET_ENTRIES = 32; static const uint32_t HK_SET_ID = HK_REPORT; static const uint32_t BOOT_REPORT_SET_ID = BOOT_STATUS_REPORT; static const uint32_t LATCHUP_RPT_ID = LATCHUP_REPORT; -static const uint32_t LOGGING_RPT_ID = LOGGING_REPORT; +static const uint32_t LOGGING_RPT_ID = COUNTERS_REPORT; static const uint32_t ADC_REPORT_SET_ID = ADC_REPORT; namespace timeout { @@ -392,7 +433,7 @@ enum PoolIds : lp_id_t { BR_SOC_STATE, POWER_CYCLES, BOOT_AFTER_MS, - BOOT_TIMEOUT_MS, + BOOT_TIMEOUT_POOL_VAR_MS, ACTIVE_NVM, BP0_STATE, BP1_STATE, @@ -417,13 +458,8 @@ enum PoolIds : lp_id_t { LATCHUP_RPT_TIME_MSEC, LATCHUP_RPT_IS_SET, - LATCHUP_HAPPENED_CNT_0, - LATCHUP_HAPPENED_CNT_1, - LATCHUP_HAPPENED_CNT_2, - LATCHUP_HAPPENED_CNT_3, - LATCHUP_HAPPENED_CNT_4, - LATCHUP_HAPPENED_CNT_5, - LATCHUP_HAPPENED_CNT_6, + SIGNATURE, + LATCHUP_HAPPENED_CNTS, ADC_DEVIATION_TRIGGERS_CNT, TC_RECEIVED_CNT, TM_AVAILABLE_CNT, @@ -432,40 +468,22 @@ enum PoolIds : lp_id_t { MPSOC_BOOT_FAILED_ATTEMPTS, MPSOC_POWER_UP, MPSOC_UPDATES, - LAST_RECVD_TC, + MPSOC_HEARTBEAT_RESETS, + CPU_WDT_RESETS, + PS_HEARTBEATS_LOST, + PL_HEARTBEATS_LOST, + EB_TASK_LOST, + BM_TASK_LOST, + LM_TASK_LOST, + AM_TASK_LOST, + TCTMM_TASK_LOST, + MM_TASK_LOST, + HK_TASK_LOST, + DL_TASK_LOST, + RWS_TASKS_LOST, - ADC_RAW_0, - ADC_RAW_1, - ADC_RAW_2, - ADC_RAW_3, - ADC_RAW_4, - ADC_RAW_5, - ADC_RAW_6, - ADC_RAW_7, - ADC_RAW_8, - ADC_RAW_9, - ADC_RAW_10, - ADC_RAW_11, - ADC_RAW_12, - ADC_RAW_13, - ADC_RAW_14, - ADC_RAW_15, - ADC_ENG_0, - ADC_ENG_1, - ADC_ENG_2, - ADC_ENG_3, - ADC_ENG_4, - ADC_ENG_5, - ADC_ENG_6, - ADC_ENG_7, - ADC_ENG_8, - ADC_ENG_9, - ADC_ENG_10, - ADC_ENG_11, - ADC_ENG_12, - ADC_ENG_13, - ADC_ENG_14, - ADC_ENG_15 + ADC_RAW, + ADC_ENG, }; struct TcParams : public ploc::SpTcParams { @@ -539,15 +557,6 @@ class TmBase : public ploc::SpTmReader { } } - bool verifyCrc() { - if (checkCrc() == returnvalue::OK) { - crcOk = true; - } - return crcOk; - } - - bool crcIsOk() const { return crcOk; } - uint8_t getServiceId() const { return getPacketData()[TIMESTAMP_LEN]; } uint16_t getModuleApid() const { return getApid() & APID_MODULE_MASK; } @@ -559,9 +568,6 @@ class TmBase : public ploc::SpTmReader { } return 0; } - - private: - bool crcOk = false; }; class NoPayloadPacket : public TcBase { @@ -769,8 +775,6 @@ class SetRestartTries : public TcBase { } private: - uint8_t restartTries = 0; - void initPacket(uint8_t restartTries) { payloadStart[0] = restartTries; } }; @@ -831,8 +835,6 @@ class LatchupAlert : public TcBase { } private: - uint8_t latchupId = 0; - void initPacket(uint8_t latchupId) { payloadStart[0] = latchupId; } }; @@ -862,9 +864,6 @@ class SetAlertlimit : public TcBase { } private: - uint8_t latchupId = 0; - uint32_t dutycycle = 0; - ReturnValue_t initPacket(uint8_t latchupId, uint32_t dutycycle) { payloadStart[0] = latchupId; size_t serLen = 0; @@ -1295,8 +1294,8 @@ class VerificationReport { virtual ~VerificationReport() = default; - virtual ReturnValue_t parse() { - if (not readerBase.crcIsOk()) { + virtual ReturnValue_t parse(bool checkCrc) { + if (checkCrc and readerBase.checkCrc() != returnvalue::OK) { return result::CRC_FAILURE; } if (readerBase.getModuleApid() != Apid::TMTC_MAN) { @@ -1313,27 +1312,27 @@ class VerificationReport { ReturnValue_t result = SerializeAdapter::deSerialize(&refApid, &payloadStart, &remLen, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { - sif::debug << "VerificationReport: Failed to deserialize reference APID field" << std::endl; + sif::warning << "VerificationReport: Failed to deserialize reference APID field" << std::endl; return result; } result = SerializeAdapter::deSerialize(&refServiceId, &payloadStart, &remLen, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { - sif::debug << "VerificationReport: Failed to deserialize reference Service ID field" - << std::endl; + sif::warning << "VerificationReport: Failed to deserialize reference Service ID field" + << std::endl; return result; } result = SerializeAdapter::deSerialize(&refSeqCount, &payloadStart, &remLen, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { - sif::debug << "VerificationReport: Failed to deserialize reference sequence count field" - << std::endl; + sif::warning << "VerificationReport: Failed to deserialize reference sequence count field" + << std::endl; return result; } result = SerializeAdapter::deSerialize(&statusCode, &payloadStart, &remLen, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { - sif::debug << "VerificationReport: Failed to deserialize status code field" << std::endl; + sif::warning << "VerificationReport: Failed to deserialize status code field" << std::endl; return result; } return returnvalue::OK; @@ -1350,7 +1349,7 @@ class VerificationReport { uint32_t getStatusCode() const { return statusCode; } - virtual void printStatusInformation(const char* prefix) { + virtual void printStatusInformation(const char* prefix) const { bool codeHandled = true; if (statusCode < 0x100) { GeneralStatusCode code = static_cast(getStatusCode()); @@ -1637,15 +1636,15 @@ class AcknowledgmentReport : public VerificationReport { public: AcknowledgmentReport(TmBase& readerBase) : VerificationReport(readerBase) {} - virtual ReturnValue_t parse() override { + ReturnValue_t parse(bool checkCrc) override { if (readerBase.getServiceId() != static_cast(tm::TmtcId::ACK) and readerBase.getServiceId() != static_cast(tm::TmtcId::NAK)) { return result::INVALID_SERVICE_ID; } - return VerificationReport::parse(); + return VerificationReport::parse(checkCrc); } - void printStatusInformation() { + void printStatusInformationAck() { VerificationReport::printStatusInformation(STATUS_PRINTOUT_PREFIX); } @@ -1659,15 +1658,15 @@ class ExecutionReport : public VerificationReport { TmBase& getReader() { return readerBase; } - ReturnValue_t parse() override { + ReturnValue_t parse(bool checkCrc) override { if (readerBase.getServiceId() != static_cast(tm::TmtcId::EXEC_ACK) and readerBase.getServiceId() != static_cast(tm::TmtcId::EXEC_NAK)) { return returnvalue::FAILED; } - return VerificationReport::parse(); + return VerificationReport::parse(checkCrc); } - void printStatusInformation() { + void printStatusInformationExe() { VerificationReport::printStatusInformation(STATUS_PRINTOUT_PREFIX); } @@ -1679,8 +1678,8 @@ class UpdateStatusReport { public: UpdateStatusReport(TmBase& tmReader) : tmReader(tmReader) {} - ReturnValue_t parse() { - if (not tmReader.crcIsOk()) { + ReturnValue_t parse(bool checkCrc) { + if (checkCrc and tmReader.checkCrc() != returnvalue::OK) { return result::CRC_FAILURE; } if (tmReader.getModuleApid() != Apid::MEM_MAN) { @@ -1742,7 +1741,7 @@ class BootStatusReport : public StaticLocalDataSet { lp_var_t bootAfterMs = lp_var_t(sid.objectId, PoolIds::BOOT_AFTER_MS, this); /** The currently set boot timeout */ lp_var_t bootTimeoutMs = - lp_var_t(sid.objectId, PoolIds::BOOT_TIMEOUT_MS, this); + lp_var_t(sid.objectId, PoolIds::BOOT_TIMEOUT_POOL_VAR_MS, this); lp_var_t activeNvm = lp_var_t(sid.objectId, PoolIds::ACTIVE_NVM, this); /** States of the boot partition pins */ lp_var_t bp0State = lp_var_t(sid.objectId, PoolIds::BP0_STATE, this); @@ -1814,26 +1813,16 @@ class LatchupStatusReport : public StaticLocalDataSet { /** * @brief This dataset stores the logging report. */ -class LoggingReport : public StaticLocalDataSet { +class CountersReport : public StaticLocalDataSet { public: - LoggingReport(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, LOGGING_RPT_ID) {} + CountersReport(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, LOGGING_RPT_ID) {} - LoggingReport(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, LOGGING_RPT_ID)) {} + CountersReport(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, LOGGING_RPT_ID)) {} - lp_var_t latchupHappenCnt0 = - lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNT_0, this); - lp_var_t latchupHappenCnt1 = - lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNT_1, this); - lp_var_t latchupHappenCnt2 = - lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNT_2, this); - lp_var_t latchupHappenCnt3 = - lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNT_3, this); - lp_var_t latchupHappenCnt4 = - lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNT_4, this); - lp_var_t latchupHappenCnt5 = - lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNT_5, this); - lp_var_t latchupHappenCnt6 = - lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNT_6, this); + lp_var_t signature = + lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNTS, this); + lp_vec_t latchupHappenCnts = + lp_vec_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNTS, this); lp_var_t adcDeviationTriggersCnt = lp_var_t(sid.objectId, PoolIds::ADC_DEVIATION_TRIGGERS_CNT, this); lp_var_t tcReceivedCnt = @@ -1847,23 +1836,31 @@ class LoggingReport : public StaticLocalDataSet { lp_var_t(sid.objectId, PoolIds::MPSOC_BOOT_FAILED_ATTEMPTS, this); lp_var_t mpsocPowerup = lp_var_t(sid.objectId, PoolIds::MPSOC_POWER_UP, this); lp_var_t mpsocUpdates = lp_var_t(sid.objectId, PoolIds::MPSOC_UPDATES, this); - lp_var_t lastRecvdTc = lp_var_t(sid.objectId, PoolIds::LAST_RECVD_TC, this); + lp_var_t mpsocHeartbeatResets = + lp_var_t(sid.objectId, PoolIds::MPSOC_HEARTBEAT_RESETS, this); + lp_var_t cpuWdtResets = + lp_var_t(sid.objectId, PoolIds::MPSOC_HEARTBEAT_RESETS, this); + lp_var_t psHeartbeatsLost = + lp_var_t(sid.objectId, PoolIds::PS_HEARTBEATS_LOST, this); + lp_var_t plHeartbeatsLost = + lp_var_t(sid.objectId, PoolIds::PL_HEARTBEATS_LOST, this); + lp_var_t ebTaskLost = lp_var_t(sid.objectId, PoolIds::EB_TASK_LOST, this); + lp_var_t bmTaskLost = lp_var_t(sid.objectId, PoolIds::BM_TASK_LOST, this); + lp_var_t lmTaskLost = lp_var_t(sid.objectId, PoolIds::LM_TASK_LOST, this); + lp_var_t amTaskLost = lp_var_t(sid.objectId, PoolIds::AM_TASK_LOST, this); + lp_var_t tctmmTaskLost = + lp_var_t(sid.objectId, PoolIds::TCTMM_TASK_LOST, this); + lp_var_t mmTaskLost = lp_var_t(sid.objectId, PoolIds::MM_TASK_LOST, this); + lp_var_t hkTaskLost = lp_var_t(sid.objectId, PoolIds::HK_TASK_LOST, this); + lp_var_t dlTaskLost = lp_var_t(sid.objectId, PoolIds::DL_TASK_LOST, this); + lp_vec_t rwsTasksLost = + lp_vec_t(sid.objectId, PoolIds::RWS_TASKS_LOST, this); void printSet() { - sif::info << "LoggingReport: Latchup happened count 0: " << this->latchupHappenCnt0 - << std::endl; - sif::info << "LoggingReport: Latchup happened count 1: " << this->latchupHappenCnt1 - << std::endl; - sif::info << "LoggingReport: Latchup happened count 2: " << this->latchupHappenCnt2 - << std::endl; - sif::info << "LoggingReport: Latchup happened count 3: " << this->latchupHappenCnt3 - << std::endl; - sif::info << "LoggingReport: Latchup happened count 4: " << this->latchupHappenCnt4 - << std::endl; - sif::info << "LoggingReport: Latchup happened count 5: " << this->latchupHappenCnt5 - << std::endl; - sif::info << "LoggingReport: Latchup happened count 6: " << this->latchupHappenCnt6 - << std::endl; + for (unsigned i = 0; i < 7; i++) { + sif::info << "LoggingReport: Latchup happened count " << i << ": " + << this->latchupHappenCnts[i] << std::endl; + } sif::info << "LoggingReport: ADC deviation triggers count: " << this->adcDeviationTriggersCnt << std::endl; sif::info << "LoggingReport: TC received count: " << this->tcReceivedCnt << std::endl; @@ -1874,88 +1871,29 @@ class LoggingReport : public StaticLocalDataSet { << std::endl; sif::info << "LoggingReport: MPSoC power up: " << this->mpsocPowerup << std::endl; sif::info << "LoggingReport: MPSoC updates: " << this->mpsocUpdates << std::endl; - sif::info << "LoggingReport: APID of last received TC: 0x" << std::hex << this->lastRecvdTc - << std::endl; } }; /** * @brief This dataset stores the ADC report. */ -class AdcReport : public StaticLocalDataSet { +class AdcReport : public StaticLocalDataSet<3> { public: AdcReport(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, ADC_REPORT_SET_ID) {} AdcReport(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, ADC_REPORT_SET_ID)) {} - lp_var_t adcRaw0 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_0, this); - lp_var_t adcRaw1 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_1, this); - lp_var_t adcRaw2 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_2, this); - lp_var_t adcRaw3 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_3, this); - lp_var_t adcRaw4 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_4, this); - lp_var_t adcRaw5 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_5, this); - lp_var_t adcRaw6 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_6, this); - lp_var_t adcRaw7 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_7, this); - lp_var_t adcRaw8 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_8, this); - lp_var_t adcRaw9 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_9, this); - lp_var_t adcRaw10 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_10, this); - lp_var_t adcRaw11 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_11, this); - lp_var_t adcRaw12 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_12, this); - lp_var_t adcRaw13 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_13, this); - lp_var_t adcRaw14 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_14, this); - lp_var_t adcRaw15 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_15, this); - lp_var_t adcEng0 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_0, this); - lp_var_t adcEng1 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_1, this); - lp_var_t adcEng2 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_2, this); - lp_var_t adcEng3 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_3, this); - lp_var_t adcEng4 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_4, this); - lp_var_t adcEng5 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_5, this); - lp_var_t adcEng6 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_6, this); - lp_var_t adcEng7 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_7, this); - lp_var_t adcEng8 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_8, this); - lp_var_t adcEng9 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_9, this); - lp_var_t adcEng10 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_10, this); - lp_var_t adcEng11 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_11, this); - lp_var_t adcEng12 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_12, this); - lp_var_t adcEng13 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_13, this); - lp_var_t adcEng14 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_14, this); - lp_var_t adcEng15 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_15, this); + lp_vec_t adcRaw = lp_vec_t(sid.objectId, PoolIds::ADC_RAW, this); + lp_vec_t adcEng = lp_vec_t(sid.objectId, PoolIds::ADC_ENG, this); void printSet() { sif::info << "---- Adc Report: Raw values ----" << std::endl; - sif::info << "AdcReport: ADC raw 0: " << std::dec << this->adcRaw0 << std::endl; - sif::info << "AdcReport: ADC raw 1: " << this->adcRaw1 << std::endl; - sif::info << "AdcReport: ADC raw 2: " << this->adcRaw2 << std::endl; - sif::info << "AdcReport: ADC raw 3: " << this->adcRaw3 << std::endl; - sif::info << "AdcReport: ADC raw 4: " << this->adcRaw4 << std::endl; - sif::info << "AdcReport: ADC raw 5: " << this->adcRaw5 << std::endl; - sif::info << "AdcReport: ADC raw 6: " << this->adcRaw6 << std::endl; - sif::info << "AdcReport: ADC raw 7: " << this->adcRaw7 << std::endl; - sif::info << "AdcReport: ADC raw 8: " << this->adcRaw8 << std::endl; - sif::info << "AdcReport: ADC raw 9: " << this->adcRaw9 << std::endl; - sif::info << "AdcReport: ADC raw 10: " << this->adcRaw10 << std::endl; - sif::info << "AdcReport: ADC raw 11: " << this->adcRaw11 << std::endl; - sif::info << "AdcReport: ADC raw 12: " << this->adcRaw12 << std::endl; - sif::info << "AdcReport: ADC raw 13: " << this->adcRaw13 << std::endl; - sif::info << "AdcReport: ADC raw 14: " << this->adcRaw14 << std::endl; - sif::info << "AdcReport: ADC raw 15: " << this->adcRaw15 << std::endl; - sif::info << "---- Adc Report: Engineering values ----" << std::endl; - sif::info << "AdcReport: ADC eng 0: " << this->adcEng0 << std::endl; - sif::info << "AdcReport: ADC eng 1: " << this->adcEng1 << std::endl; - sif::info << "AdcReport: ADC eng 2: " << this->adcEng2 << std::endl; - sif::info << "AdcReport: ADC eng 3: " << this->adcEng3 << std::endl; - sif::info << "AdcReport: ADC eng 4: " << this->adcEng4 << std::endl; - sif::info << "AdcReport: ADC eng 5: " << this->adcEng5 << std::endl; - sif::info << "AdcReport: ADC eng 6: " << this->adcEng6 << std::endl; - sif::info << "AdcReport: ADC eng 7: " << this->adcEng7 << std::endl; - sif::info << "AdcReport: ADC eng 8: " << this->adcEng8 << std::endl; - sif::info << "AdcReport: ADC eng 9: " << this->adcEng9 << std::endl; - sif::info << "AdcReport: ADC eng 10: " << this->adcEng10 << std::endl; - sif::info << "AdcReport: ADC eng 11: " << this->adcEng11 << std::endl; - sif::info << "AdcReport: ADC eng 12: " << this->adcEng12 << std::endl; - sif::info << "AdcReport: ADC eng 13: " << this->adcEng13 << std::endl; - sif::info << "AdcReport: ADC eng 14: " << this->adcEng14 << std::endl; - sif::info << "AdcReport: ADC eng 15: " << this->adcEng15 << std::endl; + for (unsigned i = 0; i < 16; i++) { + sif::info << "AdcReport: ADC raw " << i << ": " << std::dec << this->adcRaw[i] << std::endl; + } + for (unsigned i = 0; i < 16; i++) { + sif::info << "AdcReport: ADC eng " << i << ": " << std::dec << this->adcEng[i] << std::endl; + } } }; @@ -2045,11 +1983,7 @@ class EnableNvms : public TcBase { */ class EnableAutoTm : public TcBase { public: - EnableAutoTm(TcParams params) : TcBase(params) { - spParams.setFullPayloadLen(PAYLOAD_LENGTH + 2); - // spParams.creator.setApid(APID_AUTO_TM); - // spParams.creator.setSeqCount(DEFAULT_SEQUENCE_COUNT); - } + EnableAutoTm(TcParams params) : TcBase(params) { spParams.setFullPayloadLen(PAYLOAD_LENGTH + 2); } ReturnValue_t buildPacket() { auto res = checkSizeAndSerializeHeader(); diff --git a/mission/payload/plocSpBase.h b/mission/payload/plocSpBase.h index e754c7e8..96de0526 100644 --- a/mission/payload/plocSpBase.h +++ b/mission/payload/plocSpBase.h @@ -104,10 +104,6 @@ class SpTmReader : public SpacePacketReader { */ SpTmReader(const uint8_t* buf, size_t maxSize) : SpacePacketReader(buf, maxSize) {} - ReturnValue_t setData(const uint8_t* buf, size_t maxSize) { - return setReadOnlyData(buf, maxSize); - } - ReturnValue_t checkCrc() const { if (CRC::crc16ccitt(getFullData(), getFullPacketLen()) != 0) { return returnvalue::FAILED; diff --git a/mission/pollingSeqTables.cpp b/mission/pollingSeqTables.cpp index e9adf83b..1b369292 100644 --- a/mission/pollingSeqTables.cpp +++ b/mission/pollingSeqTables.cpp @@ -9,6 +9,8 @@ #include "OBSWConfig.h" #include "eive/definitions.h" +#include "eive/objects.h" +#include "linux/payload/FreshSupvHandler.h" #ifndef RPI_TEST_ADIS16507 #define RPI_TEST_ADIS16507 0 @@ -608,3 +610,25 @@ ReturnValue_t pst::pstTcsAndAcs(FixedTimeslotTaskIF *thisSequence, AcsPstCfg cfg 0); return returnvalue::OK; } +ReturnValue_t pst::pstPayload(FixedTimeslotTaskIF *thisSequence) { + uint32_t length = thisSequence->getPeriodMs(); + + thisSequence->addSlot(objects::CAM_SWITCHER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, + DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::GET_READ); + + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0, + FreshSupvHandler::OpCode::DEFAULT_OPERATION); + // Two COM TM steps, which might cover telemetry which takes a bit longer to be sent. + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.1, + FreshSupvHandler::OpCode::PARSE_TM); + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.2, + FreshSupvHandler::OpCode::PARSE_TM); + static_cast(length); + + return thisSequence->checkSequence(); +} diff --git a/mission/pollingSeqTables.h b/mission/pollingSeqTables.h index 5df3c954..db75de88 100644 --- a/mission/pollingSeqTables.h +++ b/mission/pollingSeqTables.h @@ -63,6 +63,8 @@ ReturnValue_t pstTcsAndAcs(FixedTimeslotTaskIF* thisSequence, AcsPstCfg cfg); ReturnValue_t pstI2c(TmpSchedConfig schedConf, FixedTimeslotTaskIF* thisSequence); +ReturnValue_t pstPayload(FixedTimeslotTaskIF* thisSequence); + /** * Generic test PST * @param thisSequence diff --git a/tmtc b/tmtc index 0a417a89..a41dc9b6 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 0a417a89e9e7f0447d35c70950685df59bf5c062 +Subproject commit a41dc9b691ab51b8526b3a3982f35072f5d82632