From b623f01bea657343d343955f2ba4cee962f669f8 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 8 Nov 2023 10:46:59 +0100 Subject: [PATCH 01/69] PLOC SUPV extensions --- linux/payload/PlocSupervisorHandler.cpp | 168 ++++++++++-------- linux/payload/PlocSupervisorHandler.h | 12 +- linux/payload/plocSupvDefs.h | 222 ++++++++---------------- 3 files changed, 172 insertions(+), 230 deletions(-) diff --git a/linux/payload/PlocSupervisorHandler.cpp b/linux/payload/PlocSupervisorHandler.cpp index 3863caea..271363ac 100644 --- a/linux/payload/PlocSupervisorHandler.cpp +++ b/linux/payload/PlocSupervisorHandler.cpp @@ -29,7 +29,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) { @@ -274,8 +274,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 +282,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,6 +319,17 @@ 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; @@ -358,6 +367,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 +379,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 +421,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; } @@ -559,6 +570,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 +585,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()); @@ -627,12 +655,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 +735,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 +745,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)); @@ -1105,37 +1119,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 +1165,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 +1415,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 +1432,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); @@ -1517,8 +1533,8 @@ void PlocSupervisorHandler::disableAllReplies() { disableReply(LATCHUP_REPORT); break; } - case LOGGING_REQUEST_COUNTERS: { - disableReply(LOGGING_REPORT); + case REQUEST_LOGGING_COUNTERS: { + disableReply(COUNTERS_REPORT); break; } default: { diff --git a/linux/payload/PlocSupervisorHandler.h b/linux/payload/PlocSupervisorHandler.h index 4514e69f..7358b256 100644 --- a/linux/payload/PlocSupervisorHandler.h +++ b/linux/payload/PlocSupervisorHandler.h @@ -135,7 +135,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase { 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; @@ -167,6 +167,9 @@ class PlocSupervisorHandler : public DeviceHandlerBase { Countdown bootTimeout = Countdown(BOOT_TIMEOUT); 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 +234,11 @@ 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); /** * @brief Depending on the current active command, this function sets the reply id of the @@ -301,8 +307,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/linux/payload/plocSupvDefs.h b/linux/payload/plocSupvDefs.h index 115cfe60..bbb16d3d 100644 --- a/linux/payload/plocSupvDefs.h +++ b/linux/payload/plocSupvDefs.h @@ -107,7 +107,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 +120,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 +134,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 +144,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 +207,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 +237,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 @@ -327,7 +335,7 @@ 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 { @@ -417,13 +425,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 +435,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 { @@ -1814,26 +1799,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 +1822,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 +1857,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 +1969,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(); From d8e0f9ffcec0729ba5148a3b1772ba3011ed74c7 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 8 Nov 2023 18:19:24 +0100 Subject: [PATCH 02/69] stupid --- linux/payload/PlocSupervisorHandler.cpp | 39 ++++++++++++++++++++++++- linux/payload/PlocSupervisorHandler.h | 14 +++++++-- linux/payload/plocSupvDefs.h | 2 +- tmtc | 2 +- 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/linux/payload/PlocSupervisorHandler.cpp b/linux/payload/PlocSupervisorHandler.cpp index 271363ac..22501951 100644 --- a/linux/payload/PlocSupervisorHandler.cpp +++ b/linux/payload/PlocSupervisorHandler.cpp @@ -61,6 +61,15 @@ 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; + disableAllReplies(); + } EventMessage event; for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK; result = eventQueue->receiveMessage(&event)) { @@ -177,8 +186,10 @@ void PlocSupervisorHandler::doShutDown() { } 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; @@ -336,6 +347,7 @@ ReturnValue_t PlocSupervisorHandler::buildCommandFromCommand(DeviceCommandId_t d result = DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; break; } + commandIsPending = true; return result; } @@ -552,6 +564,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; @@ -606,6 +621,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"; @@ -620,7 +643,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"; @@ -1868,6 +1899,7 @@ ReturnValue_t PlocSupervisorHandler::eventSubscription() { ReturnValue_t PlocSupervisorHandler::handleExecutionSuccessReport(ExecutionReport& report) { DeviceCommandId_t commandId = getPendingCommand(); ReturnValue_t result = OK; + commandIsPending = false; switch (commandId) { case supv::READ_GPIO: { // TODO: Fix @@ -1958,6 +1990,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/linux/payload/PlocSupervisorHandler.h index 7358b256..8de767a5 100644 --- a/linux/payload/PlocSupervisorHandler.h +++ b/linux/payload/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 @@ -94,7 +95,7 @@ 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 @@ -131,6 +132,13 @@ 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; @@ -240,6 +248,8 @@ class PlocSupervisorHandler : public DeviceHandlerBase { 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 * next reply after a successful acknowledgment report has been received. This is diff --git a/linux/payload/plocSupvDefs.h b/linux/payload/plocSupvDefs.h index bbb16d3d..7bd1b1a1 100644 --- a/linux/payload/plocSupvDefs.h +++ b/linux/payload/plocSupvDefs.h @@ -329,7 +329,7 @@ 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; diff --git a/tmtc b/tmtc index 99c6c8bb..c4bd3551 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 99c6c8bbd0d791d8b17720de481c6142091a54a4 +Subproject commit c4bd355146a2f5894a93a30f0c7f61aeef43e764 From 6ae9e12cf935c56c844f11cae4b2c5c5073701e2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 8 Nov 2023 18:43:11 +0100 Subject: [PATCH 03/69] what is going on with that thing? --- linux/payload/PlocSupervisorHandler.cpp | 34 ++++++++++++++++--------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/linux/payload/PlocSupervisorHandler.cpp b/linux/payload/PlocSupervisorHandler.cpp index 22501951..787e114c 100644 --- a/linux/payload/PlocSupervisorHandler.cpp +++ b/linux/payload/PlocSupervisorHandler.cpp @@ -61,13 +61,17 @@ ReturnValue_t PlocSupervisorHandler::initialize() { } void PlocSupervisorHandler::performOperationHook() { - if(normalCommandIsPending and normalCmdCd.hasTimedOut()) { + if (normalCommandIsPending and normalCmdCd.hasTimedOut()) { // Event, FDIR, printout? Leads to spam though and normally should not happen.. normalCommandIsPending = false; } - if(commandIsPending and cmdCd.hasTimedOut()) { + 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; @@ -181,6 +185,7 @@ void PlocSupervisorHandler::doShutDown() { nextReplyId = supv::NONE; uartManager.stop(); uartIsolatorSwitch.pullLow(); + disableAllReplies(); supv::SUPV_ON = false; startupState = StartupState::OFF; } @@ -348,6 +353,7 @@ ReturnValue_t PlocSupervisorHandler::buildCommandFromCommand(DeviceCommandId_t d break; } commandIsPending = true; + cmdCd.resetTimer(); return result; } @@ -625,8 +631,8 @@ void PlocSupervisorHandler::handlePacketPrint() { 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) { + 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 = "???"; @@ -648,8 +654,8 @@ void PlocSupervisorHandler::handlePacketPrint() { 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) { + 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)) { @@ -916,6 +922,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; } @@ -1898,7 +1905,11 @@ 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->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: { @@ -1907,14 +1918,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) { 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; } @@ -1991,8 +2001,8 @@ uint32_t PlocSupervisorHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t mod } void PlocSupervisorHandler::disableCommand(DeviceCommandId_t cmd) { - auto commandIter = deviceCommandMap.find(GET_HK_REPORT); - commandIter->second.isExecuting = false; + auto commandIter = deviceCommandMap.find(GET_HK_REPORT); + commandIter->second.isExecuting = false; } ReturnValue_t PlocSupervisorHandler::checkModeCommand(Mode_t commandedMode, From 5be3af351512dcce5a2ccda6fd6dcf13b4feec0e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 8 Nov 2023 18:49:57 +0100 Subject: [PATCH 04/69] robustness changes --- linux/payload/PlocSupervisorHandler.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/linux/payload/PlocSupervisorHandler.cpp b/linux/payload/PlocSupervisorHandler.cpp index 787e114c..aa8c7e4f 100644 --- a/linux/payload/PlocSupervisorHandler.cpp +++ b/linux/payload/PlocSupervisorHandler.cpp @@ -1586,6 +1586,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; @@ -1616,6 +1619,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(); @@ -1638,7 +1644,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; @@ -1906,10 +1914,10 @@ ReturnValue_t PlocSupervisorHandler::eventSubscription() { ReturnValue_t PlocSupervisorHandler::handleExecutionSuccessReport(ExecutionReport& report) { DeviceCommandId_t commandId = getPendingCommand(); DeviceCommandMap::iterator iter = deviceCommandMap.find(commandId); - if (iter->second.sendReplyTo != NO_COMMANDER) { + if (iter != deviceCommandMap.end() and iter->second.sendReplyTo != NO_COMMANDER) { actionHelper.finish(true, iter->second.sendReplyTo, iter->first, returnvalue::OK); + iter->second.isExecuting = false; } - iter->second.isExecuting = false; commandIsPending = false; switch (commandId) { case supv::READ_GPIO: { @@ -1918,7 +1926,7 @@ 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 */ - 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)]; From 2d686b3a26bd98a8891cc75c1ce84c96b5219abe Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 9 Nov 2023 11:11:47 +0100 Subject: [PATCH 05/69] come on indexer, do sth --- fsfw | 2 +- linux/payload/FreshSupvHandler.cpp | 10 ++++++++++ linux/payload/FreshSupvHandler.h | 11 +++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 linux/payload/FreshSupvHandler.cpp create mode 100644 linux/payload/FreshSupvHandler.h diff --git a/fsfw b/fsfw index cc3e64e7..18cc870c 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit cc3e64e70d90f6a2b5c59215b2569c1771e890f0 +Subproject commit 18cc870c8ebc3ff0565b3b8f5ed85e9a54685358 diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp new file mode 100644 index 00000000..b72e01f8 --- /dev/null +++ b/linux/payload/FreshSupvHandler.cpp @@ -0,0 +1,10 @@ +/* + * FreshSupvHandler.cpp + * + * Created on: Nov 9, 2023 + * Author: rmueller + */ + + + + diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h new file mode 100644 index 00000000..ce97810e --- /dev/null +++ b/linux/payload/FreshSupvHandler.h @@ -0,0 +1,11 @@ +#ifndef LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ +#define LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ + +#include "fsfw/devicehandlers/FreshDeviceHandlerBase.h" +class FreshSupvHandler: public FreshDeviceHandlerBase { + FreshSupvHandler(DhbConfig cfg); +}; + + + +#endif /* LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ */ From 92071b8e0e0bde900d50f1d5151337c4eba85818 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 9 Nov 2023 11:35:28 +0100 Subject: [PATCH 06/69] first structure --- fsfw | 2 +- linux/payload/CMakeLists.txt | 1 + linux/payload/FreshSupvHandler.cpp | 57 ++++++++++++++++++++++++++---- linux/payload/FreshSupvHandler.h | 36 +++++++++++++++++-- 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/fsfw b/fsfw index 18cc870c..35be7da3 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 18cc870c8ebc3ff0565b3b8f5ed85e9a54685358 +Subproject commit 35be7da3534423af2b4db2b86e75371749181213 diff --git a/linux/payload/CMakeLists.txt b/linux/payload/CMakeLists.txt index e697fac6..09062532 100644 --- a/linux/payload/CMakeLists.txt +++ b/linux/payload/CMakeLists.txt @@ -2,6 +2,7 @@ target_sources( ${OBSW_NAME} PUBLIC PlocMemoryDumper.cpp PlocMpsocHandler.cpp + FreshSupvHandler.cpp PlocMpsocSpecialComHelper.cpp plocMpsocHelpers.cpp PlocSupervisorHandler.cpp diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index b72e01f8..12120946 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -1,10 +1,55 @@ -/* - * FreshSupvHandler.cpp - * - * Created on: Nov 9, 2023 - * Author: rmueller - */ +#include "FreshSupvHandler.h" +FreshSupvHandler::FreshSupvHandler(DhbConfig cfg) : FreshDeviceHandlerBase(cfg) {} +void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { + if (!transitionActive and mode == MODE_OFF) { + // Nothing to do for now. + return; + } + if (opCode == OpCode::DEFAULT_OPERATION) { + if (transitionActive) { + // TODO: Perform transition handling: OFF to ON and ON to OFF. + } else { + if (mode == MODE_NORMAL) { + // Normal mode handling. Request normal datasets and add them to command map. + } + } + // TODO: Check whether any active commands have timeouted. + } else if (opCode == OpCode::HANDLE_ACTIVE_CMDS) { + // TODO: Parse TM from ring buffer and check whether they complete any active commands. + // If they do, check whether anyone needs to be informed. + } +} +ReturnValue_t FreshSupvHandler::handleCommandMessage(CommandMessage *message) { + // No custom messages. + return returnvalue::FAILED; +} + +LocalPoolDataSetBase *FreshSupvHandler::getDataSetHandle(sid_t sid) { + // TODO: return all relevant datasets. + return nullptr; +} + +ReturnValue_t FreshSupvHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, + LocalDataPoolManager &poolManager) { + // TODO: Copy code from god handler here. + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t *data, size_t size) { + // TODO: Handle all commands here. Need to add them to some command map. Send command immediately + // then. + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::checkModeCommand(Mode_t mode_, Submode_t submode_, + uint32_t *msToReachTheMode) { + if (mode_ != HasModesIF::MODE_OFF and mode_ != HasModesIF::MODE_ON and mode_ != MODE_NORMAL) { + return returnvalue::FAILED; + } + return returnvalue::OK; +} diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index ce97810e..4f308361 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -2,10 +2,40 @@ #define LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ #include "fsfw/devicehandlers/FreshDeviceHandlerBase.h" -class FreshSupvHandler: public FreshDeviceHandlerBase { + +class FreshSupvHandler : public FreshDeviceHandlerBase { + public: + enum OpCode { DEFAULT_OPERATION = 0, HANDLE_ACTIVE_CMDS = 1 }; + FreshSupvHandler(DhbConfig cfg); + /** + * 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; + + 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; + + private: + bool transitionActive = false; }; - - #endif /* LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ */ From bdf6baa9fc1c27f78fa0d1af5a47d4b0b11f4f91 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 9 Nov 2023 11:44:00 +0100 Subject: [PATCH 07/69] start adding data pool stuff --- linux/payload/FreshSupvHandler.cpp | 80 ++++++++++++++++++++++++- linux/payload/FreshSupvHandler.h | 15 +++++ linux/payload/PlocSupervisorHandler.cpp | 2 - 3 files changed, 94 insertions(+), 3 deletions(-) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 12120946..995f3441 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -1,6 +1,13 @@ #include "FreshSupvHandler.h" -FreshSupvHandler::FreshSupvHandler(DhbConfig cfg) : FreshDeviceHandlerBase(cfg) {} +#include + +using namespace supv; +using namespace returnvalue; + +std::atomic_bool supv::SUPV_ON = false; + +FreshSupvHandler::FreshSupvHandler(DhbConfig cfg) : FreshDeviceHandlerBase(cfg), hkSet(this) {} void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { if (!transitionActive and mode == MODE_OFF) { @@ -36,6 +43,77 @@ LocalPoolDataSetBase *FreshSupvHandler::getDataSetHandle(sid_t sid) { 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_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; } diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index 4f308361..044a0418 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -2,6 +2,7 @@ #define LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ #include "fsfw/devicehandlers/FreshDeviceHandlerBase.h" +#include "plocSupvDefs.h" class FreshSupvHandler : public FreshDeviceHandlerBase { public: @@ -35,7 +36,21 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { const uint8_t* data, size_t size) override; private: + supv::HkSet hkSet; + supv::BootStatusReport bootStatusReport; + supv::LatchupStatusReport latchupStatusReport; + supv::CountersReport countersReport; + supv::AdcReport adcReport; + bool transitionActive = false; + + 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); }; #endif /* LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ */ diff --git a/linux/payload/PlocSupervisorHandler.cpp b/linux/payload/PlocSupervisorHandler.cpp index aa8c7e4f..321dd991 100644 --- a/linux/payload/PlocSupervisorHandler.cpp +++ b/linux/payload/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) From 42cc9c0fa837f53870911904b29c5504aa505e7a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 9 Nov 2023 11:57:49 +0100 Subject: [PATCH 08/69] add required fields --- linux/payload/FreshSupvHandler.cpp | 20 ++++++++++++++++++-- linux/payload/FreshSupvHandler.h | 13 ++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 995f3441..31f42924 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -7,7 +7,16 @@ using namespace returnvalue; std::atomic_bool supv::SUPV_ON = false; -FreshSupvHandler::FreshSupvHandler(DhbConfig cfg) : FreshDeviceHandlerBase(cfg), hkSet(this) {} +FreshSupvHandler::FreshSupvHandler(DhbConfig cfg, CookieIF *comCookie, Gpio uartIsolatorSwitch, + PowerSwitchIF &switchIF, power::Switch_t powerSwitch, + PlocSupvUartManager &supvHelper) + : FreshDeviceHandlerBase(cfg), + hkSet(this), + bootStatusReport(this), + latchupStatusReport(this), + countersReport(this), + adcReport(this), + uartManager(supvHelper) {} void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { if (!transitionActive and mode == MODE_OFF) { @@ -17,7 +26,9 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { if (opCode == OpCode::DEFAULT_OPERATION) { if (transitionActive) { // TODO: Perform transition handling: OFF to ON and ON to OFF. - + // For OFF to ON, command power switch first, then to isolato switch handling, and lastly + // ensure succesfull communication + // For ON to OFF ???? } else { if (mode == MODE_NORMAL) { // Normal mode handling. Request normal datasets and add them to command map. @@ -117,6 +128,11 @@ ReturnValue_t FreshSupvHandler::initializeLocalDataPool(localpool::DataPool &loc return returnvalue::OK; } +ReturnValue_t FreshSupvHandler::setHealth(HealthState health) { + // TODO: Go to off is the device is commanded faulty. + return returnvalue::OK; +} + ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t *data, size_t size) { // TODO: Handle all commands here. Need to add them to some command map. Send command immediately diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index 044a0418..fdb38514 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -1,14 +1,21 @@ #ifndef LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ #define LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ +#include + +#include "PlocSupvUartMan.h" #include "fsfw/devicehandlers/FreshDeviceHandlerBase.h" +#include "fsfw/power/definitions.h" +#include "fsfw_hal/linux/gpio/Gpio.h" #include "plocSupvDefs.h" class FreshSupvHandler : public FreshDeviceHandlerBase { public: enum OpCode { DEFAULT_OPERATION = 0, HANDLE_ACTIVE_CMDS = 1 }; - FreshSupvHandler(DhbConfig cfg); + FreshSupvHandler(DhbConfig cfg, CookieIF* comCookie, Gpio uartIsolatorSwitch, + PowerSwitchIF& switchIF, power::Switch_t powerSwitch, + PlocSupvUartManager& supvHelper); /** * Periodic helper executed function, implemented by child class. */ @@ -23,6 +30,8 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { ReturnValue_t handleCommandMessage(CommandMessage* message) override; private: + ReturnValue_t setHealth(HealthState health) override; + // HK manager abstract functions. LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, @@ -36,6 +45,8 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { const uint8_t* data, size_t size) override; private: + PlocSupvUartManager uartManager; + supv::HkSet hkSet; supv::BootStatusReport bootStatusReport; supv::LatchupStatusReport latchupStatusReport; From 876bde16e21541af0e755b4ed9e506dcfd9166b2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 9 Nov 2023 17:19:28 +0100 Subject: [PATCH 09/69] looking good --- fsfw | 2 +- linux/payload/FreshSupvHandler.cpp | 635 ++++++++++++++++++++++-- linux/payload/FreshSupvHandler.h | 92 +++- linux/payload/PlocSupervisorHandler.cpp | 1 + linux/payload/PlocSupervisorHandler.h | 5 +- linux/payload/PlocSupvUartMan.h | 53 +- linux/payload/plocSupvDefs.h | 7 +- 7 files changed, 731 insertions(+), 64 deletions(-) diff --git a/fsfw b/fsfw index 35be7da3..bf7fac07 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 35be7da3534423af2b4db2b86e75371749181213 +Subproject commit bf7fac071c6d181251dbf9dee908728455be0925 diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 31f42924..ad743705 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -1,5 +1,7 @@ #include "FreshSupvHandler.h" +#include + #include using namespace supv; @@ -7,52 +9,93 @@ using namespace returnvalue; std::atomic_bool supv::SUPV_ON = false; -FreshSupvHandler::FreshSupvHandler(DhbConfig cfg, CookieIF *comCookie, Gpio uartIsolatorSwitch, - PowerSwitchIF &switchIF, power::Switch_t powerSwitch, - PlocSupvUartManager &supvHelper) +FreshSupvHandler::FreshSupvHandler(DhbConfig cfg, CookieIF* comCookie, Gpio uartIsolatorSwitch, + PowerSwitchIF& switchIF, power::Switch_t powerSwitch, + PlocSupvUartManager& supvHelper) : FreshDeviceHandlerBase(cfg), + uartManager(supvHelper), + comCookie(comCookie), + switchIF(switchIF), + switchId(powerSwitch), + uartIsolatorSwitch(uartIsolatorSwitch), hkSet(this), bootStatusReport(this), latchupStatusReport(this), countersReport(this), - adcReport(this), - uartManager(supvHelper) {} + adcReport(this) {} void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { - if (!transitionActive and mode == MODE_OFF) { + if (not transitionActive and mode == MODE_OFF) { // Nothing to do for now. return; } if (opCode == OpCode::DEFAULT_OPERATION) { if (transitionActive) { - // TODO: Perform transition handling: OFF to ON and ON to OFF. - // For OFF to ON, command power switch first, then to isolato switch handling, and lastly - // ensure succesfull communication - // For ON to OFF ???? + 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 { if (mode == MODE_NORMAL) { - // Normal mode handling. Request normal datasets and add them to command map. + if (hkRequestCmdInfo.isPending and hkRequestCmdInfo.cmdCountdown.hasTimedOut()) { + // trigger event? might lead to spam... + sif::warning << "FreshSupvHandler: No reply received for HK set request" << std::endl; + hkRequestCmdInfo.isPending = false; + } + // Normal mode handling. Request normal data sets and add them to command map. + if (not hkRequestCmdInfo.isPending) { + hkRequestCmdInfo.cmdCountdown.resetTimer(); + hkRequestCmdInfo.ackExeRecv = false; + hkRequestCmdInfo.ackRecv = false; + sendEmptyCmd(Apid::HK, static_cast(tc::HkId::GET_REPORT)); + } } } - // TODO: Check whether any active commands have timeouted. } else if (opCode == OpCode::HANDLE_ACTIVE_CMDS) { - // TODO: Parse TM from ring buffer and check whether they complete any active commands. - // If they do, check whether anyone needs to be informed. + std::vector cmdsToRemove; + for (auto& activeCmd : activeActionCmds) { + if (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::handleCommandMessage(CommandMessage *message) { +ReturnValue_t FreshSupvHandler::handleCommandMessage(CommandMessage* message) { // No custom messages. return returnvalue::FAILED; } -LocalPoolDataSetBase *FreshSupvHandler::getDataSetHandle(sid_t sid) { - // TODO: return all relevant datasets. +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) { +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})); @@ -71,7 +114,7 @@ ReturnValue_t FreshSupvHandler::initializeLocalDataPool(localpool::DataPool &loc 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_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})); @@ -128,22 +171,556 @@ ReturnValue_t FreshSupvHandler::initializeLocalDataPool(localpool::DataPool &loc return returnvalue::OK; } -ReturnValue_t FreshSupvHandler::setHealth(HealthState health) { - // TODO: Go to off is the device is commanded faulty. - return returnvalue::OK; -} - ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, - const uint8_t *data, size_t size) { + const uint8_t* data, size_t size) { // TODO: Handle all commands here. Need to add them to some command map. Send command immediately // then. + + using namespace supv; + ReturnValue_t result; + if (isCommandAlreadyActive(actionId)) { + return HasActionsIF::IS_BUSY; + } + spParams.buf = commandBuffer.data(); + switch (actionId) { + case GET_HK_REPORT: { + sendEmptyCmd(Apid::HK, static_cast(tc::HkId::GET_REPORT)); + result = returnvalue::OK; + break; + } + case START_MPSOC: { + sif::info << "PLOC SUPV: Starting MPSoC" << std::endl; + sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::START_MPSOC)); + result = returnvalue::OK; + break; + } + case SHUTDOWN_MPSOC: { + sif::info << "PLOC SUPV: Shutting down MPSoC" << std::endl; + sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::SHUTDOWN_MPSOC)); + 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(Apid::BOOT_MAN, static_cast(tc::BootManId::RESET_MPSOC)); + 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(Apid::BOOT_MAN, static_cast(tc::BootManId::GET_BOOT_STATUS_REPORT)); + 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(Apid::LATCHUP_MON, static_cast(tc::LatchupMonId::GET_STATUS_REPORT)); + 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(Apid::BOOT_MAN, static_cast(tc::BootManId::FACTORY_FLASH)); + result = returnvalue::OK; + break; + } + case RESET_PL: { + sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::RESET_PL)); + 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(Apid::ADC_MON, static_cast(tc::AdcMonId::REQUEST_ADC_SAMPLE)); + result = returnvalue::OK; + break; + } + case REQUEST_LOGGING_COUNTERS: { + sendEmptyCmd(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; + } + 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(packet); return returnvalue::OK; } -ReturnValue_t FreshSupvHandler::checkModeCommand(Mode_t mode_, Submode_t submode_, - uint32_t *msToReachTheMode) { - if (mode_ != HasModesIF::MODE_OFF and mode_ != HasModesIF::MODE_ON and mode_ != MODE_NORMAL) { +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(packet); + return returnvalue::OK; +} + +void FreshSupvHandler::startTransition(Mode_t newMode, Submode_t newSubmode) { + if (newMode == mode) { + // 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) { + bootTimeout.resetTimer(); + startupState = StartupState::POWER_SWITCHING; + switchIF.sendSwitchCommand(switchId, PowerSwitchIF::SWITCH_ON); + } 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; + } + } + if (startupState == StartupState::BOOTING) { + if (bootTimeout.hasTimedOut()) { + uartIsolatorSwitch.pullHigh(); + uartManager.start(); + if (SET_TIME_DURING_BOOT) { + // TODO: Send command ,add command to command map. + startupState = StartupState::SET_TIME; + } else { + startupState = StartupState::ON; + } + } + } + if (startupState == StartupState::TIME_WAS_SET) { + startupState = StartupState::ON; + } + if (startupState == StartupState::ON) { + hkSet.setReportingEnabled(true); + supv::SUPV_ON = true; + setMode(targetMode); + } +} + +void FreshSupvHandler::handleTransitionToOff() { + if (shutdownState == ShutdownState::IDLE) { + hkSet.setReportingEnabled(false); + hkSet.setValidity(false, true); + uartManager.stop(); + 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; + setMode(MODE_OFF); + } + } +} + +ReturnValue_t FreshSupvHandler::sendCommand(TcBase& tc) { + if (DEBUG_PLOC_SUPV) { + sif::debug << "PLOC SUPV: SEND PACKET Size " << tc.getFullPacketLen() << " Module APID " + << (int)tc.getModuleApid() << " Service ID " << (int)tc.getServiceId() << std::endl; + } + return uartManager.sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen()); +} + +ReturnValue_t FreshSupvHandler::initialize() { + uartManager.initializeInterface(comCookie); + return FreshDeviceHandlerBase::initialize(); +} + +ReturnValue_t FreshSupvHandler::sendEmptyCmd(uint16_t apid, uint8_t serviceId) { + supv::NoPayloadPacket packet(spParams, apid, serviceId); + ReturnValue_t result = packet.buildPacket(); + if (result != returnvalue::OK) { + return result; + } + sendCommand(packet); + 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(packet); + 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(packet); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::prepareDisableHk() { + supv::DisablePeriodicHkTransmission packet(spParams); + ReturnValue_t result = packet.buildPacket(); + if (result != returnvalue::OK) { + return result; + } + sendCommand(packet); + 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(packet); + break; + } + case (supv::DISABLE_LATCHUP_ALERT): { + supv::LatchupAlert packet(spParams); + result = packet.buildPacket(false, latchupId); + if (result != returnvalue::OK) { + return result; + } + sendCommand(packet); + 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(packet); + 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(packet); + 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(packet); + 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(packet); + 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(resetCmd); + 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(packet); + 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(packet); + 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(packet); + 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(packet); + return returnvalue::OK; +} + +ReturnValue_t FreshSupvHandler::parseTmPackets() { + uint8_t* receivedData = nullptr; + size_t receivedSize = 0; + ReturnValue_t result; + while (true) { + result = uartManager.readReceivedMessage(comCookie, &receivedData, &receivedSize); + if (receivedSize == 0) { + break; + } + // TODO: Implement TM packet parsing and call corresponding handler functions or verify + // sent commands. + } + return returnvalue::OK; +} + +bool FreshSupvHandler::isCommandAlreadyActive(ActionId_t actionId) const { + auto iter = activeActionCmds.find(actionId); + if (iter == activeActionCmds.end()) { + return false; + } + if (iter->second.isPending) { + return true; + } + return false; +} diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index fdb38514..e61b269f 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -2,6 +2,9 @@ #define LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ #include +#include + +#include #include "PlocSupvUartMan.h" #include "fsfw/devicehandlers/FreshDeviceHandlerBase.h" @@ -9,6 +12,10 @@ #include "fsfw_hal/linux/gpio/Gpio.h" #include "plocSupvDefs.h" +using supv::TcBase; + +static constexpr bool DEBUG_PLOC_SUPV = false; + class FreshSupvHandler : public FreshDeviceHandlerBase { public: enum OpCode { DEFAULT_OPERATION = 0, HANDLE_ACTIVE_CMDS = 1 }; @@ -29,9 +36,9 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { */ ReturnValue_t handleCommandMessage(CommandMessage* message) override; - private: - ReturnValue_t setHealth(HealthState health) override; + ReturnValue_t initialize() override; + private: // HK manager abstract functions. LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, @@ -44,8 +51,38 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { 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; + + void handleTransitionToOn(); + void handleTransitionToOff(); + private: + static constexpr bool SET_TIME_DURING_BOOT = true; + + enum class StartupState : uint8_t { + IDLE, + POWER_SWITCHING, + BOOTING, + SET_TIME, + WAIT_FOR_TIME_REPLY, + TIME_WAS_SET, + ON + }; + + StartupState startupState = StartupState::IDLE; + + 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; @@ -55,6 +92,12 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { bool transitionActive = false; + Mode_t targetMode = HasModesIF::MODE_INVALID; + Submode_t targetSubmode = 0; + + // Vorago nees some time to boot properly + Countdown bootTimeout = Countdown(supv::BOOT_TIMEOUT_MS); + PoolEntry adcRawEntry = PoolEntry(16); PoolEntry adcEngEntry = PoolEntry(16); PoolEntry latchupCounters = PoolEntry(7); @@ -62,6 +105,51 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { PoolEntry bootStateEntry = PoolEntry(1); PoolEntry bootCyclesEntry = PoolEntry(1); PoolEntry tempSupEntry = PoolEntry(1); + + pwrctrl::EnablePl enablePl = pwrctrl::EnablePl(objects::POWER_CONTROLLER); + + struct ActiveCmdInfo { + ActiveCmdInfo(uint32_t cmdCountdownMs) : cmdCountdown(cmdCountdownMs) {} + + bool isPending = false; + bool ackRecv = false; + bool ackExeRecv = false; + MessageQueueId_t commandedBy = MessageQueueIF::NO_QUEUE; + bool requiresActionReply = false; + Countdown cmdCountdown; + }; + + // Map for Action commands. For normal commands, a separate static structure will be used. + std::map activeActionCmds; + + ActiveCmdInfo hkRequestCmdInfo = ActiveCmdInfo(500); + + std::array commandBuffer; + SpacePacketCreator creator; + supv::TcParams spParams = supv::TcParams(creator); + + ReturnValue_t parseTmPackets(); + + ReturnValue_t sendCommand(TcBase& tc); + ReturnValue_t sendEmptyCmd(uint16_t apid, uint8_t serviceId); + 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); + + bool isCommandAlreadyActive(ActionId_t actionId) const; }; #endif /* LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ */ diff --git a/linux/payload/PlocSupervisorHandler.cpp b/linux/payload/PlocSupervisorHandler.cpp index 321dd991..67ec707f 100644 --- a/linux/payload/PlocSupervisorHandler.cpp +++ b/linux/payload/PlocSupervisorHandler.cpp @@ -1518,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); diff --git a/linux/payload/PlocSupervisorHandler.h b/linux/payload/PlocSupervisorHandler.h index 8de767a5..8df4b3fb 100644 --- a/linux/payload/PlocSupervisorHandler.h +++ b/linux/payload/PlocSupervisorHandler.h @@ -102,8 +102,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase { 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, @@ -172,7 +171,7 @@ 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); diff --git a/linux/payload/PlocSupvUartMan.h b/linux/payload/PlocSupvUartMan.h index 61d4b284..dc06b199 100644 --- a/linux/payload/PlocSupvUartMan.h +++ b/linux/payload/PlocSupvUartMan.h @@ -121,6 +121,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; @@ -319,32 +345,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 +369,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 7bd1b1a1..e991c519 100644 --- a/linux/payload/plocSupvDefs.h +++ b/linux/payload/plocSupvDefs.h @@ -18,6 +18,9 @@ namespace supv { extern std::atomic_bool SUPV_ON; +static constexpr uint32_t BOOT_TIMEOUT_MS = 4000; +static constexpr uint32_t MAX_TRANSITION_TIME_TO_ON_MS = 6000; +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; @@ -400,7 +403,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, @@ -1727,7 +1730,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); From 53a743f19fcb7fb8ab21c005b2471b858241c11b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 13 Nov 2023 11:39:13 +0100 Subject: [PATCH 10/69] continue ploc supv --- linux/payload/FreshSupvHandler.cpp | 14 ++++++-------- linux/payload/FreshSupvHandler.h | 5 +++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 31f42924..bed2ce90 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -11,12 +11,15 @@ FreshSupvHandler::FreshSupvHandler(DhbConfig cfg, CookieIF *comCookie, Gpio uart PowerSwitchIF &switchIF, power::Switch_t powerSwitch, PlocSupvUartManager &supvHelper) : FreshDeviceHandlerBase(cfg), + uartManager(supvHelper), + comCookie(comCookie), + switchIF(switchIF), + switchId(powerSwitch), hkSet(this), bootStatusReport(this), latchupStatusReport(this), countersReport(this), - adcReport(this), - uartManager(supvHelper) {} + adcReport(this) {} void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { if (!transitionActive and mode == MODE_OFF) { @@ -26,7 +29,7 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { if (opCode == OpCode::DEFAULT_OPERATION) { if (transitionActive) { // TODO: Perform transition handling: OFF to ON and ON to OFF. - // For OFF to ON, command power switch first, then to isolato switch handling, and lastly + // For OFF to ON, command power switch first, then to isolator switch handling, and lastly // ensure succesfull communication // For ON to OFF ???? } else { @@ -128,11 +131,6 @@ ReturnValue_t FreshSupvHandler::initializeLocalDataPool(localpool::DataPool &loc return returnvalue::OK; } -ReturnValue_t FreshSupvHandler::setHealth(HealthState health) { - // TODO: Go to off is the device is commanded faulty. - return returnvalue::OK; -} - ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t *data, size_t size) { // TODO: Handle all commands here. Need to add them to some command map. Send command immediately diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index fdb38514..655b8126 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -30,8 +30,6 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { ReturnValue_t handleCommandMessage(CommandMessage* message) override; private: - ReturnValue_t setHealth(HealthState health) override; - // HK manager abstract functions. LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, @@ -46,6 +44,9 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { private: PlocSupvUartManager uartManager; + CookieIF* comCookie; + PowerSwitchIF& switchIF; + power::Switch_t switchId; supv::HkSet hkSet; supv::BootStatusReport bootStatusReport; From 134073fd848e524268ea701c9c9c39ec6f1a3ad8 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 13 Nov 2023 15:33:11 +0100 Subject: [PATCH 11/69] continue PLOC SUPV --- .gitignore | 4 + cmake/scripts/q7s/q7s-make-debug.sh | 2 + cmake/scripts/q7s/q7s-make-release.sh | 2 + fsfw | 2 +- linux/payload/FreshSupvHandler.cpp | 206 +++++++++++++++++++++++++- linux/payload/FreshSupvHandler.h | 9 +- linux/payload/PlocSupervisorHandler.h | 20 --- linux/payload/plocSupvDefs.h | 20 +++ 8 files changed, 241 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index 5419ca42..eb6a49fa 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,7 @@ __pycache__ !/.idea/cmake.xml generators/*.db + +# Clangd LSP +/compile_commands.json +/.cache 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 bf7fac07..d554062b 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit bf7fac071c6d181251dbf9dee908728455be0925 +Subproject commit d554062b86999fd4d94ce9c3fe0341b73984d1ce diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index ad743705..8e3abd88 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -1,8 +1,15 @@ #include "FreshSupvHandler.h" #include +#include #include +#include + +#include "eive/definitions.h" +#include "fsfw/ipc/MessageQueueIF.h" +#include "fsfw/ipc/QueueFactory.h" +#include "fsfw/returnvalues/returnvalue.h" using namespace supv; using namespace returnvalue; @@ -22,7 +29,9 @@ FreshSupvHandler::FreshSupvHandler(DhbConfig cfg, CookieIF* comCookie, Gpio uart bootStatusReport(this), latchupStatusReport(this), countersReport(this), - adcReport(this) {} + adcReport(this) { + eventQueue = QueueFactory::instance()->createMessageQueue(EventMessage::EVENT_MESSAGE_SIZE * 5); +} void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { if (not transitionActive and mode == MODE_OFF) { @@ -30,6 +39,20 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { 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(); @@ -175,9 +198,47 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI const uint8_t* data, size_t size) { // TODO: Handle all commands here. Need to add them to some command map. Send command immediately // then. - using namespace supv; 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; + } if (isCommandAlreadyActive(actionId)) { return HasActionsIF::IS_BUSY; } @@ -454,6 +515,11 @@ ReturnValue_t FreshSupvHandler::sendCommand(TcBase& tc) { ReturnValue_t FreshSupvHandler::initialize() { uartManager.initializeInterface(comCookie); + + ReturnValue_t result = eventSubscription(); + if (result != returnvalue::OK) { + return result; + } return FreshDeviceHandlerBase::initialize(); } @@ -724,3 +790,139 @@ bool FreshSupvHandler::isCommandAlreadyActive(ActionId_t actionId) const { } 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) { + // Wait for a short period for the uart state machine to adjust + // TaskFactory::delayTask(5); + if (not isCommandAlreadyActive(supv::SHUTDOWN_MPSOC)) { + result = this->executeAction(supv::SHUTDOWN_MPSOC, MessageQueueIF::NO_QUEUE, nullptr, 0); + 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; +} diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index e61b269f..859dfa43 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -62,6 +62,7 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { private: static constexpr bool SET_TIME_DURING_BOOT = true; + static const uint8_t SIZE_NULL_TERMINATOR = 1; enum class StartupState : uint8_t { IDLE, @@ -74,6 +75,7 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { }; StartupState startupState = StartupState::IDLE; + MessageQueueIF* eventQueue = nullptr; enum class ShutdownState : uint8_t { IDLE, POWER_SWITCHING }; ShutdownState shutdownState = ShutdownState::IDLE; @@ -148,7 +150,12 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { 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); + ReturnValue_t eventSubscription(); bool isCommandAlreadyActive(ActionId_t actionId) const; }; diff --git a/linux/payload/PlocSupervisorHandler.h b/linux/payload/PlocSupervisorHandler.h index 8df4b3fb..85c3d94e 100644 --- a/linux/payload/PlocSupervisorHandler.h +++ b/linux/payload/PlocSupervisorHandler.h @@ -68,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; diff --git a/linux/payload/plocSupvDefs.h b/linux/payload/plocSupvDefs.h index e991c519..fc9b9abe 100644 --- a/linux/payload/plocSupvDefs.h +++ b/linux/payload/plocSupvDefs.h @@ -17,6 +17,26 @@ namespace supv { +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); + extern std::atomic_bool SUPV_ON; static constexpr uint32_t BOOT_TIMEOUT_MS = 4000; static constexpr uint32_t MAX_TRANSITION_TIME_TO_ON_MS = 6000; From 87149487885dd462cc9043e9ac215313814ed49e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 13 Nov 2023 15:43:32 +0100 Subject: [PATCH 12/69] this is what device handler writing should have been --- linux/payload/FreshSupvHandler.cpp | 131 ++++++++++++++++++++++++++++- linux/payload/FreshSupvHandler.h | 7 +- 2 files changed, 135 insertions(+), 3 deletions(-) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 8e3abd88..0074e0fe 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -774,12 +774,139 @@ ReturnValue_t FreshSupvHandler::parseTmPackets() { if (receivedSize == 0) { break; } - // TODO: Implement TM packet parsing and call corresponding handler functions or verify - // sent commands. + tmReader.setData(receivedData, receivedSize); + uint16_t apid = tmReader.getModuleApid(); + if (DEBUG_PLOC_SUPV) { + handlePacketPrint(); + } + switch (apid) { + case (Apid::TMTC_MAN): { + switch (tmReader.getServiceId()) { + case (static_cast(supv::tm::TmtcId::ACK)): + case (static_cast(supv::tm::TmtcId::NAK)): { + // TODO: Handle ACK report. + return OK; + } + case (static_cast(supv::tm::TmtcId::EXEC_ACK)): + case (static_cast(supv::tm::TmtcId::EXEC_NAK)): { + // TODO: Hnadle Exe report. + return OK; + } + } + break; + } + case (Apid::HK): { + if (tmReader.getServiceId() == static_cast(supv::tm::HkId::REPORT)) { + // TODO: Handle HK report. + return OK; + } 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)) { + // TODO: Handle boot status report. + continue; + } + break; + } + case (Apid::ADC_MON): { + if (tmReader.getServiceId() == static_cast(supv::tm::AdcMonId::ADC_REPORT)) { + // TODO: Handle ADC report. + continue; + } + break; + } + case (Apid::MEM_MAN): { + if (tmReader.getServiceId() == + static_cast(supv::tm::MemManId::UPDATE_STATUS_REPORT)) { + // TODO: Handle update status report. + continue; + } + break; + } + case (Apid::DATA_LOGGER): { + if (tmReader.getServiceId() == + static_cast(supv::tm::DataLoggerId::COUNTERS_REPORT)) { + // TODO: Handle counters report. + 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(); + 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"; + + } 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(); + 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"; + + } 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; + } + } + 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 { auto iter = activeActionCmds.find(actionId); if (iter == activeActionCmds.end()) { diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index 859dfa43..91b2778d 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -14,7 +14,8 @@ 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; class FreshSupvHandler : public FreshDeviceHandlerBase { public: @@ -76,6 +77,7 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { StartupState startupState = StartupState::IDLE; MessageQueueIF* eventQueue = nullptr; + supv::TmBase tmReader; enum class ShutdownState : uint8_t { IDLE, POWER_SWITCHING }; ShutdownState shutdownState = ShutdownState::IDLE; @@ -155,7 +157,10 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { 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; }; From e41e2e62e0b22e22454e28da39c9a6da496c0a2a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 13 Nov 2023 16:32:40 +0100 Subject: [PATCH 13/69] rewrite almost done --- linux/payload/FreshSupvHandler.cpp | 180 ++++++++++++++++++++++++++--- linux/payload/FreshSupvHandler.h | 12 +- linux/payload/plocSupvDefs.h | 6 + 3 files changed, 182 insertions(+), 16 deletions(-) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 0074e0fe..06b2eac9 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -505,11 +505,27 @@ void FreshSupvHandler::handleTransitionToOff() { } } -ReturnValue_t FreshSupvHandler::sendCommand(TcBase& tc) { +ReturnValue_t FreshSupvHandler::sendCommand(TcBase& tc, uint32_t cmdCountdownMs) { if (DEBUG_PLOC_SUPV) { sif::debug << "PLOC SUPV: SEND PACKET Size " << tc.getFullPacketLen() << " Module APID " << (int)tc.getModuleApid() << " Service ID " << (int)tc.getServiceId() << std::endl; } + ActiveCmdInfo info(cmdCountdownMs); + auto activeCmdIter = + activeActionCmds.find(buildActiveCmdKey(tc.getModuleApid(), tc.getServiceId())); + if (activeCmdIter == activeActionCmds.end()) { + activeActionCmds.emplace(buildActiveCmdKey(tc.getModuleApid(), tc.getServiceId()), info); + + } else { + if (activeCmdIter->second.isPending) { + return HasActionsIF::IS_BUSY; + } + activeCmdIter->second.isPending = true; + activeCmdIter->second.ackRecv = false; + activeCmdIter->second.ackExeRecv = false; + activeCmdIter->second.cmdCountdown.setTimeout(cmdCountdownMs); + activeCmdIter->second.cmdCountdown.resetTimer(); + } return uartManager.sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen()); } @@ -768,10 +784,9 @@ ReturnValue_t FreshSupvHandler::prepareWipeMramCmd(const uint8_t* commandData, s ReturnValue_t FreshSupvHandler::parseTmPackets() { uint8_t* receivedData = nullptr; size_t receivedSize = 0; - ReturnValue_t result; while (true) { - result = uartManager.readReceivedMessage(comCookie, &receivedData, &receivedSize); - if (receivedSize == 0) { + ReturnValue_t result = uartManager.readReceivedMessage(comCookie, &receivedData, &receivedSize); + if (result != returnvalue::OK or receivedSize == 0) { break; } tmReader.setData(receivedData, receivedSize); @@ -784,13 +799,13 @@ ReturnValue_t FreshSupvHandler::parseTmPackets() { switch (tmReader.getServiceId()) { case (static_cast(supv::tm::TmtcId::ACK)): case (static_cast(supv::tm::TmtcId::NAK)): { - // TODO: Handle ACK report. - return OK; + handleAckReport(receivedData); + continue; } case (static_cast(supv::tm::TmtcId::EXEC_ACK)): case (static_cast(supv::tm::TmtcId::EXEC_NAK)): { - // TODO: Hnadle Exe report. - return OK; + handleExecutionReport(receivedData); + continue; } } break; @@ -908,12 +923,12 @@ void FreshSupvHandler::handlePacketPrint() { } bool FreshSupvHandler::isCommandAlreadyActive(ActionId_t actionId) const { - auto iter = activeActionCmds.find(actionId); - if (iter == activeActionCmds.end()) { - return false; - } - if (iter->second.isPending) { - return true; + // 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; } @@ -1053,3 +1068,140 @@ ReturnValue_t FreshSupvHandler::eventSubscription() { } return result; } + +ReturnValue_t FreshSupvHandler::handleAckReport(const uint8_t* data) { + using namespace supv; + ReturnValue_t result = returnvalue::OK; + if (not tmReader.verifyCrc()) { + sif::error << "PlocSupervisorHandler::handleAckReport: CRC failure" << std::endl; + triggerEvent(SUPV_CRC_FAILURE_EVENT); + return returnvalue::FAILED; + } + AcknowledgmentReport ack(tmReader); + result = ack.parse(); + 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.printStatusInformation(); + 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; + if (info.ackRecv and info.ackExeRecv) { + actionHelper.finish(true, info.commandedBy, info.commandId, returnvalue::OK); + info.isPending = false; + } + return result; +} + +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; + + if (not tmReader.verifyCrc()) { + return result::CRC_FAILURE; + } + ExecutionReport exe(tmReader); + result = exe.parse(); + if (result != OK) { + 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; + if (info.ackRecv and info.ackExeRecv) { + actionHelper.finish(true, info.commandedBy, info.commandId, returnvalue::OK); + info.isPending = false; + } + 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: { + // We could only allow proper bootup when the time was set successfully, but + // this makes debugging difficult. + + 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.printStatusInformation(); + 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; +} diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index 91b2778d..1296d32c 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -115,6 +115,7 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { struct ActiveCmdInfo { ActiveCmdInfo(uint32_t cmdCountdownMs) : cmdCountdown(cmdCountdownMs) {} + DeviceCommandId_t commandId; bool isPending = false; bool ackRecv = false; bool ackExeRecv = false; @@ -123,8 +124,10 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { 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::map activeActionCmds; ActiveCmdInfo hkRequestCmdInfo = ActiveCmdInfo(500); @@ -134,7 +137,7 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { ReturnValue_t parseTmPackets(); - ReturnValue_t sendCommand(TcBase& tc); + ReturnValue_t sendCommand(TcBase& tc, uint32_t cmdCountdownMs = 1000); ReturnValue_t sendEmptyCmd(uint16_t apid, uint8_t serviceId); ReturnValue_t prepareSelBootImageCmd(const uint8_t* commandData); ReturnValue_t prepareSetTimeRefCmd(); @@ -162,6 +165,11 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { 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); }; #endif /* LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ */ diff --git a/linux/payload/plocSupvDefs.h b/linux/payload/plocSupvDefs.h index fc9b9abe..79e90560 100644 --- a/linux/payload/plocSupvDefs.h +++ b/linux/payload/plocSupvDefs.h @@ -36,6 +36,12 @@ static const Event SUPV_CRC_FAILURE_EVENT = MAKE_EVENT(6, severity::LOW); 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 BOOT_TIMEOUT_MS = 4000; From bd4449d7dd8d9b663597473603a1fd95fa06196c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 14 Nov 2023 11:49:13 +0100 Subject: [PATCH 14/69] Fresh Supv handler --- fsfw | 2 +- linux/payload/FreshSupvHandler.cpp | 394 +++++++++++++++++++++++++---- linux/payload/FreshSupvHandler.h | 15 +- 3 files changed, 359 insertions(+), 52 deletions(-) diff --git a/fsfw b/fsfw index d554062b..91b194d8 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit d554062b86999fd4d94ce9c3fe0341b73984d1ce +Subproject commit 91b194d8ebd79352ad358f955274d49f15dd3e6d diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 06b2eac9..b0846dd2 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -10,6 +10,7 @@ #include "fsfw/ipc/MessageQueueIF.h" #include "fsfw/ipc/QueueFactory.h" #include "fsfw/returnvalues/returnvalue.h" +#include "linux/payload/plocSupvDefs.h" using namespace supv; using namespace returnvalue; @@ -77,7 +78,7 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { hkRequestCmdInfo.cmdCountdown.resetTimer(); hkRequestCmdInfo.ackExeRecv = false; hkRequestCmdInfo.ackRecv = false; - sendEmptyCmd(Apid::HK, static_cast(tc::HkId::GET_REPORT)); + sendEmptyCmd(Apid::HK, static_cast(tc::HkId::GET_REPORT), true); } } } @@ -245,19 +246,19 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI spParams.buf = commandBuffer.data(); switch (actionId) { case GET_HK_REPORT: { - sendEmptyCmd(Apid::HK, static_cast(tc::HkId::GET_REPORT)); + sendEmptyCmd(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(Apid::BOOT_MAN, static_cast(tc::BootManId::START_MPSOC)); + sendEmptyCmd(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(Apid::BOOT_MAN, static_cast(tc::BootManId::SHUTDOWN_MPSOC)); + sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::SHUTDOWN_MPSOC), false); result = returnvalue::OK; break; } @@ -268,7 +269,7 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI } case RESET_MPSOC: { sif::info << "PLOC SUPV: Resetting MPSoC" << std::endl; - sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::RESET_MPSOC)); + sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::RESET_MPSOC), false); result = returnvalue::OK; break; } @@ -292,7 +293,8 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI break; } case GET_BOOT_STATUS_REPORT: { - sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::GET_BOOT_STATUS_REPORT)); + sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::GET_BOOT_STATUS_REPORT), + true); result = returnvalue::OK; break; } @@ -309,7 +311,8 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI break; } case GET_LATCHUP_STATUS_REPORT: { - sendEmptyCmd(Apid::LATCHUP_MON, static_cast(tc::LatchupMonId::GET_STATUS_REPORT)); + sendEmptyCmd(Apid::LATCHUP_MON, static_cast(tc::LatchupMonId::GET_STATUS_REPORT), + true); result = returnvalue::OK; break; } @@ -331,12 +334,12 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI break; } case FACTORY_FLASH: { - sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::FACTORY_FLASH)); + sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::FACTORY_FLASH), false); result = returnvalue::OK; break; } case RESET_PL: { - sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::RESET_PL)); + sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::RESET_PL), false); result = returnvalue::OK; break; } @@ -360,13 +363,13 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI break; } case REQUEST_ADC_REPORT: { - sendEmptyCmd(Apid::ADC_MON, static_cast(tc::AdcMonId::REQUEST_ADC_SAMPLE)); + sendEmptyCmd(Apid::ADC_MON, static_cast(tc::AdcMonId::REQUEST_ADC_SAMPLE), true); result = returnvalue::OK; break; } case REQUEST_LOGGING_COUNTERS: { sendEmptyCmd(Apid::DATA_LOGGER, - static_cast(tc::DataLoggerServiceId::REQUEST_COUNTERS)); + static_cast(tc::DataLoggerServiceId::REQUEST_COUNTERS), true); result = returnvalue::OK; break; } @@ -392,7 +395,7 @@ ReturnValue_t FreshSupvHandler::prepareSetTimeRefCmd() { if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); return returnvalue::OK; } @@ -427,7 +430,7 @@ ReturnValue_t FreshSupvHandler::prepareSelBootImageCmd(const uint8_t* commandDat if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); return returnvalue::OK; } @@ -453,17 +456,21 @@ void FreshSupvHandler::handleTransitionToOn() { bootTimeout.resetTimer(); startupState = StartupState::POWER_SWITCHING; switchIF.sendSwitchCommand(switchId, PowerSwitchIF::SWITCH_ON); - } else { - if (modeHelper.isTimedOut()) { - targetMode = MODE_OFF; - shutdownState = ShutdownState::IDLE; - handleTransitionToOff(); - return; - } + 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; + } else if (switchTimeout.hasTimedOut()) { + targetMode = MODE_OFF; + shutdownState = ShutdownState::IDLE; + handleTransitionToOff(); + return; } } if (startupState == StartupState::BOOTING) { @@ -505,7 +512,8 @@ void FreshSupvHandler::handleTransitionToOff() { } } -ReturnValue_t FreshSupvHandler::sendCommand(TcBase& tc, uint32_t cmdCountdownMs) { +ReturnValue_t FreshSupvHandler::sendCommand(TcBase& tc, bool replyExpected, + uint32_t cmdCountdownMs) { if (DEBUG_PLOC_SUPV) { sif::debug << "PLOC SUPV: SEND PACKET Size " << tc.getFullPacketLen() << " Module APID " << (int)tc.getModuleApid() << " Service ID " << (int)tc.getServiceId() << std::endl; @@ -523,6 +531,8 @@ ReturnValue_t FreshSupvHandler::sendCommand(TcBase& tc, uint32_t cmdCountdownMs) activeCmdIter->second.isPending = true; 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(); } @@ -539,13 +549,13 @@ ReturnValue_t FreshSupvHandler::initialize() { return FreshDeviceHandlerBase::initialize(); } -ReturnValue_t FreshSupvHandler::sendEmptyCmd(uint16_t apid, uint8_t serviceId) { +ReturnValue_t FreshSupvHandler::sendEmptyCmd(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(packet); + sendCommand(packet, replyExpected); return returnvalue::OK; } @@ -561,7 +571,7 @@ ReturnValue_t FreshSupvHandler::prepareSetBootTimeoutCmd(const uint8_t* commandD if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); return returnvalue::OK; } @@ -576,7 +586,7 @@ ReturnValue_t FreshSupvHandler::prepareRestartTriesCmd(const uint8_t* commandDat if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); return returnvalue::OK; } @@ -586,7 +596,7 @@ ReturnValue_t FreshSupvHandler::prepareDisableHk() { if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); return returnvalue::OK; } @@ -608,7 +618,7 @@ ReturnValue_t FreshSupvHandler::prepareLatchupConfigCmd(const uint8_t* commandDa if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); break; } case (supv::DISABLE_LATCHUP_ALERT): { @@ -617,7 +627,7 @@ ReturnValue_t FreshSupvHandler::prepareLatchupConfigCmd(const uint8_t* commandDa if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); break; } default: { @@ -648,7 +658,7 @@ ReturnValue_t FreshSupvHandler::prepareSetAlertLimitCmd(const uint8_t* commandDa if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); return returnvalue::OK; } @@ -673,7 +683,7 @@ ReturnValue_t FreshSupvHandler::prepareSetShutdownTimeoutCmd(const uint8_t* comm if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); return returnvalue::OK; } @@ -690,7 +700,7 @@ ReturnValue_t FreshSupvHandler::prepareSetGpioCmd(const uint8_t* commandData, if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); return returnvalue::OK; } @@ -706,7 +716,7 @@ ReturnValue_t FreshSupvHandler::prepareReadGpioCmd(const uint8_t* commandData, if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); return returnvalue::OK; } @@ -719,7 +729,7 @@ ReturnValue_t FreshSupvHandler::prepareFactoryResetCmd(const uint8_t* commandDat if (result != returnvalue::OK) { return result; } - sendCommand(resetCmd); + sendCommand(resetCmd, false); return returnvalue::OK; } @@ -730,7 +740,7 @@ ReturnValue_t FreshSupvHandler::prepareSetAdcEnabledChannelsCmd(const uint8_t* c if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); return returnvalue::OK; } @@ -744,7 +754,7 @@ ReturnValue_t FreshSupvHandler::prepareSetAdcWindowAndStrideCmd(const uint8_t* c if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); return returnvalue::OK; } @@ -756,7 +766,7 @@ ReturnValue_t FreshSupvHandler::prepareSetAdcThresholdCmd(const uint8_t* command if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); return returnvalue::OK; } @@ -777,7 +787,7 @@ ReturnValue_t FreshSupvHandler::prepareWipeMramCmd(const uint8_t* commandData, s if (result != returnvalue::OK) { return result; } - sendCommand(packet); + sendCommand(packet, false); return returnvalue::OK; } @@ -812,8 +822,8 @@ ReturnValue_t FreshSupvHandler::parseTmPackets() { } case (Apid::HK): { if (tmReader.getServiceId() == static_cast(supv::tm::HkId::REPORT)) { - // TODO: Handle HK report. - return OK; + handleHkReport(receivedData); + continue; } else if (tmReader.getServiceId() == static_cast(supv::tm::HkId::HARDFAULTS)) { handleBadApidServiceCombination(SUPV_UNINIMPLEMENTED_TM, apid, tmReader.getServiceId()); return INVALID_DATA; @@ -823,14 +833,15 @@ ReturnValue_t FreshSupvHandler::parseTmPackets() { case (Apid::BOOT_MAN): { if (tmReader.getServiceId() == static_cast(supv::tm::BootManId::BOOT_STATUS_REPORT)) { - // TODO: Handle boot status report. + handleBootStatusReport(receivedData); continue; } break; } case (Apid::ADC_MON): { if (tmReader.getServiceId() == static_cast(supv::tm::AdcMonId::ADC_REPORT)) { - // TODO: Handle ADC report. + genericHandleTm("ADC", receivedData, adcReport, supv::Apid::ADC_MON, + static_cast(supv::tc::AdcMonId::REQUEST_ADC_SAMPLE)); continue; } break; @@ -838,7 +849,10 @@ ReturnValue_t FreshSupvHandler::parseTmPackets() { case (Apid::MEM_MAN): { if (tmReader.getServiceId() == static_cast(supv::tm::MemManId::UPDATE_STATUS_REPORT)) { - // TODO: Handle 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; @@ -846,7 +860,8 @@ ReturnValue_t FreshSupvHandler::parseTmPackets() { case (Apid::DATA_LOGGER): { if (tmReader.getServiceId() == static_cast(supv::tm::DataLoggerId::COUNTERS_REPORT)) { - // TODO: Handle counters report. + genericHandleTm("COUNTERS", receivedData, countersReport, supv::Apid::DATA_LOGGER, + static_cast(supv::tc::DataLoggerServiceId::REQUEST_COUNTERS)); continue; } } @@ -1100,11 +1115,16 @@ ReturnValue_t FreshSupvHandler::handleAckReport(const uint8_t* data) { return returnvalue::OK; } info.ackRecv = true; - if (info.ackRecv and info.ackExeRecv) { + performCommandCompletionHandling(info); + return result; +} + +void FreshSupvHandler::performCommandCompletionHandling(ActiveCmdInfo& info) { + if (info.ackRecv and info.ackExeRecv and + (not info.replyPacketExpected or info.replyPacketReceived)) { actionHelper.finish(true, info.commandedBy, info.commandId, returnvalue::OK); info.isPending = false; } - return result; } void FreshSupvHandler::printAckFailureInfo(uint16_t statusCode, DeviceCommandId_t commandId) { @@ -1150,10 +1170,7 @@ ReturnValue_t FreshSupvHandler::handleExecutionReport(const uint8_t* data) { return returnvalue::OK; } info.ackExeRecv = true; - if (info.ackRecv and info.ackExeRecv) { - actionHelper.finish(true, info.commandedBy, info.commandId, returnvalue::OK); - info.isPending = false; - } + performCommandCompletionHandling(info); return result; } @@ -1205,3 +1222,282 @@ void FreshSupvHandler::handleExecutionFailureReport(ActiveCmdInfo& info, Executi } info.isPending = false; } + +void FreshSupvHandler::confirmReplyPacketReceived(supv::Apid apid, uint8_t serviceId) { + auto infoIter = activeActionCmds.find( + buildActiveCmdKey(supv::Apid::HK, static_cast(supv::tc::HkId::GET_REPORT))); + if (infoIter != activeActionCmds.end()) { + ActiveCmdInfo& info = infoIter->second; + info.replyPacketReceived = true; + performCommandCompletionHandling(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; +} diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index 1296d32c..6f7d7af2 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -99,6 +99,7 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { 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); @@ -119,6 +120,8 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { 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; @@ -137,8 +140,8 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { ReturnValue_t parseTmPackets(); - ReturnValue_t sendCommand(TcBase& tc, uint32_t cmdCountdownMs = 1000); - ReturnValue_t sendEmptyCmd(uint16_t apid, uint8_t serviceId); + ReturnValue_t sendCommand(TcBase& tc, bool replyPacketExpected, uint32_t cmdCountdownMs = 1000); + ReturnValue_t sendEmptyCmd(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); @@ -170,6 +173,14 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { 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(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); }; #endif /* LINUX_PAYLOAD_FRESHSUPVHANDLER_H_ */ From bb20def961433ae11e60c3ea75dc1ee344c2411a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 14 Nov 2023 13:25:53 +0100 Subject: [PATCH 15/69] Added new payload PST --- .../PlocSupervisorHandler.cpp | 0 .../PlocSupervisorHandler.h | 0 bsp_q7s/objectFactory.cpp | 11 +++++---- bsp_q7s/scheduling.cpp | 9 ++++---- linux/payload/CMakeLists.txt | 1 - linux/payload/FreshSupvHandler.cpp | 2 +- linux/payload/FreshSupvHandler.h | 2 +- linux/payload/PlocSupvUartMan.cpp | 1 + linux/payload/PlocSupvUartMan.h | 1 - mission/pollingSeqTables.cpp | 23 +++++++++++++++++++ mission/pollingSeqTables.h | 2 ++ 11 files changed, 39 insertions(+), 13 deletions(-) rename {linux/payload => archive}/PlocSupervisorHandler.cpp (100%) rename {linux/payload => archive}/PlocSupervisorHandler.h (100%) diff --git a/linux/payload/PlocSupervisorHandler.cpp b/archive/PlocSupervisorHandler.cpp similarity index 100% rename from linux/payload/PlocSupervisorHandler.cpp rename to archive/PlocSupervisorHandler.cpp diff --git a/linux/payload/PlocSupervisorHandler.h b/archive/PlocSupervisorHandler.h similarity index 100% rename from linux/payload/PlocSupervisorHandler.h rename to archive/PlocSupervisorHandler.h diff --git a/bsp_q7s/objectFactory.cpp b/bsp_q7s/objectFactory.cpp index eadf70c6..258703c9 100644 --- a/bsp_q7s/objectFactory.cpp +++ b/bsp_q7s/objectFactory.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -60,6 +59,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" @@ -651,10 +651,11 @@ void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwit 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); + + DhbConfig dhbConf(objects::PLOC_SUPERVISOR_HANDLER); + auto* supvHandler = + new FreshSupvHandler(dhbConf, supervisorCookie, Gpio(gpioIds::ENABLE_SUPV_UART, gpioComIF), + pwrSwitch, power::PDU1_CH6_PLOC_12V, *supvHelper); 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..b4344db2 100644 --- a/bsp_q7s/scheduling.cpp +++ b/bsp_q7s/scheduling.cpp @@ -383,11 +383,12 @@ void scheduling::initTasks() { } #endif /* OBSW_ADD_PLOC_SUPERVISOR */ - PeriodicTaskIF* plTask = factory->createPeriodicTask( + FixedTimeslotTaskIF* plTask = factory->createFixedTimeslotTask( "PL_TASK", 25, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc, &RR_SCHEDULING); - plTask->addComponent(objects::CAM_SWITCHER); - scheduling::addMpsocSupvHandlers(plTask); - scheduling::scheduleScexDev(plTask); + // plTask->addComponent(objects::CAM_SWITCHER); + // scheduling::addMpsocSupvHandlers(plTask); + // scheduling::scheduleScexDev(plTask); + pst::pstPayload(plTask); #if OBSW_ADD_SCEX_DEVICE == 1 PeriodicTaskIF* scexReaderTask; diff --git a/linux/payload/CMakeLists.txt b/linux/payload/CMakeLists.txt index 09062532..48fb9d96 100644 --- a/linux/payload/CMakeLists.txt +++ b/linux/payload/CMakeLists.txt @@ -5,7 +5,6 @@ target_sources( 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 index b0846dd2..798fb652 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -82,7 +82,7 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { } } } - } else if (opCode == OpCode::HANDLE_ACTIVE_CMDS) { + } else if (opCode == OpCode::PARSE_TM) { std::vector cmdsToRemove; for (auto& activeCmd : activeActionCmds) { if (activeCmd.second.cmdCountdown.hasTimedOut()) { diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index 6f7d7af2..0f190a1d 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -19,7 +19,7 @@ static constexpr bool REDUCE_NORMAL_MODE_PRINTOUT = true; class FreshSupvHandler : public FreshDeviceHandlerBase { public: - enum OpCode { DEFAULT_OPERATION = 0, HANDLE_ACTIVE_CMDS = 1 }; + enum OpCode { DEFAULT_OPERATION = 0, PARSE_TM = 1 }; FreshSupvHandler(DhbConfig cfg, CookieIF* comCookie, Gpio uartIsolatorSwitch, PowerSwitchIF& switchIF, power::Switch_t powerSwitch, diff --git a/linux/payload/PlocSupvUartMan.cpp b/linux/payload/PlocSupvUartMan.cpp index 1a129927..00a90fa3 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; diff --git a/linux/payload/PlocSupvUartMan.h b/linux/payload/PlocSupvUartMan.h index dc06b199..2da9a8b9 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" diff --git a/mission/pollingSeqTables.cpp b/mission/pollingSeqTables.cpp index e9adf83b..8bd0bb86 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,24 @@ 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); + 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 From 2563432171bc2c570dc6a1c1046e680ae3f77d35 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 14 Nov 2023 15:28:27 +0100 Subject: [PATCH 16/69] somethings wrong --- bsp_q7s/scheduling.cpp | 3 -- linux/payload/FreshSupvHandler.cpp | 49 +++++++++++++++++++----------- linux/payload/FreshSupvHandler.h | 4 +-- linux/payload/PlocSupvUartMan.cpp | 7 ++++- linux/payload/PlocSupvUartMan.h | 4 +-- linux/payload/plocSupvDefs.h | 2 +- 6 files changed, 42 insertions(+), 27 deletions(-) diff --git a/bsp_q7s/scheduling.cpp b/bsp_q7s/scheduling.cpp index b4344db2..31ccd140 100644 --- a/bsp_q7s/scheduling.cpp +++ b/bsp_q7s/scheduling.cpp @@ -385,9 +385,6 @@ void scheduling::initTasks() { FixedTimeslotTaskIF* plTask = factory->createFixedTimeslotTask( "PL_TASK", 25, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc, &RR_SCHEDULING); - // plTask->addComponent(objects::CAM_SWITCHER); - // scheduling::addMpsocSupvHandlers(plTask); - // scheduling::scheduleScexDev(plTask); pst::pstPayload(plTask); #if OBSW_ADD_SCEX_DEVICE == 1 diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 798fb652..bd964540 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -31,6 +31,8 @@ FreshSupvHandler::FreshSupvHandler(DhbConfig cfg, CookieIF* comCookie, Gpio uart latchupStatusReport(this), countersReport(this), adcReport(this) { + spParams.buf = commandBuffer.data(); + spParams.maxSize = commandBuffer.size(); eventQueue = QueueFactory::instance()->createMessageQueue(EventMessage::EVENT_MESSAGE_SIZE * 5); } @@ -83,7 +85,6 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { } } } else if (opCode == OpCode::PARSE_TM) { - std::vector cmdsToRemove; for (auto& activeCmd : activeActionCmds) { if (activeCmd.second.cmdCountdown.hasTimedOut()) { if (activeCmd.second.commandedBy != MessageQueueIF::NO_QUEUE) { @@ -452,6 +453,7 @@ void FreshSupvHandler::startTransition(Mode_t newMode, Submode_t newSubmode) { } void FreshSupvHandler::handleTransitionToOn() { + sif::debug << "psupv: trans to on" << std::endl; if (startupState == StartupState::IDLE) { bootTimeout.resetTimer(); startupState = StartupState::POWER_SWITCHING; @@ -473,24 +475,31 @@ void FreshSupvHandler::handleTransitionToOn() { return; } } - if (startupState == StartupState::BOOTING) { - if (bootTimeout.hasTimedOut()) { - uartIsolatorSwitch.pullHigh(); - uartManager.start(); - if (SET_TIME_DURING_BOOT) { - // TODO: Send command ,add command to command map. - startupState = StartupState::SET_TIME; - } else { - startupState = StartupState::ON; - } + 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) { + ReturnValue_t result = prepareSetTimeRefCmd(); + if (result != returnvalue::OK) { + sif::error << "FreshSupvHandler: Setting time command prepration failed" << std::endl; + startupState = StartupState::ON; + } + 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; + sif::debug << "psupv: going on" << std::endl; + transitionActive = false; setMode(targetMode); } } @@ -506,7 +515,9 @@ void FreshSupvHandler::handleTransitionToOff() { } if (shutdownState == ShutdownState::POWER_SWITCHING) { if (switchIF.getSwitchState(switchId) == PowerSwitchIF::SWITCH_OFF or modeHelper.isTimedOut()) { + sif::debug << "psupv: going off" << std::endl; supv::SUPV_ON = false; + transitionActive = false; setMode(MODE_OFF); } } @@ -1115,11 +1126,13 @@ ReturnValue_t FreshSupvHandler::handleAckReport(const uint8_t* data) { return returnvalue::OK; } info.ackRecv = true; - performCommandCompletionHandling(info); + performCommandCompletionHandling(static_cast((infoIter->first >> 16) & 0xffff), + infoIter->first & 0xff, info); return result; } -void FreshSupvHandler::performCommandCompletionHandling(ActiveCmdInfo& info) { +void FreshSupvHandler::performCommandCompletionHandling(supv::Apid apid, uint8_t serviceId, + ActiveCmdInfo& info) { if (info.ackRecv and info.ackExeRecv and (not info.replyPacketExpected or info.replyPacketReceived)) { actionHelper.finish(true, info.commandedBy, info.commandId, returnvalue::OK); @@ -1170,7 +1183,9 @@ ReturnValue_t FreshSupvHandler::handleExecutionReport(const uint8_t* data) { return returnvalue::OK; } info.ackExeRecv = true; - performCommandCompletionHandling(info); + performCommandCompletionHandling(static_cast((infoIter->first >> 16) & 0xffff), + infoIter->first & 0xff, info); + return result; } @@ -1197,9 +1212,6 @@ ReturnValue_t FreshSupvHandler::handleExecutionSuccessReport(ActiveCmdInfo& info break; } case supv::SET_TIME_REF: { - // We could only allow proper bootup when the time was set successfully, but - // this makes debugging difficult. - if (startupState == StartupState::WAIT_FOR_TIME_REPLY) { startupState = StartupState::TIME_WAS_SET; } @@ -1229,7 +1241,8 @@ void FreshSupvHandler::confirmReplyPacketReceived(supv::Apid apid, uint8_t servi if (infoIter != activeActionCmds.end()) { ActiveCmdInfo& info = infoIter->second; info.replyPacketReceived = true; - performCommandCompletionHandling(info); + performCommandCompletionHandling(static_cast((infoIter->first >> 16) & 0xffff), + infoIter->first & 0xff, info); } } diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index 0f190a1d..2efd5d9d 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -15,7 +15,7 @@ using supv::TcBase; static constexpr bool DEBUG_PLOC_SUPV = true; -static constexpr bool REDUCE_NORMAL_MODE_PRINTOUT = true; +static constexpr bool REDUCE_NORMAL_MODE_PRINTOUT = false; class FreshSupvHandler : public FreshDeviceHandlerBase { public: @@ -176,7 +176,7 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { 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(ActiveCmdInfo& info); + 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); diff --git a/linux/payload/PlocSupvUartMan.cpp b/linux/payload/PlocSupvUartMan.cpp index 00a90fa3..b53a5f32 100644 --- a/linux/payload/PlocSupvUartMan.cpp +++ b/linux/payload/PlocSupvUartMan.cpp @@ -45,10 +45,12 @@ PlocSupvUartManager::PlocSupvUartManager(object_id_t objectId) PlocSupvUartManager::~PlocSupvUartManager() = default; ReturnValue_t PlocSupvUartManager::initializeInterface(CookieIF* cookie) { + sif::debug << "init ploc supv uart IF" << std::endl; auto* uartCookie = dynamic_cast(cookie); if (uartCookie == nullptr) { return FAILED; } + sif::debug << "hello blub" << std::endl; std::string devname = uartCookie->getDeviceFile(); /* Get file descriptor */ serialPort = open(devname.c_str(), O_RDWR); @@ -70,7 +72,7 @@ ReturnValue_t PlocSupvUartManager::initializeInterface(CookieIF* cookie) { tty.c_lflag &= ~(ICANON | ECHO); // Blocking mode, 0.2 seconds timeout - tty.c_cc[VTIME] = 2; + tty.c_cc[VTIME] = 0; tty.c_cc[VMIN] = 0; serial::setBaudrate(tty, uartCookie->getBaudrate()); @@ -80,6 +82,7 @@ ReturnValue_t PlocSupvUartManager::initializeInterface(CookieIF* cookie) { } // Flush received and unread data tcflush(serialPort, TCIOFLUSH); + sif::debug << "ploc supv cfg complete" << std::endl; return OK; } @@ -114,6 +117,7 @@ ReturnValue_t PlocSupvUartManager::performOperation(uint8_t operationCode) { lock->lockMutex(); InternalState currentState = state; lock->unlockMutex(); + sif::debug << "supv uart man post-lock" << std::endl; switch (currentState) { case InternalState::SLEEPING: case InternalState::GO_TO_SLEEP: { @@ -139,6 +143,7 @@ ReturnValue_t PlocSupvUartManager::performOperation(uint8_t operationCode) { ReturnValue_t PlocSupvUartManager::handleUartReception() { ReturnValue_t result = OK; ReturnValue_t status = OK; + sif::debug << "handling uart reception" << std::endl; ssize_t bytesRead = read(serialPort, reinterpret_cast(recBuf.data()), static_cast(recBuf.size())); if (bytesRead == 0) { diff --git a/linux/payload/PlocSupvUartMan.h b/linux/payload/PlocSupvUartMan.h index 2da9a8b9..e5d01f70 100644 --- a/linux/payload/PlocSupvUartMan.h +++ b/linux/payload/PlocSupvUartMan.h @@ -282,8 +282,8 @@ class PlocSupvUartManager : public DeviceCommunicationIF, std::array tmBuf{}; - bool printTc = false; - bool debugMode = false; + bool printTc = true; + bool debugMode = true; bool timestamping = true; // Remembers APID to know at which command a procedure failed diff --git a/linux/payload/plocSupvDefs.h b/linux/payload/plocSupvDefs.h index 79e90560..c7fa3ae7 100644 --- a/linux/payload/plocSupvDefs.h +++ b/linux/payload/plocSupvDefs.h @@ -45,7 +45,7 @@ static const Event SUPV_EXE_ACK_UNKNOWN_COMMAND = MAKE_EVENT(10, severity::LOW); extern std::atomic_bool SUPV_ON; static constexpr uint32_t BOOT_TIMEOUT_MS = 4000; -static constexpr uint32_t MAX_TRANSITION_TIME_TO_ON_MS = 6000; +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 { From 3898e2d66f16cf0753ad523bec2fb2be9fa9a474 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 14 Nov 2023 18:20:52 +0100 Subject: [PATCH 17/69] almost there.. I think --- bsp_q7s/objectFactory.cpp | 7 + bsp_q7s/scheduling.cpp | 2 +- linux/payload/CMakeLists.txt | 1 + linux/payload/FreshSupvHandler.cpp | 40 +- linux/payload/FreshSupvHandler.h | 2 - linux/payload/PlocSupervisorHandler.cpp | 2027 +++++++++++++++++++++++ linux/payload/PlocSupervisorHandler.h | 386 +++++ linux/payload/PlocSupvUartMan.cpp | 9 +- linux/payload/PlocSupvUartMan.h | 2 +- linux/payload/plocSupvDefs.h | 3 + mission/pollingSeqTables.cpp | 7 + 11 files changed, 2454 insertions(+), 32 deletions(-) create mode 100644 linux/payload/PlocSupervisorHandler.cpp create mode 100644 linux/payload/PlocSupervisorHandler.h diff --git a/bsp_q7s/objectFactory.cpp b/bsp_q7s/objectFactory.cpp index 258703c9..4a9d3080 100644 --- a/bsp_q7s/objectFactory.cpp +++ b/bsp_q7s/objectFactory.cpp @@ -60,6 +60,7 @@ #include "linux/ipcore/Ptme.h" #include "linux/ipcore/PtmeConfig.h" #include "linux/payload/FreshSupvHandler.h" +#include "linux/payload/PlocSupervisorHandler.h" #include "mission/config/configfile.h" #include "mission/system/acs/AcsBoardFdir.h" #include "mission/system/acs/AcsSubsystem.h" @@ -656,6 +657,12 @@ void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwit auto* supvHandler = new FreshSupvHandler(dhbConf, supervisorCookie, Gpio(gpioIds::ENABLE_SUPV_UART, gpioComIF), pwrSwitch, power::PDU1_CH6_PLOC_12V, *supvHelper); + /* + auto* supvHandler = new PlocSupervisorHandler(objects::PLOC_SUPERVISOR_HANDLER, supervisorCookie, + Gpio(gpioIds::ENABLE_SUPV_UART, gpioComIF), + power::PDU1_CH6_PLOC_12V, *supvHelper); + supvHandler->setPowerSwitcher(&pwrSwitch); + */ 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 31ccd140..fd99ab3f 100644 --- a/bsp_q7s/scheduling.cpp +++ b/bsp_q7s/scheduling.cpp @@ -384,7 +384,7 @@ void scheduling::initTasks() { #endif /* OBSW_ADD_PLOC_SUPERVISOR */ FixedTimeslotTaskIF* plTask = factory->createFixedTimeslotTask( - "PL_TASK", 25, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc, &RR_SCHEDULING); + "PL_TASK", 25, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc); pst::pstPayload(plTask); #if OBSW_ADD_SCEX_DEVICE == 1 diff --git a/linux/payload/CMakeLists.txt b/linux/payload/CMakeLists.txt index 48fb9d96..2def0752 100644 --- a/linux/payload/CMakeLists.txt +++ b/linux/payload/CMakeLists.txt @@ -3,6 +3,7 @@ target_sources( PUBLIC PlocMemoryDumper.cpp PlocMpsocHandler.cpp FreshSupvHandler.cpp + PlocSupervisorHandler.cpp PlocMpsocSpecialComHelper.cpp plocMpsocHelpers.cpp PlocSupvUartMan.cpp diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index bd964540..581dd348 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -10,6 +10,7 @@ #include "fsfw/ipc/MessageQueueIF.h" #include "fsfw/ipc/QueueFactory.h" #include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/tasks/TaskFactory.h" #include "linux/payload/plocSupvDefs.h" using namespace supv; @@ -33,7 +34,7 @@ FreshSupvHandler::FreshSupvHandler(DhbConfig cfg, CookieIF* comCookie, Gpio uart adcReport(this) { spParams.buf = commandBuffer.data(); spParams.maxSize = commandBuffer.size(); - eventQueue = QueueFactory::instance()->createMessageQueue(EventMessage::EVENT_MESSAGE_SIZE * 5); + eventQueue = QueueFactory::instance()->createMessageQueue(10); } void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { @@ -70,16 +71,9 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { } } else { if (mode == MODE_NORMAL) { - if (hkRequestCmdInfo.isPending and hkRequestCmdInfo.cmdCountdown.hasTimedOut()) { - // trigger event? might lead to spam... - sif::warning << "FreshSupvHandler: No reply received for HK set request" << std::endl; - hkRequestCmdInfo.isPending = false; - } - // Normal mode handling. Request normal data sets and add them to command map. - if (not hkRequestCmdInfo.isPending) { - hkRequestCmdInfo.cmdCountdown.resetTimer(); - hkRequestCmdInfo.ackExeRecv = false; - hkRequestCmdInfo.ackRecv = false; + auto cmdIter = activeActionCmds.find( + buildActiveCmdKey(Apid::HK, static_cast(tc::HkId::GET_REPORT))); + if (cmdIter == activeActionCmds.end() or not cmdIter->second.isPending) { sendEmptyCmd(Apid::HK, static_cast(tc::HkId::GET_REPORT), true); } } @@ -436,7 +430,7 @@ ReturnValue_t FreshSupvHandler::prepareSelBootImageCmd(const uint8_t* commandDat } void FreshSupvHandler::startTransition(Mode_t newMode, Submode_t newSubmode) { - if (newMode == mode) { + if (newMode == mode or (mode == MODE_ON and newMode == MODE_NORMAL)) { // Can finish immediately. setMode(newMode, newSubmode); return; @@ -453,9 +447,7 @@ void FreshSupvHandler::startTransition(Mode_t newMode, Submode_t newSubmode) { } void FreshSupvHandler::handleTransitionToOn() { - sif::debug << "psupv: trans to on" << std::endl; if (startupState == StartupState::IDLE) { - bootTimeout.resetTimer(); startupState = StartupState::POWER_SWITCHING; switchIF.sendSwitchCommand(switchId, PowerSwitchIF::SWITCH_ON); switchTimeout.resetTimer(); @@ -468,6 +460,7 @@ void FreshSupvHandler::handleTransitionToOn() { 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; @@ -489,8 +482,9 @@ void FreshSupvHandler::handleTransitionToOn() { if (result != returnvalue::OK) { sif::error << "FreshSupvHandler: Setting time command prepration failed" << std::endl; startupState = StartupState::ON; + } else { + startupState = StartupState::WAIT_FOR_TIME_REPLY; } - startupState = StartupState::WAIT_FOR_TIME_REPLY; } if (startupState == StartupState::TIME_WAS_SET) { startupState = StartupState::ON; @@ -498,7 +492,6 @@ void FreshSupvHandler::handleTransitionToOn() { if (startupState == StartupState::ON) { hkSet.setReportingEnabled(true); supv::SUPV_ON = true; - sif::debug << "psupv: going on" << std::endl; transitionActive = false; setMode(targetMode); } @@ -515,7 +508,6 @@ void FreshSupvHandler::handleTransitionToOff() { } if (shutdownState == ShutdownState::POWER_SWITCHING) { if (switchIF.getSwitchState(switchId) == PowerSwitchIF::SWITCH_OFF or modeHelper.isTimedOut()) { - sif::debug << "psupv: going off" << std::endl; supv::SUPV_ON = false; transitionActive = false; setMode(MODE_OFF); @@ -525,7 +517,7 @@ void FreshSupvHandler::handleTransitionToOff() { ReturnValue_t FreshSupvHandler::sendCommand(TcBase& tc, bool replyExpected, uint32_t cmdCountdownMs) { - if (DEBUG_PLOC_SUPV) { + if (supv::DEBUG_PLOC_SUPV) { sif::debug << "PLOC SUPV: SEND PACKET Size " << tc.getFullPacketLen() << " Module APID " << (int)tc.getModuleApid() << " Service ID " << (int)tc.getServiceId() << std::endl; } @@ -557,7 +549,9 @@ ReturnValue_t FreshSupvHandler::initialize() { if (result != returnvalue::OK) { return result; } - return FreshDeviceHandlerBase::initialize(); + result = FreshDeviceHandlerBase::initialize(); + sif::debug << "serial port: " << uartManager.serialPort << std::endl; + return result; } ReturnValue_t FreshSupvHandler::sendEmptyCmd(uint16_t apid, uint8_t serviceId, bool replyExpected) { @@ -812,7 +806,7 @@ ReturnValue_t FreshSupvHandler::parseTmPackets() { } tmReader.setData(receivedData, receivedSize); uint16_t apid = tmReader.getModuleApid(); - if (DEBUG_PLOC_SUPV) { + if (supv::DEBUG_PLOC_SUPV) { handlePacketPrint(); } switch (apid) { @@ -904,7 +898,8 @@ void FreshSupvHandler::handlePacketPrint() { 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 + if (supv::REDUCE_NORMAL_MODE_PRINTOUT and + ack.getRefModuleApid() == (uint8_t)supv::Apid::HK and ack.getRefServiceId() == (uint8_t)supv::tc::HkId::GET_REPORT) { return; } @@ -927,7 +922,8 @@ void FreshSupvHandler::handlePacketPrint() { 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 + if (supv::REDUCE_NORMAL_MODE_PRINTOUT and + exe.getRefModuleApid() == (uint8_t)supv::Apid::HK and exe.getRefServiceId() == (uint8_t)supv::tc::HkId::GET_REPORT) { return; } diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index 2efd5d9d..0cf56487 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -132,8 +132,6 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { // Map for Action commands. For normal commands, a separate static structure will be used. std::map activeActionCmds; - ActiveCmdInfo hkRequestCmdInfo = ActiveCmdInfo(500); - std::array commandBuffer; SpacePacketCreator creator; supv::TcParams spParams = supv::TcParams(creator); diff --git a/linux/payload/PlocSupervisorHandler.cpp b/linux/payload/PlocSupervisorHandler.cpp new file mode 100644 index 00000000..67ec707f --- /dev/null +++ b/linux/payload/PlocSupervisorHandler.cpp @@ -0,0 +1,2027 @@ +#include "PlocSupervisorHandler.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include "OBSWConfig.h" +#include "eive/definitions.h" +#include "fsfw/datapool/PoolReadGuard.h" +#include "fsfw/globalfunctions/CRC.h" +#include "fsfw/ipc/QueueFactory.h" +#include "fsfw/timemanager/Clock.h" + +using namespace supv; +using namespace returnvalue; + +PlocSupervisorHandler::PlocSupervisorHandler(object_id_t objectId, CookieIF* comCookie, + Gpio uartIsolatorSwitch, power::Switch_t powerSwitch, + PlocSupvUartManager& supvHelper) + : DeviceHandlerBase(objectId, supvHelper.getObjectId(), comCookie), + uartIsolatorSwitch(uartIsolatorSwitch), + hkset(this), + bootStatusReport(this), + latchupStatusReport(this), + countersReport(this), + adcReport(this), + powerSwitch(powerSwitch), + uartManager(supvHelper) { + if (comCookie == nullptr) { + sif::error << "PlocSupervisorHandler: Invalid com cookie" << std::endl; + } + spParams.buf = commandBuffer; + spParams.maxSize = sizeof(commandBuffer); + eventQueue = QueueFactory::instance()->createMessageQueue(EventMessage::EVENT_MESSAGE_SIZE * 5); +} + +PlocSupervisorHandler::~PlocSupervisorHandler() {} + +ReturnValue_t PlocSupervisorHandler::initialize() { + ReturnValue_t result = returnvalue::OK; + result = DeviceHandlerBase::initialize(); + if (result != returnvalue::OK) { + return result; + } +#ifdef XIPHOS_Q7S + sdcMan = SdCardManager::instance(); +#endif /* TE0720_1CFA */ + + result = eventSubscription(); + if (result != returnvalue::OK) { + return result; + } + return result; +} + +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)) { + 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; + } + } +} + +ReturnValue_t PlocSupervisorHandler::executeAction(ActionId_t actionId, + MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) { + using namespace supv; + ReturnValue_t result = returnvalue::OK; + + switch (actionId) { + default: + break; + } + + if (uartManager.longerRequestActive()) { + return result::SUPV_HELPER_EXECUTING; + } + + result = acceptExternalDeviceCommands(); + if (result != returnvalue::OK) { + return result; + } + + switch (actionId) { + case PERFORM_UPDATE: { + if (size > config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE) { + return result::FILENAME_TOO_LONG; + } + shutdownCmdSent = false; + 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: { + shutdownCmdSent = false; + uartManager.initiateUpdateContinuation(); + return EXECUTION_FINISHED; + } + case MEMORY_CHECK_WITH_FILE: { + shutdownCmdSent = false; + 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; + } + return DeviceHandlerBase::executeAction(actionId, commandedBy, data, size); +} + +void PlocSupervisorHandler::doStartUp() { + if (startupState == StartupState::OFF) { + bootTimeout.resetTimer(); + startupState = StartupState::BOOTING; + } + if (startupState == StartupState::BOOTING) { + if (bootTimeout.hasTimedOut()) { + uartIsolatorSwitch.pullHigh(); + uartManager.start(); + if (SET_TIME_DURING_BOOT) { + startupState = StartupState::SET_TIME; + } else { + startupState = StartupState::ON; + } + } + } + if (startupState == StartupState::TIME_WAS_SET) { + startupState = StartupState::ON; + } + if (startupState == StartupState::ON) { + hkset.setReportingEnabled(true); + supv::SUPV_ON = true; + setMode(_MODE_TO_ON); + } +} + +void PlocSupervisorHandler::doShutDown() { + setMode(_MODE_POWER_DOWN); + hkset.setReportingEnabled(false); + hkset.setValidity(false, true); + shutdownCmdSent = false; + packetInBuffer = false; + nextReplyId = supv::NONE; + uartManager.stop(); + uartIsolatorSwitch.pullLow(); + disableAllReplies(); + supv::SUPV_ON = false; + startupState = StartupState::OFF; +} + +ReturnValue_t PlocSupervisorHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { + if (not normalCommandIsPending) { + *id = GET_HK_REPORT; + normalCommandIsPending = true; + normalCmdCd.resetTimer(); + return buildCommandFromCommand(*id, nullptr, 0); + } + return NOTHING_TO_SEND; +} + +ReturnValue_t PlocSupervisorHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { + if (startupState == StartupState::SET_TIME) { + *id = supv::SET_TIME_REF; + startupState = StartupState::WAIT_FOR_TIME_REPLY; + return buildCommandFromCommand(*id, nullptr, 0); + } + return NOTHING_TO_SEND; +} + +ReturnValue_t PlocSupervisorHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand, + const uint8_t* commandData, + size_t commandDataLen) { + using namespace supv; + ReturnValue_t result = returnvalue::FAILED; + spParams.buf = commandBuffer; + switch (deviceCommand) { + case GET_HK_REPORT: { + prepareEmptyCmd(Apid::HK, static_cast(tc::HkId::GET_REPORT)); + result = returnvalue::OK; + break; + } + case START_MPSOC: { + sif::info << "PLOC SUPV: Starting MPSoC" << std::endl; + prepareEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::START_MPSOC)); + result = returnvalue::OK; + break; + } + case SHUTDOWN_MPSOC: { + sif::info << "PLOC SUPV: Shutting down MPSoC" << std::endl; + prepareEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::SHUTDOWN_MPSOC)); + result = returnvalue::OK; + break; + } + case SEL_MPSOC_BOOT_IMAGE: { + prepareSelBootImageCmd(commandData); + result = returnvalue::OK; + break; + } + case RESET_MPSOC: { + sif::info << "PLOC SUPV: Resetting MPSoC" << std::endl; + prepareEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::RESET_MPSOC)); + result = returnvalue::OK; + break; + } + case SET_TIME_REF: { + result = prepareSetTimeRefCmd(); + break; + } + case SET_BOOT_TIMEOUT: { + prepareSetBootTimeoutCmd(commandData); + result = returnvalue::OK; + break; + } + case SET_MAX_RESTART_TRIES: { + prepareRestartTriesCmd(commandData); + result = returnvalue::OK; + break; + } + case DISABLE_PERIOIC_HK_TRANSMISSION: { + prepareDisableHk(); + result = returnvalue::OK; + break; + } + case GET_BOOT_STATUS_REPORT: { + prepareEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::GET_BOOT_STATUS_REPORT)); + result = returnvalue::OK; + break; + } + case ENABLE_LATCHUP_ALERT: { + result = prepareLatchupConfigCmd(commandData, deviceCommand); + break; + } + case DISABLE_LATCHUP_ALERT: { + result = prepareLatchupConfigCmd(commandData, deviceCommand); + break; + } + case SET_ALERT_LIMIT: { + result = prepareSetAlertLimitCmd(commandData); + break; + } + case GET_LATCHUP_STATUS_REPORT: { + prepareEmptyCmd(Apid::LATCHUP_MON, static_cast(tc::LatchupMonId::GET_STATUS_REPORT)); + result = returnvalue::OK; + break; + } + case RUN_AUTO_EM_TESTS: { + result = prepareRunAutoEmTest(commandData); + break; + } + case SET_GPIO: { + result = prepareSetGpioCmd(commandData, commandDataLen); + break; + } + case FACTORY_RESET: { + result = prepareFactoryResetCmd(commandData, commandDataLen); + break; + } + case READ_GPIO: { + result = prepareReadGpioCmd(commandData, commandDataLen); + break; + } + case SET_SHUTDOWN_TIMEOUT: { + prepareSetShutdownTimeoutCmd(commandData); + result = returnvalue::OK; + break; + } + case FACTORY_FLASH: { + prepareEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::FACTORY_FLASH)); + result = returnvalue::OK; + break; + } + case RESET_PL: { + prepareEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::RESET_PL)); + result = returnvalue::OK; + break; + } + case SET_ADC_ENABLED_CHANNELS: { + prepareSetAdcEnabledChannelsCmd(commandData); + result = returnvalue::OK; + break; + } + case SET_ADC_WINDOW_AND_STRIDE: { + prepareSetAdcWindowAndStrideCmd(commandData); + result = returnvalue::OK; + break; + } + case SET_ADC_THRESHOLD: { + prepareSetAdcThresholdCmd(commandData); + result = returnvalue::OK; + break; + } + case WIPE_MRAM: { + 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; +} + +void PlocSupervisorHandler::fillCommandAndReplyMap() { + // Command only + insertInCommandMap(GET_HK_REPORT); + insertInCommandMap(START_MPSOC); + insertInCommandMap(SHUTDOWN_MPSOC); + insertInCommandMap(SEL_MPSOC_BOOT_IMAGE); + insertInCommandMap(SET_BOOT_TIMEOUT); + insertInCommandMap(SET_MAX_RESTART_TRIES); + insertInCommandMap(RESET_MPSOC); + insertInCommandMap(WIPE_MRAM); + insertInCommandMap(SET_TIME_REF); + insertInCommandMap(DISABLE_PERIOIC_HK_TRANSMISSION); + insertInCommandMap(GET_BOOT_STATUS_REPORT); + insertInCommandMap(ENABLE_LATCHUP_ALERT); + insertInCommandMap(DISABLE_LATCHUP_ALERT); + insertInCommandMap(SET_ALERT_LIMIT); + insertInCommandMap(GET_LATCHUP_STATUS_REPORT); + insertInCommandMap(RUN_AUTO_EM_TESTS); + insertInCommandMap(SET_GPIO); + insertInCommandMap(READ_GPIO); + insertInCommandMap(FACTORY_RESET); + insertInCommandMap(MEMORY_CHECK); + insertInCommandMap(SET_SHUTDOWN_TIMEOUT); + insertInCommandMap(FACTORY_FLASH); + insertInCommandMap(SET_ADC_ENABLED_CHANNELS); + 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); + insertInReplyMap(EXE_REPORT, 0, nullptr, SIZE_EXE_REPORT, false, &executionReportTimeout); + insertInReplyMap(MEMORY_CHECK, 5, nullptr, 0, false); + + // TM replies + 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(COUNTERS_REPORT, 3, &countersReport, SIZE_COUNTERS_REPORT); + insertInReplyMap(ADC_REPORT, 3, &adcReport, SIZE_ADC_REPORT); +} + +ReturnValue_t PlocSupervisorHandler::enableReplyInReplyMap(DeviceCommandMap::iterator command, + uint8_t expectedReplies, + bool useAlternateId, + DeviceCommandId_t alternateReplyID) { + ReturnValue_t result = OK; + + uint8_t enabledReplies = 0; + + switch (command->first) { + case GET_HK_REPORT: { + enabledReplies = 3; + result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, HK_REPORT); + if (result != returnvalue::OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " << HK_REPORT + << " not in replyMap" << std::endl; + } + break; + } + case GET_BOOT_STATUS_REPORT: { + enabledReplies = 3; + result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, + BOOT_STATUS_REPORT); + if (result != returnvalue::OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " + << BOOT_STATUS_REPORT << " not in replyMap" << std::endl; + } + break; + } + case GET_LATCHUP_STATUS_REPORT: { + enabledReplies = 3; + result = + DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, LATCHUP_REPORT); + if (result != returnvalue::OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " + << LATCHUP_REPORT << " not in replyMap" << std::endl; + } + break; + } + case REQUEST_LOGGING_COUNTERS: { + enabledReplies = 3; + result = + DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, COUNTERS_REPORT); + if (result != returnvalue::OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " + << COUNTERS_REPORT << " not in replyMap" << std::endl; + } + break; + } + case REQUEST_ADC_REPORT: { + enabledReplies = 3; + result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, ADC_REPORT); + if (result != returnvalue::OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " << ADC_REPORT + << " not in replyMap" << std::endl; + } + break; + } + case FIRST_MRAM_DUMP: { + enabledReplies = 2; // expected replies will be increased in handleMramDumpPacket + result = + DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, FIRST_MRAM_DUMP); + if (result != returnvalue::OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " + << FIRST_MRAM_DUMP << " not in replyMap" << std::endl; + } + break; + } + case CONSECUTIVE_MRAM_DUMP: { + enabledReplies = 2; // expected replies will be increased in handleMramDumpPacket + result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, + CONSECUTIVE_MRAM_DUMP); + if (result != returnvalue::OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " + << CONSECUTIVE_MRAM_DUMP << " not in replyMap" << std::endl; + } + break; + } + case MEMORY_CHECK: { + enabledReplies = 3; + result = + DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, MEMORY_CHECK); + if (result != returnvalue::OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " << MEMORY_CHECK + << " not in replyMap" << std::endl; + } + break; + } + case START_MPSOC: + case SHUTDOWN_MPSOC: + case SEL_MPSOC_BOOT_IMAGE: + case SET_BOOT_TIMEOUT: + case SET_MAX_RESTART_TRIES: + case RESET_MPSOC: + case SET_TIME_REF: + case ENABLE_LATCHUP_ALERT: + case DISABLE_LATCHUP_ALERT: + case SET_ALERT_LIMIT: + case SET_ADC_ENABLED_CHANNELS: + case SET_ADC_WINDOW_AND_STRIDE: + case SET_ADC_THRESHOLD: + case RUN_AUTO_EM_TESTS: + case WIPE_MRAM: + case SET_GPIO: + case FACTORY_RESET: + case READ_GPIO: + case DISABLE_PERIOIC_HK_TRANSMISSION: + case SET_SHUTDOWN_TIMEOUT: + case FACTORY_FLASH: + case ENABLE_AUTO_TM: + case DISABLE_AUTO_TM: + case RESET_PL: + enabledReplies = 2; + break; + default: + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Unknown command id" << std::endl; + break; + } + + /** + * Every command causes at least one acknowledgment and one execution report. Therefore both + * replies will be enabled here. + */ + result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, ACK_REPORT); + if (result != returnvalue::OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " << ACK_REPORT + << " not in replyMap" << std::endl; + } + + setExecutionTimeout(command->first); + + result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, EXE_REPORT); + if (result != returnvalue::OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " << EXE_REPORT + << " not in replyMap" << std::endl; + } + + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::scanForReply(const uint8_t* start, size_t remainingSize, + DeviceCommandId_t* foundId, size_t* foundLen) { + using namespace supv; + + tmReader.setData(start, remainingSize); + uint16_t apid = tmReader.getModuleApid(); + if (DEBUG_PLOC_SUPV) { + handlePacketPrint(); + } + + switch (apid) { + case (Apid::TMTC_MAN): { + switch (tmReader.getServiceId()) { + case (static_cast(supv::tm::TmtcId::ACK)): + case (static_cast(supv::tm::TmtcId::NAK)): { + *foundLen = tmReader.getFullPacketLen(); + *foundId = ReplyId::ACK_REPORT; + return OK; + } + case (static_cast(supv::tm::TmtcId::EXEC_ACK)): + case (static_cast(supv::tm::TmtcId::EXEC_NAK)): { + *foundLen = tmReader.getFullPacketLen(); + *foundId = EXE_REPORT; + return OK; + } + } + break; + } + 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; + } 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)) { + *foundLen = tmReader.getFullPacketLen(); + *foundId = ReplyId::BOOT_STATUS_REPORT; + return OK; + } + 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)) { + *foundLen = tmReader.getFullPacketLen(); + *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()); + *foundLen = remainingSize; + return INVALID_DATA; +} + +void PlocSupervisorHandler::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(); + 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"; + + } 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(); + 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"; + + } 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; + } + } + sif::debug << "PlocSupervisorHandler: RECV PACKET Size " << tmReader.getFullPacketLen() + << " Module APID " << (int)tmReader.getModuleApid() << " Service ID " + << (int)tmReader.getServiceId() << std::endl; +} +ReturnValue_t PlocSupervisorHandler::interpretDeviceReply(DeviceCommandId_t id, + const uint8_t* packet) { + using namespace supv; + ReturnValue_t result = returnvalue::OK; + + switch (id) { + case ACK_REPORT: { + result = handleAckReport(packet); + break; + } + case (HK_REPORT): { + result = handleHkReport(packet); + break; + } + case (BOOT_STATUS_REPORT): { + 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 = genericHandleTm("ADC", packet, adcReport); +#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_PLOC_SUPERVISOR == 1 + adcReport.printSet(); +#endif + break; + } + case (EXE_REPORT): { + result = handleExecutionReport(packet); + break; + } + case (UPDATE_STATUS_REPORT): { + // TODO: handle status report here + break; + } + default: { + sif::debug << "PlocSupervisorHandler::interpretDeviceReply: Unknown device reply id" + << std::endl; + return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY; + } + } + + return result; +} + +ReturnValue_t PlocSupervisorHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) { + 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_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; +} + +void PlocSupervisorHandler::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) { + // Wait for a short period for the uart state machine to adjust + // TaskFactory::delayTask(5); + if (not shutdownCmdSent) { + shutdownCmdSent = true; + result = this->executeAction(supv::SHUTDOWN_MPSOC, NO_COMMANDER, nullptr, 0); + if (result != returnvalue::OK) { + triggerEvent(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; + } +} + +void PlocSupervisorHandler::setExecutionTimeout(DeviceCommandId_t command) { + using namespace supv; + switch (command) { + case FIRST_MRAM_DUMP: + case CONSECUTIVE_MRAM_DUMP: + executionReportTimeout.setTimeout(MRAM_DUMP_EXECUTION_TIMEOUT); + break; + case COPY_ADC_DATA_TO_MRAM: + executionReportTimeout.setTimeout(COPY_ADC_TO_MRAM_TIMEOUT); + break; + default: + executionReportTimeout.setTimeout(EXECUTION_DEFAULT_TIMEOUT); + break; + } +} + +ReturnValue_t PlocSupervisorHandler::verifyPacket(const uint8_t* start, size_t foundLen) { + if (CRC::crc16ccitt(start, foundLen) != 0) { + return result::CRC_FAILURE; + } + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::handleAckReport(const uint8_t* data) { + using namespace supv; + ReturnValue_t result = returnvalue::OK; + + if (not tmReader.verifyCrc()) { + sif::error << "PlocSupervisorHandler::handleAckReport: CRC failure" << std::endl; + nextReplyId = supv::NONE; + replyRawReplyIfnotWiretapped(data, supv::SIZE_ACK_REPORT); + triggerEvent(SUPV_CRC_FAILURE_EVENT); + sendFailureReport(supv::ACK_REPORT, result::CRC_FAILURE); + disableAllReplies(); + return returnvalue::OK; + } + AcknowledgmentReport ack(tmReader); + result = ack.parse(); + if (result != returnvalue::OK) { + nextReplyId = supv::NONE; + replyRawReplyIfnotWiretapped(data, supv::SIZE_ACK_REPORT); + triggerEvent(SUPV_CRC_FAILURE_EVENT); + sendFailureReport(supv::ACK_REPORT, result); + disableAllReplies(); + return result; + } + if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::NAK)) { + DeviceCommandId_t commandId = getPendingCommand(); + if (commandId != DeviceHandlerIF::NO_COMMAND_ID) { + triggerEvent(SUPV_ACK_FAILURE, commandId, static_cast(ack.getStatusCode())); + } + ack.printStatusInformation(); + printAckFailureInfo(ack.getStatusCode(), commandId); + sendFailureReport(supv::ACK_REPORT, result::RECEIVED_ACK_FAILURE); + disableAllReplies(); + nextReplyId = supv::NONE; + result = IGNORE_REPLY_DATA; + } else if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::ACK)) { + setNextReplyId(); + } + return result; +} + +ReturnValue_t PlocSupervisorHandler::handleExecutionReport(const uint8_t* data) { + using namespace supv; + ReturnValue_t result = returnvalue::OK; + + if (not tmReader.verifyCrc()) { + nextReplyId = supv::NONE; + return result::CRC_FAILURE; + } + ExecutionReport report(tmReader); + result = report.parse(); + if (result != OK) { + nextReplyId = supv::NONE; + return result; + } + if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::EXEC_ACK)) { + result = handleExecutionSuccessReport(report); + } else if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::EXEC_NAK)) { + handleExecutionFailureReport(report); + } + commandIsPending = false; + nextReplyId = supv::NONE; + return result; +} + +ReturnValue_t PlocSupervisorHandler::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; + + nextReplyId = supv::EXE_REPORT; + hkset.setValidity(true, true); + +#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 PlocSupervisorHandler::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); + + nextReplyId = supv::EXE_REPORT; + bootStatusReport.setValidity(true, true); + +#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 PlocSupervisorHandler::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); + + nextReplyId = supv::EXE_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 PlocSupervisorHandler::genericHandleTm(const char* contextString, const uint8_t* data, + LocalPoolDataSetBase& set) { + 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); + nextReplyId = supv::EXE_REPORT; + return result; +} + +void PlocSupervisorHandler::setNextReplyId() { + switch (getPendingCommand()) { + case supv::GET_HK_REPORT: + nextReplyId = supv::HK_REPORT; + break; + case supv::GET_BOOT_STATUS_REPORT: + nextReplyId = supv::BOOT_STATUS_REPORT; + break; + case supv::GET_LATCHUP_STATUS_REPORT: + nextReplyId = supv::LATCHUP_REPORT; + break; + case supv::FIRST_MRAM_DUMP: + nextReplyId = supv::FIRST_MRAM_DUMP; + break; + case supv::CONSECUTIVE_MRAM_DUMP: + nextReplyId = supv::CONSECUTIVE_MRAM_DUMP; + break; + case supv::REQUEST_LOGGING_COUNTERS: + nextReplyId = supv::COUNTERS_REPORT; + break; + case supv::REQUEST_ADC_REPORT: + nextReplyId = supv::ADC_REPORT; + break; + default: + /* If no telemetry is expected the next reply is always the execution report */ + nextReplyId = supv::EXE_REPORT; + break; + } +} + +size_t PlocSupervisorHandler::getNextReplyLength(DeviceCommandId_t commandId) { + size_t replyLen = 0; + + if (nextReplyId == supv::NONE) { + return replyLen; + } + + if (nextReplyId == supv::FIRST_MRAM_DUMP || nextReplyId == supv::CONSECUTIVE_MRAM_DUMP) { + /** + * Try to read 20 MRAM packets. If reply is larger, the packets will be read with the + * next doSendRead call. The command will be as long active as the packet with the sequence + * count indicating the last packet has not been received. + */ + replyLen = supv::MAX_PACKET_SIZE * 20; + return replyLen; + } + + DeviceReplyIter iter = deviceReplyMap.find(nextReplyId); + if (iter != deviceReplyMap.end()) { + if ((iter->second.delayCycles == 0 && iter->second.countdown == nullptr) || + (not iter->second.active && iter->second.countdown != nullptr)) { + /* Reply inactive */ + return replyLen; + } + replyLen = iter->second.replyLen; + } else { + sif::debug << "PlocSupervisorHandler::getNextReplyLength: No entry for reply with reply id " + << std::hex << nextReplyId << " in deviceReplyMap" << std::endl; + } + + return replyLen; +} + +void PlocSupervisorHandler::doOffActivity() {} + +void PlocSupervisorHandler::handleDeviceTm(const uint8_t* data, size_t dataSize, + DeviceCommandId_t replyId) { + ReturnValue_t result = returnvalue::OK; + + if (wiretappingMode == RAW) { + /* Data already sent in doGetRead() */ + return; + } + + DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId); + if (iter == deviceReplyMap.end()) { + sif::debug << "PlocSupervisorHandler::handleDeviceTM: Unknown reply id" << std::endl; + return; + } + MessageQueueId_t queueId = iter->second.command->second.sendReplyTo; + + if (queueId == NO_COMMANDER) { + return; + } + + result = actionHelper.reportData(queueId, replyId, data, dataSize); + if (result != returnvalue::OK) { + sif::debug << "PlocSupervisorHandler::handleDeviceTM: Failed to report data" << std::endl; + } +} + +ReturnValue_t PlocSupervisorHandler::prepareEmptyCmd(uint16_t apid, uint8_t serviceId) { + supv::NoPayloadPacket packet(spParams, apid, serviceId); + ReturnValue_t result = packet.buildPacket(); + if (result != returnvalue::OK) { + return result; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::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; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::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; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::prepareDisableHk() { + supv::DisablePeriodicHkTransmission packet(spParams); + ReturnValue_t result = packet.buildPacket(); + if (result != returnvalue::OK) { + return result; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::prepareSetBootTimeoutCmd(const uint8_t* commandData) { + 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; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::prepareRestartTriesCmd(const uint8_t* commandData) { + uint8_t restartTries = *(commandData); + supv::SetRestartTries packet(spParams); + ReturnValue_t result = packet.buildPacket(restartTries); + if (result != returnvalue::OK) { + return result; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::prepareLatchupConfigCmd(const uint8_t* commandData, + DeviceCommandId_t deviceCommand) { + ReturnValue_t result = returnvalue::OK; + 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; + } + finishTcPrep(packet); + break; + } + case (supv::DISABLE_LATCHUP_ALERT): { + supv::LatchupAlert packet(spParams); + result = packet.buildPacket(false, latchupId); + if (result != returnvalue::OK) { + return result; + } + finishTcPrep(packet); + break; + } + default: { + sif::debug << "PlocSupervisorHandler::prepareLatchupConfigCmd: Invalid command id" + << std::endl; + result = returnvalue::FAILED; + break; + } + } + return result; +} + +ReturnValue_t PlocSupervisorHandler::prepareSetAlertLimitCmd(const uint8_t* commandData) { + 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; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::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; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::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; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::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; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::prepareRunAutoEmTest(const uint8_t* commandData) { + uint8_t test = *commandData; + if (test != 1 && test != 2) { + return result::INVALID_TEST_PARAM; + } + supv::RunAutoEmTests packet(spParams); + ReturnValue_t result = packet.buildPacket(test); + if (result != returnvalue::OK) { + return result; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +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); + supv::SetGpio packet(spParams); + ReturnValue_t result = packet.buildPacket(port, pin, val); + if (result != returnvalue::OK) { + return result; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +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); + ReturnValue_t result = packet.buildPacket(port, pin); + if (result != returnvalue::OK) { + return result; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::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; + } + finishTcPrep(resetCmd); + return returnvalue::OK; +} + +void PlocSupervisorHandler::finishTcPrep(TcBase& tc) { + nextReplyId = supv::ACK_REPORT; + rawPacket = commandBuffer; + rawPacketLen = tc.getFullPacketLen(); + if (DEBUG_PLOC_SUPV) { + sif::debug << "PLOC SUPV: SEND PACKET Size " << tc.getFullPacketLen() << " Module APID " + << (int)tc.getModuleApid() << " Service ID " << (int)tc.getServiceId() << std::endl; + } +} + +ReturnValue_t PlocSupervisorHandler::prepareSetShutdownTimeoutCmd(const uint8_t* commandData) { + 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; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +void PlocSupervisorHandler::disableAllReplies() { + using namespace supv; + DeviceReplyMap::iterator iter; + + /* Disable ack reply */ + iter = deviceReplyMap.find(ACK_REPORT); + if (iter == deviceReplyMap.end()) { + return; + } + DeviceReplyInfo* info = &(iter->second); + if (info == nullptr) { + return; + } + info->delayCycles = 0; + info->command = deviceCommandMap.end(); + + DeviceCommandId_t commandId = getPendingCommand(); + + /* If the command expects a telemetry packet the appropriate tm reply will be disabled here */ + switch (commandId) { + case GET_HK_REPORT: { + disableReply(GET_HK_REPORT); + break; + } + case FIRST_MRAM_DUMP: + case CONSECUTIVE_MRAM_DUMP: { + disableReply(commandId); + break; + } + case REQUEST_ADC_REPORT: { + disableReply(ADC_REPORT); + break; + } + case GET_BOOT_STATUS_REPORT: { + disableReply(BOOT_STATUS_REPORT); + break; + } + case GET_LATCHUP_STATUS_REPORT: { + disableReply(LATCHUP_REPORT); + break; + } + case REQUEST_LOGGING_COUNTERS: { + disableReply(COUNTERS_REPORT); + break; + } + default: { + break; + } + } + + /* We must always disable the execution report reply here */ + disableExeReportReply(); +} + +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; + info->command = deviceCommandMap.end(); +} + +void PlocSupervisorHandler::sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status) { + DeviceReplyIter iter = deviceReplyMap.find(replyId); + + if (iter == deviceReplyMap.end()) { + sif::debug << "PlocSupervisorHandler::sendFailureReport: Reply not in reply map" << std::endl; + return; + } + + DeviceCommandInfo* info = &(iter->second.command->second); + + if (info == nullptr) { + sif::debug << "PlocSupervisorHandler::sendFailureReport: Reply has no active command" + << std::endl; + return; + } + + if (info->sendReplyTo != NO_COMMANDER) { + actionHelper.finish(false, info->sendReplyTo, iter->first, status); + } + info->isExecuting = false; +} + +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(); + info->active = false; + /* Expected replies is set to one here. The value will set to 0 in replyToReply() */ + info->command->second.expectedReplies = 1; +} + +ReturnValue_t PlocSupervisorHandler::handleMramDumpPacket(DeviceCommandId_t id) { + ReturnValue_t result = returnvalue::FAILED; + + // Prepare packet for downlink + if (packetInBuffer) { + uint16_t packetLen = readSpacePacketLength(spacePacketBuffer); + result = verifyPacket(spacePacketBuffer, ccsds::HEADER_LEN + packetLen + 1); + if (result != returnvalue::OK) { + sif::warning << "PlocSupervisorHandler::handleMramDumpPacket: CRC failure" << std::endl; + return result; + } + result = handleMramDumpFile(id); + if (result != returnvalue::OK) { + DeviceCommandMap::iterator iter = deviceCommandMap.find(id); + if (iter != deviceCommandMap.end()) { + actionHelper.finish(false, iter->second.sendReplyTo, id, result); + } + disableAllReplies(); + nextReplyId = supv::NONE; + return result; + } + packetInBuffer = false; + receivedMramDumpPackets++; + if (expectedMramDumpPackets == receivedMramDumpPackets) { + nextReplyId = supv::EXE_REPORT; + } + increaseExpectedMramReplies(id); + return returnvalue::OK; + } + return result; +} + +void PlocSupervisorHandler::increaseExpectedMramReplies(DeviceCommandId_t id) { + DeviceReplyMap::iterator mramDumpIter = deviceReplyMap.find(id); + DeviceReplyMap::iterator exeReportIter = deviceReplyMap.find(supv::EXE_REPORT); + if (mramDumpIter == deviceReplyMap.end()) { + sif::debug << "PlocSupervisorHandler::increaseExpectedMramReplies: Dump MRAM reply not " + << "in reply map" << std::endl; + return; + } + if (exeReportIter == deviceReplyMap.end()) { + sif::debug << "PlocSupervisorHandler::increaseExpectedMramReplies: Execution report not " + << "in reply map" << std::endl; + return; + } + DeviceReplyInfo* mramReplyInfo = &(mramDumpIter->second); + if (mramReplyInfo == nullptr) { + sif::debug << "PlocSupervisorHandler::increaseExpectedReplies: MRAM reply info nullptr" + << std::endl; + return; + } + DeviceReplyInfo* exeReplyInfo = &(exeReportIter->second); + if (exeReplyInfo == nullptr) { + sif::debug << "PlocSupervisorHandler::increaseExpectedReplies: Execution reply info" + << " nullptr" << std::endl; + return; + } + DeviceCommandInfo* info = &(mramReplyInfo->command->second); + if (info == nullptr) { + sif::debug << "PlocSupervisorHandler::increaseExpectedReplies: Command info nullptr" + << std::endl; + return; + } + uint8_t sequenceFlags = spacePacketBuffer[2] >> 6; + if (sequenceFlags != static_cast(ccsds::SequenceFlags::LAST_SEGMENT) && + (sequenceFlags != static_cast(ccsds::SequenceFlags::UNSEGMENTED))) { + // Command expects at least one MRAM packet more and the execution report + info->expectedReplies = 2; + mramReplyInfo->countdown->resetTimer(); + } else { + // Command expects the execution report + info->expectedReplies = 1; + mramReplyInfo->active = false; + } + exeReplyInfo->countdown->resetTimer(); + return; +} + +ReturnValue_t PlocSupervisorHandler::handleMramDumpFile(DeviceCommandId_t id) { +#ifdef XIPHOS_Q7S + if (not sdcMan->getActiveSdCard()) { + return HasFileSystemIF::FILESYSTEM_INACTIVE; + } +#endif + ReturnValue_t result = returnvalue::OK; + uint16_t packetLen = readSpacePacketLength(spacePacketBuffer); + uint8_t sequenceFlags = readSequenceFlags(spacePacketBuffer); + if (id == supv::FIRST_MRAM_DUMP) { + if (sequenceFlags == static_cast(ccsds::SequenceFlags::FIRST_SEGMENT) || + (sequenceFlags == static_cast(ccsds::SequenceFlags::UNSEGMENTED))) { + result = createMramDumpFile(); + if (result != returnvalue::OK) { + return result; + } + } + } + if (not std::filesystem::exists(activeMramFile)) { + sif::warning << "PlocSupervisorHandler::handleMramDumpFile: MRAM file does not exist" + << std::endl; + return result::MRAM_FILE_NOT_EXISTS; + } + std::ofstream file(activeMramFile, std::ios_base::app | std::ios_base::out); + file.write(reinterpret_cast(spacePacketBuffer + ccsds::HEADER_LEN), packetLen - 1); + file.close(); + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::prepareWipeMramCmd(const uint8_t* commandData) { + 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; + } + finishTcPrep(packet); + return returnvalue::OK; +} + +uint16_t PlocSupervisorHandler::readSpacePacketLength(uint8_t* spacePacket) { + return spacePacket[4] << 8 | spacePacket[5]; +} + +uint8_t PlocSupervisorHandler::readSequenceFlags(uint8_t* spacePacket) { + return spacePacketBuffer[2] >> 6; +} + +ReturnValue_t PlocSupervisorHandler::createMramDumpFile() { + ReturnValue_t result = returnvalue::OK; + std::string timeStamp; + result = getTimeStampString(timeStamp); + if (result != returnvalue::OK) { + return result; + } + + std::string filename = "mram-dump--" + timeStamp + ".bin"; + +#ifdef XIPHOS_Q7S + const char* currentMountPrefix = sdcMan->getCurrentMountPrefix(); +#else + const char* currentMountPrefix = "/mnt/sd0"; +#endif /* BOARD_TE0720 == 0 */ + if (currentMountPrefix == nullptr) { + return returnvalue::FAILED; + } + + // Check if path to PLOC directory exists + if (not std::filesystem::exists(std::string(currentMountPrefix) + "/" + supervisorFilePath)) { + sif::warning << "PlocSupervisorHandler::createMramDumpFile: Supervisor path does not exist" + << std::endl; + return result::PATH_DOES_NOT_EXIST; + } + activeMramFile = std::string(currentMountPrefix) + "/" + supervisorFilePath + "/" + filename; + // Create new file + std::ofstream file(activeMramFile, std::ios_base::out); + file.close(); + + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::getTimeStampString(std::string& timeStamp) { + Clock::TimeOfDay_t time; + ReturnValue_t result = Clock::getDateAndTime(&time); + if (result != returnvalue::OK) { + sif::warning << "PlocSupervisorHandler::getTimeStampString: Failed to get current time" + << std::endl; + return result::GET_TIME_FAILURE; + } + timeStamp = std::to_string(time.year) + "-" + std::to_string(time.month) + "-" + + std::to_string(time.day) + "--" + std::to_string(time.hour) + "-" + + std::to_string(time.minute) + "-" + std::to_string(time.second); + return returnvalue::OK; +} + +ReturnValue_t PlocSupervisorHandler::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 PlocSupervisorHandler::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; +} + +ReturnValue_t PlocSupervisorHandler::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 PlocSupervisorHandler::handleExecutionSuccessReport(ExecutionReport& report) { + DeviceCommandId_t commandId = getPendingCommand(); + 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 + 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 */ + if (iter != deviceCommandMap.end() and iter->second.sendReplyTo == NO_COMMAND_ID) { + return returnvalue::OK; + } + 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(iter->second.sendReplyTo, 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: { + // We could only allow proper bootup when the time was set successfully, but + // this makes debugging difficult. + + if (startupState == StartupState::WAIT_FOR_TIME_REPLY) { + startupState = StartupState::TIME_WAS_SET; + } + break; + } + default: + break; + } + return returnvalue::OK; +} + +void PlocSupervisorHandler::handleExecutionFailureReport(ExecutionReport& report) { + using namespace supv; + DeviceCommandId_t commandId = getPendingCommand(); + report.printStatusInformation(); + if (commandId != DeviceHandlerIF::NO_COMMAND_ID) { + triggerEvent(SUPV_EXE_FAILURE, commandId, static_cast(report.getStatusCode())); + } + sendFailureReport(EXE_REPORT, result::RECEIVED_EXE_FAILURE); + disableExeReportReply(); +} + +void PlocSupervisorHandler::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 PlocSupervisorHandler::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; + } +} + +ReturnValue_t PlocSupervisorHandler::getSwitches(const uint8_t** switches, + uint8_t* numberOfSwitches) { + if (powerSwitch == power::NO_SWITCH) { + return DeviceHandlerBase::NO_SWITCH; + } + *numberOfSwitches = 1; + *switches = &powerSwitch; + return returnvalue::OK; +} + +uint32_t PlocSupervisorHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { + 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) { + 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; + } + } + } + return DeviceHandlerBase::checkModeCommand(commandedMode, commandedSubmode, msToReachTheMode); +} diff --git a/linux/payload/PlocSupervisorHandler.h b/linux/payload/PlocSupervisorHandler.h new file mode 100644 index 00000000..14051c22 --- /dev/null +++ b/linux/payload/PlocSupervisorHandler.h @@ -0,0 +1,386 @@ +#ifndef MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ +#define MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ + +#include +#include +#include + +#include "OBSWConfig.h" +#include "devices/powerSwitcherList.h" +#include "fsfw/devicehandlers/DeviceHandlerBase.h" +#include "fsfw/timemanager/Countdown.h" +#include "fsfw_hal/linux/gpio/Gpio.h" +#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h" +#include "fsfw_hal/linux/serial/SerialComIF.h" + +#ifdef XIPHOS_Q7S +#include "bsp_q7s/fs/SdCardManager.h" +#endif + +using supv::ExecutionReport; +using supv::TcBase; + +/** + * @brief This is the device handler for the supervisor of the PLOC which is programmed by + * Thales. + * + * @details The PLOC uses the space packet protocol for communication. On each command the PLOC + * answers with at least one acknowledgment and one execution report. + * Flight manual: + * https://egit.irs.uni-stuttgart.de/redmine/projects/eive-flight-manual/wiki/PLOC_Commands + * ILH ICD: https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/ + * Arbeitsdaten/08_Used%20Components/PLOC&fileid=940960 + * @author J. Meier + */ +class PlocSupervisorHandler : public DeviceHandlerBase { + public: + PlocSupervisorHandler(object_id_t objectId, CookieIF* comCookie, Gpio uartIsolatorSwitch, + power::Switch_t powerSwitch, PlocSupvUartManager& supvHelper); + virtual ~PlocSupervisorHandler(); + + virtual ReturnValue_t initialize() override; + void performOperationHook() override; + ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) override; + + protected: + void doStartUp() override; + void doShutDown() override; + ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t* id) override; + ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t* id) override; + void fillCommandAndReplyMap() override; + ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t* commandData, + size_t commandDataLen) override; + ReturnValue_t scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId, + size_t* foundLen) override; + ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) override; + uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; + ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; + ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator command, + uint8_t expectedReplies = 1, bool useAlternateId = false, + DeviceCommandId_t alternateReplyID = 0) override; + size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override; + // ReturnValue_t doSendReadHook() override; + void doOffActivity() override; + + private: + static const uint16_t APID_MASK = 0x7FF; + static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF; + static const uint8_t EXE_STATUS_OFFSET = 10; + static const uint8_t SIZE_NULL_TERMINATOR = 1; + // 5 s + static const uint32_t EXECUTION_DEFAULT_TIMEOUT = 5000; + // 70 S + 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; + + enum class StartupState : uint8_t { + OFF, + BOOTING, + SET_TIME, + WAIT_FOR_TIME_REPLY, + TIME_WAS_SET, + ON + }; + + static constexpr bool SET_TIME_DURING_BOOT = true; + + StartupState startupState = StartupState::OFF; + + uint8_t commandBuffer[supv::MAX_COMMAND_SIZE]; + SpacePacketCreator creator; + supv::TcParams spParams = supv::TcParams(creator); + + /** + * This variable is used to store the id of the next reply to receive. This is necessary + * because the PLOC sends as reply to each command at least one acknowledgment and execution + * report. + */ + DeviceCommandId_t nextReplyId = supv::NONE; + + SerialComIF* uartComIf = nullptr; + 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::CountersReport countersReport; + supv::AdcReport adcReport; + + const power::Switch_t powerSwitch = power::NO_SWITCH; + supv::TmBase tmReader; + + PlocSupvUartManager& uartManager; + MessageQueueIF* eventQueue = nullptr; + + /** Number of expected replies following the MRAM dump command */ + uint32_t expectedMramDumpPackets = 0; + uint32_t receivedMramDumpPackets = 0; + /** Set to true as soon as a complete space packet is present in the spacePacketBuffer */ + bool packetInBuffer = false; + + /** This buffer is used to concatenate space packets received in two different read steps */ + uint8_t spacePacketBuffer[supv::MAX_PACKET_SIZE]; + +#ifdef XIPHOS_Q7S + SdCardManager* sdcMan = nullptr; +#endif + + // Path to supervisor specific files on SD card + std::string supervisorFilePath = "ploc/supervisor"; + std::string activeMramFile; + + Countdown executionReportTimeout = Countdown(EXECUTION_DEFAULT_TIMEOUT, false); + Countdown acknowledgementReportTimeout = Countdown(ACKNOWLEDGE_DEFAULT_TIMEOUT, false); + // Vorago nees some time to boot properly + 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); + PoolEntry tempSupEntry = PoolEntry(1); + + /** + * @brief Adjusts the timeout of the execution report dependent on command + */ + void setExecutionTimeout(DeviceCommandId_t command); + + void handlePacketPrint(); + + /** + * @brief Handles event messages received from the supervisor helper + */ + void handleEvent(EventMessage* eventMessage); + + ReturnValue_t getSwitches(const uint8_t** switches, uint8_t* numberOfSwitches); + + /** + * @brief This function checks the crc of the received PLOC reply. + * + * @param start Pointer to the first byte of the reply. + * @param foundLen Pointer to the length of the whole packet. + * + * @return returnvalue::OK if CRC is ok, otherwise CRC_FAILURE. + */ + ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen); + + /** + * @brief This function handles the acknowledgment report. + * + * @param data Pointer to the data holding the acknowledgment report. + * + * @return returnvalue::OK if successful, otherwise an error code. + */ + ReturnValue_t handleAckReport(const uint8_t* data); + + /** + * @brief This function handles the data of a execution report. + * + * @param data Pointer to the received data packet. + * + * @return returnvalue::OK if successful, otherwise an error code. + */ + ReturnValue_t handleExecutionReport(const uint8_t* data); + + /** + * @brief This function handles the housekeeping report. This means verifying the CRC of the + * reply and filling the appropriate dataset. + * + * @param data Pointer to the data buffer holding the housekeeping read report. + * + * @return returnvalue::OK if successful, otherwise an error code. + */ + ReturnValue_t handleHkReport(const uint8_t* data); + + /** + * @brief This function calls the function to check the CRC of the received boot status report + * and fills the associated dataset with the boot status information. + */ + 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 + * next reply after a successful acknowledgment report has been received. This is + * required by the function getNextReplyLength() to identify the length of the next + * reply to read. + */ + void setNextReplyId(); + + /** + * @brief This function handles action message replies in case the telemetry has been + * requested by another object. + * + * @param data Pointer to the telemetry data. + * @param dataSize Size of telemetry in bytes. + * @param replyId Id of the reply. This will be added to the ActionMessage. + */ + void handleDeviceTm(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId); + + /** + * @brief This function prepares a space packet which does not transport any data in the + * packet data field apart from the crc. + */ + ReturnValue_t prepareEmptyCmd(uint16_t apid, uint8_t serviceId); + + /** + * @brief This function initializes the space packet to select the boot image of the MPSoC. + */ + ReturnValue_t prepareSelBootImageCmd(const uint8_t* commandData); + + ReturnValue_t prepareDisableHk(); + + /** + * @brief This function fills the commandBuffer with the data to update the time of the + * PLOC supervisor. + */ + ReturnValue_t prepareSetTimeRefCmd(); + + /** + * @brief This function fills the commandBuffer with the data to change the boot timeout + * value in the PLOC supervisor. + */ + ReturnValue_t prepareSetBootTimeoutCmd(const uint8_t* commandData); + + ReturnValue_t prepareRestartTriesCmd(const uint8_t* commandData); + + ReturnValue_t prepareFactoryResetCmd(const uint8_t* commandData, size_t len); + + /** + * @brief This function fills the command buffer with the packet to enable or disable the + * watchdogs on the PLOC. + */ + void prepareWatchdogsEnableCmd(const uint8_t* commandData); + + /** + * @brief This function fills the command buffer with the packet to set the watchdog timer + * of one of the three watchdogs (PS, PL, INT). + */ + ReturnValue_t prepareWatchdogsConfigTimeoutCmd(const uint8_t* commandData); + + ReturnValue_t prepareLatchupConfigCmd(const uint8_t* commandData, + DeviceCommandId_t deviceCommand); + ReturnValue_t prepareSetAlertLimitCmd(const uint8_t* commandData); + ReturnValue_t prepareSetAdcEnabledChannelsCmd(const uint8_t* commandData); + ReturnValue_t prepareSetAdcWindowAndStrideCmd(const uint8_t* commandData); + 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, 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. + */ + void finishTcPrep(TcBase& tc); + + /** + * @brief In case an acknowledgment failure reply has been received this function disables + * all previously enabled commands and resets the exepected replies variable of an + * active command. + */ + void disableAllReplies(); + + void disableReply(DeviceCommandId_t replyId); + + /** + * @brief This function sends a failure report if the active action was commanded by an other + * object. + * + * @param replyId The id of the reply which signals a failure. + * @param status A status byte which gives information about the failure type. + */ + void sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status); + + /** + * @brief This function disables the execution report reply. Within this function also the + * the variable expectedReplies of an active command will be set to 0. + */ + void disableExeReportReply(); + + /** + * @brief This function generates the Service 8 packets for the MRAM dump data. + */ + ReturnValue_t handleMramDumpPacket(DeviceCommandId_t id); + + /** + * @brief With this function the number of expected replies following an MRAM dump command + * will be increased. This is necessary to release the command in case not all replies + * have been received. + */ + void increaseExpectedMramReplies(DeviceCommandId_t id); + + /** + * @brief Writes the data of the MRAM dump to a file. The file will be created when receiving + * the first packet. + */ + ReturnValue_t handleMramDumpFile(DeviceCommandId_t id); + + /** + * @brief Extracts the length field of a spacePacket referenced by the spacePacket pointer. + * + * @param spacePacket Pointer to the buffer holding the space packet. + * + * @return The value stored in the length field of the data field. + */ + uint16_t readSpacePacketLength(uint8_t* spacePacket); + + /** + * @brief Extracts the sequence flags from a space packet referenced by the spacePacket + * pointer. + * + * @param spacePacket Pointer to the buffer holding the space packet. + * + * @return uint8_t where the two least significant bits hold the sequence flags. + */ + uint8_t readSequenceFlags(uint8_t* spacePacket); + + ReturnValue_t createMramDumpFile(); + ReturnValue_t getTimeStampString(std::string& timeStamp); + + ReturnValue_t prepareSetShutdownTimeoutCmd(const uint8_t* commandData); + + 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); + ReturnValue_t eventSubscription(); + + ReturnValue_t handleExecutionSuccessReport(ExecutionReport& report); + void handleExecutionFailureReport(ExecutionReport& report); + + void printAckFailureInfo(uint16_t statusCode, DeviceCommandId_t commandId); + + pwrctrl::EnablePl enablePl = pwrctrl::EnablePl(objects::POWER_CONTROLLER); + ReturnValue_t checkModeCommand(Mode_t commandedMode, Submode_t commandedSubmode, + uint32_t* msToReachTheMode) override; +}; + +#endif /* MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ */ diff --git a/linux/payload/PlocSupvUartMan.cpp b/linux/payload/PlocSupvUartMan.cpp index b53a5f32..dc5aab27 100644 --- a/linux/payload/PlocSupvUartMan.cpp +++ b/linux/payload/PlocSupvUartMan.cpp @@ -45,12 +45,10 @@ PlocSupvUartManager::PlocSupvUartManager(object_id_t objectId) PlocSupvUartManager::~PlocSupvUartManager() = default; ReturnValue_t PlocSupvUartManager::initializeInterface(CookieIF* cookie) { - sif::debug << "init ploc supv uart IF" << std::endl; auto* uartCookie = dynamic_cast(cookie); if (uartCookie == nullptr) { return FAILED; } - sif::debug << "hello blub" << std::endl; std::string devname = uartCookie->getDeviceFile(); /* Get file descriptor */ serialPort = open(devname.c_str(), O_RDWR); @@ -72,7 +70,7 @@ ReturnValue_t PlocSupvUartManager::initializeInterface(CookieIF* cookie) { tty.c_lflag &= ~(ICANON | ECHO); // Blocking mode, 0.2 seconds timeout - tty.c_cc[VTIME] = 0; + tty.c_cc[VTIME] = 2; tty.c_cc[VMIN] = 0; serial::setBaudrate(tty, uartCookie->getBaudrate()); @@ -82,7 +80,7 @@ ReturnValue_t PlocSupvUartManager::initializeInterface(CookieIF* cookie) { } // Flush received and unread data tcflush(serialPort, TCIOFLUSH); - sif::debug << "ploc supv cfg complete" << std::endl; + sif::debug << "piece of shit port " << serialPort << std::endl; return OK; } @@ -117,7 +115,6 @@ ReturnValue_t PlocSupvUartManager::performOperation(uint8_t operationCode) { lock->lockMutex(); InternalState currentState = state; lock->unlockMutex(); - sif::debug << "supv uart man post-lock" << std::endl; switch (currentState) { case InternalState::SLEEPING: case InternalState::GO_TO_SLEEP: { @@ -143,7 +140,7 @@ ReturnValue_t PlocSupvUartManager::performOperation(uint8_t operationCode) { ReturnValue_t PlocSupvUartManager::handleUartReception() { ReturnValue_t result = OK; ReturnValue_t status = OK; - sif::debug << "handling uart reception" << std::endl; + sif::debug << "reading port " << serialPort << std::endl; ssize_t bytesRead = read(serialPort, reinterpret_cast(recBuf.data()), static_cast(recBuf.size())); if (bytesRead == 0) { diff --git a/linux/payload/PlocSupvUartMan.h b/linux/payload/PlocSupvUartMan.h index e5d01f70..69f938b0 100644 --- a/linux/payload/PlocSupvUartMan.h +++ b/linux/payload/PlocSupvUartMan.h @@ -231,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; diff --git a/linux/payload/plocSupvDefs.h b/linux/payload/plocSupvDefs.h index c7fa3ae7..a87d25a3 100644 --- a/linux/payload/plocSupvDefs.h +++ b/linux/payload/plocSupvDefs.h @@ -17,6 +17,9 @@ namespace supv { +static constexpr bool DEBUG_PLOC_SUPV = true; +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 diff --git a/mission/pollingSeqTables.cpp b/mission/pollingSeqTables.cpp index 8bd0bb86..7c953461 100644 --- a/mission/pollingSeqTables.cpp +++ b/mission/pollingSeqTables.cpp @@ -627,6 +627,13 @@ ReturnValue_t pst::pstPayload(FixedTimeslotTaskIF *thisSequence) { FreshSupvHandler::OpCode::PARSE_TM); thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.2, FreshSupvHandler::OpCode::PARSE_TM); + + /* + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0, DeviceHandlerIF::GET_READ); + */ static_cast(length); return thisSequence->checkSequence(); From 4f6a59470712b3eba82284b5f894d8bb95c05051 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 14 Nov 2023 18:37:09 +0100 Subject: [PATCH 18/69] OOPS --- linux/payload/FreshSupvHandler.cpp | 4 +--- linux/payload/PlocSupvUartMan.cpp | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 581dd348..36195152 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -549,9 +549,7 @@ ReturnValue_t FreshSupvHandler::initialize() { if (result != returnvalue::OK) { return result; } - result = FreshDeviceHandlerBase::initialize(); - sif::debug << "serial port: " << uartManager.serialPort << std::endl; - return result; + return FreshDeviceHandlerBase::initialize(); } ReturnValue_t FreshSupvHandler::sendEmptyCmd(uint16_t apid, uint8_t serviceId, bool replyExpected) { diff --git a/linux/payload/PlocSupvUartMan.cpp b/linux/payload/PlocSupvUartMan.cpp index dc5aab27..b0f61713 100644 --- a/linux/payload/PlocSupvUartMan.cpp +++ b/linux/payload/PlocSupvUartMan.cpp @@ -80,7 +80,6 @@ ReturnValue_t PlocSupvUartManager::initializeInterface(CookieIF* cookie) { } // Flush received and unread data tcflush(serialPort, TCIOFLUSH); - sif::debug << "piece of shit port " << serialPort << std::endl; return OK; } From 193c45ee33d2ba087bf1674aab165ae40edba1d4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Nov 2023 08:48:31 +0100 Subject: [PATCH 19/69] another small fix --- linux/payload/FreshSupvHandler.cpp | 4 ++-- linux/payload/FreshSupvHandler.h | 2 +- linux/payload/PlocMpsocHandler.cpp | 4 ++-- linux/payload/PlocSupvUartMan.cpp | 6 +++++- tmtc | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 36195152..4feaa1a2 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -74,6 +74,7 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { 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(); sendEmptyCmd(Apid::HK, static_cast(tc::HkId::GET_REPORT), true); } } @@ -192,8 +193,6 @@ ReturnValue_t FreshSupvHandler::initializeLocalDataPool(localpool::DataPool& loc ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size) { - // TODO: Handle all commands here. Need to add them to some command map. Send command immediately - // then. using namespace supv; ReturnValue_t result; if (uartManager.longerRequestActive()) { @@ -478,6 +477,7 @@ void FreshSupvHandler::handleTransitionToOn() { } } 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; diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index 0cf56487..9a960a60 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -116,7 +116,7 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { struct ActiveCmdInfo { ActiveCmdInfo(uint32_t cmdCountdownMs) : cmdCountdown(cmdCountdownMs) {} - DeviceCommandId_t commandId; + DeviceCommandId_t commandId = DeviceHandlerIF::NO_COMMAND_ID; bool isPending = false; bool ackRecv = false; bool ackExeRecv = false; diff --git a/linux/payload/PlocMpsocHandler.cpp b/linux/payload/PlocMpsocHandler.cpp index 34053c70..b5bcb78c 100644 --- a/linux/payload/PlocMpsocHandler.cpp +++ b/linux/payload/PlocMpsocHandler.cpp @@ -20,9 +20,9 @@ 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); + eventQueue = QueueFactory::instance()->createMessageQueue(10); commandActionHelperQueue = - QueueFactory::instance()->createMessageQueue(EventMessage::EVENT_MESSAGE_SIZE * 5); + QueueFactory::instance()->createMessageQueue(10); spParams.maxSize = sizeof(commandBuffer); spParams.buf = commandBuffer; } diff --git a/linux/payload/PlocSupvUartMan.cpp b/linux/payload/PlocSupvUartMan.cpp index b0f61713..475e611b 100644 --- a/linux/payload/PlocSupvUartMan.cpp +++ b/linux/payload/PlocSupvUartMan.cpp @@ -80,6 +80,7 @@ ReturnValue_t PlocSupvUartManager::initializeInterface(CookieIF* cookie) { } // Flush received and unread data tcflush(serialPort, TCIOFLUSH); + sif::debug << "serial port: " << serialPort << std::endl; return OK; } @@ -140,7 +141,8 @@ ReturnValue_t PlocSupvUartManager::handleUartReception() { ReturnValue_t result = OK; ReturnValue_t status = OK; sif::debug << "reading port " << serialPort << std::endl; - ssize_t bytesRead = read(serialPort, reinterpret_cast(recBuf.data()), + TaskFactory::delayTask(100); + ssize_t bytesRead = read(302, reinterpret_cast(recBuf.data()), static_cast(recBuf.size())); if (bytesRead == 0) { while (result != NO_PACKET_FOUND) { @@ -968,6 +970,8 @@ ReturnValue_t PlocSupvUartManager::encodeAndSendPacket(const uint8_t* sendData, sif::debug << "Sending TC" << std::endl; arrayprinter::print(encodedSendBuf.data(), encodedLen); } + sif::debug << "writing to serial port: " << serialPort << std::endl; + TaskFactory::delayTask(50); size_t bytesWritten = write(serialPort, encodedSendBuf.data(), encodedLen); if (bytesWritten != encodedLen) { sif::warning diff --git a/tmtc b/tmtc index c4bd3551..07b13c15 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit c4bd355146a2f5894a93a30f0c7f61aeef43e764 +Subproject commit 07b13c153dab03c35ea3c7921f68c6ba77049d1e From bd74b95ffd19b02f1799151dd4c5e6ce30d30958 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Nov 2023 11:31:57 +0100 Subject: [PATCH 20/69] on and normal mode finally work --- bsp_q7s/objectFactory.cpp | 15 +- fsfw | 2 +- linux/payload/CMakeLists.txt | 1 - linux/payload/FreshSupvHandler.cpp | 152 +- linux/payload/FreshSupvHandler.h | 16 +- linux/payload/PlocMpsocHandler.cpp | 3 +- linux/payload/PlocMpsocSpecialComHelper.cpp | 2 +- linux/payload/PlocSupervisorHandler.cpp | 2027 ------------------- linux/payload/PlocSupervisorHandler.h | 386 ---- linux/payload/PlocSupvUartMan.cpp | 56 +- linux/payload/PlocSupvUartMan.h | 4 +- linux/payload/plocSupvDefs.h | 53 +- mission/payload/plocSpBase.h | 4 - 13 files changed, 152 insertions(+), 2569 deletions(-) delete mode 100644 linux/payload/PlocSupervisorHandler.cpp delete mode 100644 linux/payload/PlocSupervisorHandler.h diff --git a/bsp_q7s/objectFactory.cpp b/bsp_q7s/objectFactory.cpp index 4a9d3080..e4474bb8 100644 --- a/bsp_q7s/objectFactory.cpp +++ b/bsp_q7s/objectFactory.cpp @@ -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,18 +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); - + new PlocSupvUartManager(objects::PLOC_SUPERVISOR_HELPER); DhbConfig dhbConf(objects::PLOC_SUPERVISOR_HANDLER); auto* supvHandler = new FreshSupvHandler(dhbConf, supervisorCookie, Gpio(gpioIds::ENABLE_SUPV_UART, gpioComIF), - pwrSwitch, power::PDU1_CH6_PLOC_12V, *supvHelper); - /* - auto* supvHandler = new PlocSupervisorHandler(objects::PLOC_SUPERVISOR_HANDLER, supervisorCookie, - Gpio(gpioIds::ENABLE_SUPV_UART, gpioComIF), - power::PDU1_CH6_PLOC_12V, *supvHelper); - supvHandler->setPowerSwitcher(&pwrSwitch); - */ + pwrSwitcher, power::PDU1_CH6_PLOC_12V); supvHandler->connectModeTreeParent(satsystem::payload::SUBSYSTEM); #endif /* OBSW_ADD_PLOC_SUPERVISOR == 1 */ static_cast(consumer); diff --git a/fsfw b/fsfw index 91b194d8..7673d8b3 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 91b194d8ebd79352ad358f955274d49f15dd3e6d +Subproject commit 7673d8b396764186d93c3378496ccfc3c1b2e2e8 diff --git a/linux/payload/CMakeLists.txt b/linux/payload/CMakeLists.txt index 2def0752..48fb9d96 100644 --- a/linux/payload/CMakeLists.txt +++ b/linux/payload/CMakeLists.txt @@ -3,7 +3,6 @@ target_sources( PUBLIC PlocMemoryDumper.cpp PlocMpsocHandler.cpp FreshSupvHandler.cpp - PlocSupervisorHandler.cpp PlocMpsocSpecialComHelper.cpp plocMpsocHelpers.cpp PlocSupvUartMan.cpp diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 4feaa1a2..8fbce1da 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -7,8 +7,10 @@ #include #include "eive/definitions.h" +#include "eive/objects.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" @@ -19,10 +21,8 @@ using namespace returnvalue; std::atomic_bool supv::SUPV_ON = false; FreshSupvHandler::FreshSupvHandler(DhbConfig cfg, CookieIF* comCookie, Gpio uartIsolatorSwitch, - PowerSwitchIF& switchIF, power::Switch_t powerSwitch, - PlocSupvUartManager& supvHelper) + PowerSwitchIF& switchIF, power::Switch_t powerSwitch) : FreshDeviceHandlerBase(cfg), - uartManager(supvHelper), comCookie(comCookie), switchIF(switchIF), switchId(powerSwitch), @@ -75,7 +75,8 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { buildActiveCmdKey(Apid::HK, static_cast(tc::HkId::GET_REPORT))); if (cmdIter == activeActionCmds.end() or not cmdIter->second.isPending) { spParams.buf = commandBuffer.data(); - sendEmptyCmd(Apid::HK, static_cast(tc::HkId::GET_REPORT), true); + sendEmptyCmd(supv::GET_HK_REPORT, Apid::HK, static_cast(tc::HkId::GET_REPORT), + true); } } } @@ -195,7 +196,7 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI const uint8_t* data, size_t size) { using namespace supv; ReturnValue_t result; - if (uartManager.longerRequestActive()) { + if (uartManager->longerRequestActive()) { return result::SUPV_HELPER_EXECUTING; } @@ -209,14 +210,14 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI if (result != returnvalue::OK) { return result; } - result = uartManager.performUpdate(params); + result = uartManager->performUpdate(params); if (result != returnvalue::OK) { return result; } return EXECUTION_FINISHED; } case CONTINUE_UPDATE: { - uartManager.initiateUpdateContinuation(); + uartManager->initiateUpdateContinuation(); return EXECUTION_FINISHED; } case MEMORY_CHECK_WITH_FILE: { @@ -228,7 +229,7 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI if (not std::filesystem::exists(params.file)) { return HasFileSystemIF::FILE_DOES_NOT_EXIST; } - uartManager.performMemCheck(params.file, params.memId, params.startAddr); + uartManager->performMemCheck(params.file, params.memId, params.startAddr); return EXECUTION_FINISHED; } default: @@ -240,19 +241,21 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI spParams.buf = commandBuffer.data(); switch (actionId) { case GET_HK_REPORT: { - sendEmptyCmd(Apid::HK, static_cast(tc::HkId::GET_REPORT), true); + 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(Apid::BOOT_MAN, static_cast(tc::BootManId::START_MPSOC), false); + 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(Apid::BOOT_MAN, static_cast(tc::BootManId::SHUTDOWN_MPSOC), false); + sendEmptyCmd(supv::SHUTDOWN_MPSOC, Apid::BOOT_MAN, + static_cast(tc::BootManId::SHUTDOWN_MPSOC), false); result = returnvalue::OK; break; } @@ -263,7 +266,8 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI } case RESET_MPSOC: { sif::info << "PLOC SUPV: Resetting MPSoC" << std::endl; - sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::RESET_MPSOC), false); + sendEmptyCmd(supv::RESET_MPSOC, Apid::BOOT_MAN, + static_cast(tc::BootManId::RESET_MPSOC), false); result = returnvalue::OK; break; } @@ -287,8 +291,8 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI break; } case GET_BOOT_STATUS_REPORT: { - sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::GET_BOOT_STATUS_REPORT), - true); + sendEmptyCmd(supv::GET_BOOT_STATUS_REPORT, Apid::BOOT_MAN, + static_cast(tc::BootManId::GET_BOOT_STATUS_REPORT), true); result = returnvalue::OK; break; } @@ -305,8 +309,8 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI break; } case GET_LATCHUP_STATUS_REPORT: { - sendEmptyCmd(Apid::LATCHUP_MON, static_cast(tc::LatchupMonId::GET_STATUS_REPORT), - true); + sendEmptyCmd(supv::GET_LATCHUP_STATUS_REPORT, Apid::LATCHUP_MON, + static_cast(tc::LatchupMonId::GET_STATUS_REPORT), true); result = returnvalue::OK; break; } @@ -328,12 +332,14 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI break; } case FACTORY_FLASH: { - sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::FACTORY_FLASH), false); + sendEmptyCmd(supv::FACTORY_FLASH, Apid::BOOT_MAN, + static_cast(tc::BootManId::FACTORY_FLASH), false); result = returnvalue::OK; break; } case RESET_PL: { - sendEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::RESET_PL), false); + sendEmptyCmd(supv::RESET_PL, Apid::BOOT_MAN, static_cast(tc::BootManId::RESET_PL), + false); result = returnvalue::OK; break; } @@ -357,12 +363,13 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI break; } case REQUEST_ADC_REPORT: { - sendEmptyCmd(Apid::ADC_MON, static_cast(tc::AdcMonId::REQUEST_ADC_SAMPLE), true); + 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(Apid::DATA_LOGGER, + sendEmptyCmd(supv::REQUEST_LOGGING_COUNTERS, Apid::DATA_LOGGER, static_cast(tc::DataLoggerServiceId::REQUEST_COUNTERS), true); result = returnvalue::OK; break; @@ -389,7 +396,7 @@ ReturnValue_t FreshSupvHandler::prepareSetTimeRefCmd() { if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + sendCommand(supv::SET_TIME_REF, packet, false); return returnvalue::OK; } @@ -424,12 +431,13 @@ ReturnValue_t FreshSupvHandler::prepareSelBootImageCmd(const uint8_t* commandDat if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + 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)) { + 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; @@ -469,7 +477,7 @@ void FreshSupvHandler::handleTransitionToOn() { } if (startupState == StartupState::BOOTING and bootTimeout.hasTimedOut()) { uartIsolatorSwitch.pullHigh(); - uartManager.start(); + uartManager->start(); if (SET_TIME_DURING_BOOT) { startupState = StartupState::SET_TIME; } else { @@ -501,7 +509,7 @@ void FreshSupvHandler::handleTransitionToOff() { if (shutdownState == ShutdownState::IDLE) { hkSet.setReportingEnabled(false); hkSet.setValidity(false, true); - uartManager.stop(); + uartManager->stop(); uartIsolatorSwitch.pullLow(); switchIF.sendSwitchCommand(switchId, PowerSwitchIF::SWITCH_OFF); shutdownState = ShutdownState::POWER_SWITCHING; @@ -515,13 +523,13 @@ void FreshSupvHandler::handleTransitionToOff() { } } -ReturnValue_t FreshSupvHandler::sendCommand(TcBase& tc, bool replyExpected, - uint32_t cmdCountdownMs) { +ReturnValue_t FreshSupvHandler::sendCommand(DeviceCommandId_t commandId, TcBase& tc, + bool replyExpected, uint32_t cmdCountdownMs) { if (supv::DEBUG_PLOC_SUPV) { sif::debug << "PLOC SUPV: SEND PACKET Size " << tc.getFullPacketLen() << " Module APID " << (int)tc.getModuleApid() << " Service ID " << (int)tc.getServiceId() << std::endl; } - ActiveCmdInfo info(cmdCountdownMs); + ActiveCmdInfo info(commandId, cmdCountdownMs); auto activeCmdIter = activeActionCmds.find(buildActiveCmdKey(tc.getModuleApid(), tc.getServiceId())); if (activeCmdIter == activeActionCmds.end()) { @@ -532,6 +540,7 @@ ReturnValue_t FreshSupvHandler::sendCommand(TcBase& tc, bool replyExpected, return HasActionsIF::IS_BUSY; } activeCmdIter->second.isPending = true; + activeCmdIter->second.commandId = commandId; activeCmdIter->second.ackRecv = false; activeCmdIter->second.ackExeRecv = false; activeCmdIter->second.replyPacketExpected = replyExpected; @@ -539,11 +548,16 @@ ReturnValue_t FreshSupvHandler::sendCommand(TcBase& tc, bool replyExpected, activeCmdIter->second.cmdCountdown.setTimeout(cmdCountdownMs); activeCmdIter->second.cmdCountdown.resetTimer(); } - return uartManager.sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen()); + return uartManager->sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen()); } ReturnValue_t FreshSupvHandler::initialize() { - uartManager.initializeInterface(comCookie); + 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) { @@ -552,13 +566,14 @@ ReturnValue_t FreshSupvHandler::initialize() { return FreshDeviceHandlerBase::initialize(); } -ReturnValue_t FreshSupvHandler::sendEmptyCmd(uint16_t apid, uint8_t serviceId, bool replyExpected) { +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(packet, replyExpected); + sendCommand(commandId, packet, replyExpected); return returnvalue::OK; } @@ -574,7 +589,7 @@ ReturnValue_t FreshSupvHandler::prepareSetBootTimeoutCmd(const uint8_t* commandD if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + sendCommand(supv::SET_BOOT_TIMEOUT, packet, false); return returnvalue::OK; } @@ -589,7 +604,7 @@ ReturnValue_t FreshSupvHandler::prepareRestartTriesCmd(const uint8_t* commandDat if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + sendCommand(supv::ENABLE_AUTO_TM, packet, false); return returnvalue::OK; } @@ -599,7 +614,7 @@ ReturnValue_t FreshSupvHandler::prepareDisableHk() { if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + sendCommand(supv::DISABLE_AUTO_TM, packet, false); return returnvalue::OK; } @@ -621,7 +636,7 @@ ReturnValue_t FreshSupvHandler::prepareLatchupConfigCmd(const uint8_t* commandDa if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + sendCommand(deviceCommand, packet, false); break; } case (supv::DISABLE_LATCHUP_ALERT): { @@ -630,7 +645,7 @@ ReturnValue_t FreshSupvHandler::prepareLatchupConfigCmd(const uint8_t* commandDa if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + sendCommand(deviceCommand, packet, false); break; } default: { @@ -661,7 +676,7 @@ ReturnValue_t FreshSupvHandler::prepareSetAlertLimitCmd(const uint8_t* commandDa if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + sendCommand(supv::SET_ALERT_LIMIT, packet, false); return returnvalue::OK; } @@ -686,7 +701,7 @@ ReturnValue_t FreshSupvHandler::prepareSetShutdownTimeoutCmd(const uint8_t* comm if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + sendCommand(supv::SET_SHUTDOWN_TIMEOUT, packet, false); return returnvalue::OK; } @@ -703,7 +718,7 @@ ReturnValue_t FreshSupvHandler::prepareSetGpioCmd(const uint8_t* commandData, if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + sendCommand(supv::SET_GPIO, packet, false); return returnvalue::OK; } @@ -719,7 +734,7 @@ ReturnValue_t FreshSupvHandler::prepareReadGpioCmd(const uint8_t* commandData, if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + sendCommand(supv::READ_GPIO, packet, false); return returnvalue::OK; } @@ -732,7 +747,7 @@ ReturnValue_t FreshSupvHandler::prepareFactoryResetCmd(const uint8_t* commandDat if (result != returnvalue::OK) { return result; } - sendCommand(resetCmd, false); + sendCommand(supv::FACTORY_RESET, resetCmd, false); return returnvalue::OK; } @@ -743,7 +758,7 @@ ReturnValue_t FreshSupvHandler::prepareSetAdcEnabledChannelsCmd(const uint8_t* c if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + sendCommand(supv::SET_ADC_ENABLED_CHANNELS, packet, false); return returnvalue::OK; } @@ -757,7 +772,7 @@ ReturnValue_t FreshSupvHandler::prepareSetAdcWindowAndStrideCmd(const uint8_t* c if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + sendCommand(supv::SET_ADC_WINDOW_AND_STRIDE, packet, false); return returnvalue::OK; } @@ -769,7 +784,7 @@ ReturnValue_t FreshSupvHandler::prepareSetAdcThresholdCmd(const uint8_t* command if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + sendCommand(supv::SET_ADC_THRESHOLD, packet, false); return returnvalue::OK; } @@ -790,7 +805,7 @@ ReturnValue_t FreshSupvHandler::prepareWipeMramCmd(const uint8_t* commandData, s if (result != returnvalue::OK) { return result; } - sendCommand(packet, false); + sendCommand(supv::WIPE_MRAM, packet, false); return returnvalue::OK; } @@ -798,11 +813,16 @@ ReturnValue_t FreshSupvHandler::parseTmPackets() { uint8_t* receivedData = nullptr; size_t receivedSize = 0; while (true) { - ReturnValue_t result = uartManager.readReceivedMessage(comCookie, &receivedData, &receivedSize); + ReturnValue_t result = + uartManager->readReceivedMessage(comCookie, &receivedData, &receivedSize); if (result != returnvalue::OK or receivedSize == 0) { break; } - tmReader.setData(receivedData, receivedSize); + tmReader.setReadOnlyData(receivedData, receivedSize); + if (tmReader.checkCrc() != returnvalue::OK) { + sif::warning << "PlocSupervisorHandler::parseTmPackets: CRC failure" << std::endl; + continue; + } uint16_t apid = tmReader.getModuleApid(); if (supv::DEBUG_PLOC_SUPV) { handlePacketPrint(); @@ -892,9 +912,17 @@ void FreshSupvHandler::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(); + ReturnValue_t result = ack.parse(false); if (result != returnvalue::OK) { - sif::warning << "PlocSupervisorHandler: Parsing ACK failed" << std::endl; + 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 (supv::REDUCE_NORMAL_MODE_PRINTOUT and ack.getRefModuleApid() == (uint8_t)supv::Apid::HK and @@ -915,7 +943,7 @@ void FreshSupvHandler::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(); + ReturnValue_t result = exe.parse(false); if (result != returnvalue::OK) { sif::warning << "PlocSupervisorHandler: Parsing EXE failed" << std::endl; } @@ -1092,13 +1120,8 @@ ReturnValue_t FreshSupvHandler::eventSubscription() { ReturnValue_t FreshSupvHandler::handleAckReport(const uint8_t* data) { using namespace supv; ReturnValue_t result = returnvalue::OK; - if (not tmReader.verifyCrc()) { - sif::error << "PlocSupervisorHandler::handleAckReport: CRC failure" << std::endl; - triggerEvent(SUPV_CRC_FAILURE_EVENT); - return returnvalue::FAILED; - } AcknowledgmentReport ack(tmReader); - result = ack.parse(); + result = ack.parse(false); if (result != returnvalue::OK) { return result; } @@ -1111,7 +1134,7 @@ ReturnValue_t FreshSupvHandler::handleAckReport(const uint8_t* data) { ActiveCmdInfo& info = infoIter->second; if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::NAK)) { triggerEvent(SUPV_ACK_FAILURE, info.commandId, static_cast(ack.getStatusCode())); - ack.printStatusInformation(); + ack.printStatusInformationAck(); printAckFailureInfo(ack.getStatusCode(), info.commandId); if (info.commandedBy != MessageQueueIF::NO_QUEUE) { actionHelper.finish(false, info.commandedBy, info.commandId, result::RECEIVED_ACK_FAILURE); @@ -1129,7 +1152,9 @@ void FreshSupvHandler::performCommandCompletionHandling(supv::Apid apid, uint8_t ActiveCmdInfo& info) { if (info.ackRecv and info.ackExeRecv and (not info.replyPacketExpected or info.replyPacketReceived)) { - actionHelper.finish(true, info.commandedBy, info.commandId, returnvalue::OK); + if (info.commandedBy != MessageQueueIF::NO_QUEUE) { + actionHelper.finish(true, info.commandedBy, info.commandId, returnvalue::OK); + } info.isPending = false; } } @@ -1154,13 +1179,10 @@ uint32_t FreshSupvHandler::buildActiveCmdKey(uint16_t moduleApid, uint8_t servic ReturnValue_t FreshSupvHandler::handleExecutionReport(const uint8_t* data) { using namespace supv; ReturnValue_t result = returnvalue::OK; - - if (not tmReader.verifyCrc()) { - return result::CRC_FAILURE; - } ExecutionReport exe(tmReader); - result = exe.parse(); + result = exe.parse(false); if (result != OK) { + sif::warning << "FreshSupvHandler::handleExecutionReport: Parsing ACK EXE failed" << std::endl; return result; } auto infoIter = @@ -1219,7 +1241,7 @@ ReturnValue_t FreshSupvHandler::handleExecutionSuccessReport(ActiveCmdInfo& info void FreshSupvHandler::handleExecutionFailureReport(ActiveCmdInfo& info, ExecutionReport& report) { using namespace supv; - report.printStatusInformation(); + report.printStatusInformationExe(); if (info.commandId != DeviceHandlerIF::NO_COMMAND_ID) { triggerEvent(SUPV_EXE_FAILURE, info.commandId, static_cast(report.getStatusCode())); } diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index 9a960a60..be968564 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -22,8 +22,7 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { enum OpCode { DEFAULT_OPERATION = 0, PARSE_TM = 1 }; FreshSupvHandler(DhbConfig cfg, CookieIF* comCookie, Gpio uartIsolatorSwitch, - PowerSwitchIF& switchIF, power::Switch_t powerSwitch, - PlocSupvUartManager& supvHelper); + PowerSwitchIF& switchIF, power::Switch_t powerSwitch); /** * Periodic helper executed function, implemented by child class. */ @@ -82,7 +81,7 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { enum class ShutdownState : uint8_t { IDLE, POWER_SWITCHING }; ShutdownState shutdownState = ShutdownState::IDLE; - PlocSupvUartManager uartManager; + PlocSupvUartManager* uartManager; CookieIF* comCookie; PowerSwitchIF& switchIF; power::Switch_t switchId; @@ -114,7 +113,8 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { pwrctrl::EnablePl enablePl = pwrctrl::EnablePl(objects::POWER_CONTROLLER); struct ActiveCmdInfo { - ActiveCmdInfo(uint32_t cmdCountdownMs) : cmdCountdown(cmdCountdownMs) {} + ActiveCmdInfo(DeviceCommandId_t commandId, uint32_t cmdCountdownMs) + : commandId(commandId), cmdCountdown(cmdCountdownMs) {} DeviceCommandId_t commandId = DeviceHandlerIF::NO_COMMAND_ID; bool isPending = false; @@ -132,14 +132,16 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { // Map for Action commands. For normal commands, a separate static structure will be used. std::map activeActionCmds; - std::array commandBuffer; + std::array commandBuffer{}; SpacePacketCreator creator; supv::TcParams spParams = supv::TcParams(creator); ReturnValue_t parseTmPackets(); - ReturnValue_t sendCommand(TcBase& tc, bool replyPacketExpected, uint32_t cmdCountdownMs = 1000); - ReturnValue_t sendEmptyCmd(uint16_t apid, uint8_t serviceId, bool replyPacketExpected); + 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); diff --git a/linux/payload/PlocMpsocHandler.cpp b/linux/payload/PlocMpsocHandler.cpp index b5bcb78c..05b3a04e 100644 --- a/linux/payload/PlocMpsocHandler.cpp +++ b/linux/payload/PlocMpsocHandler.cpp @@ -21,8 +21,7 @@ PlocMpsocHandler::PlocMpsocHandler(object_id_t objectId, object_id_t uartComIFid sif::error << "PlocMPSoCHandler: Invalid communication cookie" << std::endl; } eventQueue = QueueFactory::instance()->createMessageQueue(10); - commandActionHelperQueue = - 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/PlocSupervisorHandler.cpp b/linux/payload/PlocSupervisorHandler.cpp deleted file mode 100644 index 67ec707f..00000000 --- a/linux/payload/PlocSupervisorHandler.cpp +++ /dev/null @@ -1,2027 +0,0 @@ -#include "PlocSupervisorHandler.h" - -#include -#include -#include - -#include -#include -#include -#include - -#include "OBSWConfig.h" -#include "eive/definitions.h" -#include "fsfw/datapool/PoolReadGuard.h" -#include "fsfw/globalfunctions/CRC.h" -#include "fsfw/ipc/QueueFactory.h" -#include "fsfw/timemanager/Clock.h" - -using namespace supv; -using namespace returnvalue; - -PlocSupervisorHandler::PlocSupervisorHandler(object_id_t objectId, CookieIF* comCookie, - Gpio uartIsolatorSwitch, power::Switch_t powerSwitch, - PlocSupvUartManager& supvHelper) - : DeviceHandlerBase(objectId, supvHelper.getObjectId(), comCookie), - uartIsolatorSwitch(uartIsolatorSwitch), - hkset(this), - bootStatusReport(this), - latchupStatusReport(this), - countersReport(this), - adcReport(this), - powerSwitch(powerSwitch), - uartManager(supvHelper) { - if (comCookie == nullptr) { - sif::error << "PlocSupervisorHandler: Invalid com cookie" << std::endl; - } - spParams.buf = commandBuffer; - spParams.maxSize = sizeof(commandBuffer); - eventQueue = QueueFactory::instance()->createMessageQueue(EventMessage::EVENT_MESSAGE_SIZE * 5); -} - -PlocSupervisorHandler::~PlocSupervisorHandler() {} - -ReturnValue_t PlocSupervisorHandler::initialize() { - ReturnValue_t result = returnvalue::OK; - result = DeviceHandlerBase::initialize(); - if (result != returnvalue::OK) { - return result; - } -#ifdef XIPHOS_Q7S - sdcMan = SdCardManager::instance(); -#endif /* TE0720_1CFA */ - - result = eventSubscription(); - if (result != returnvalue::OK) { - return result; - } - return result; -} - -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)) { - 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; - } - } -} - -ReturnValue_t PlocSupervisorHandler::executeAction(ActionId_t actionId, - MessageQueueId_t commandedBy, - const uint8_t* data, size_t size) { - using namespace supv; - ReturnValue_t result = returnvalue::OK; - - switch (actionId) { - default: - break; - } - - if (uartManager.longerRequestActive()) { - return result::SUPV_HELPER_EXECUTING; - } - - result = acceptExternalDeviceCommands(); - if (result != returnvalue::OK) { - return result; - } - - switch (actionId) { - case PERFORM_UPDATE: { - if (size > config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE) { - return result::FILENAME_TOO_LONG; - } - shutdownCmdSent = false; - 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: { - shutdownCmdSent = false; - uartManager.initiateUpdateContinuation(); - return EXECUTION_FINISHED; - } - case MEMORY_CHECK_WITH_FILE: { - shutdownCmdSent = false; - 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; - } - return DeviceHandlerBase::executeAction(actionId, commandedBy, data, size); -} - -void PlocSupervisorHandler::doStartUp() { - if (startupState == StartupState::OFF) { - bootTimeout.resetTimer(); - startupState = StartupState::BOOTING; - } - if (startupState == StartupState::BOOTING) { - if (bootTimeout.hasTimedOut()) { - uartIsolatorSwitch.pullHigh(); - uartManager.start(); - if (SET_TIME_DURING_BOOT) { - startupState = StartupState::SET_TIME; - } else { - startupState = StartupState::ON; - } - } - } - if (startupState == StartupState::TIME_WAS_SET) { - startupState = StartupState::ON; - } - if (startupState == StartupState::ON) { - hkset.setReportingEnabled(true); - supv::SUPV_ON = true; - setMode(_MODE_TO_ON); - } -} - -void PlocSupervisorHandler::doShutDown() { - setMode(_MODE_POWER_DOWN); - hkset.setReportingEnabled(false); - hkset.setValidity(false, true); - shutdownCmdSent = false; - packetInBuffer = false; - nextReplyId = supv::NONE; - uartManager.stop(); - uartIsolatorSwitch.pullLow(); - disableAllReplies(); - supv::SUPV_ON = false; - startupState = StartupState::OFF; -} - -ReturnValue_t PlocSupervisorHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { - if (not normalCommandIsPending) { - *id = GET_HK_REPORT; - normalCommandIsPending = true; - normalCmdCd.resetTimer(); - return buildCommandFromCommand(*id, nullptr, 0); - } - return NOTHING_TO_SEND; -} - -ReturnValue_t PlocSupervisorHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { - if (startupState == StartupState::SET_TIME) { - *id = supv::SET_TIME_REF; - startupState = StartupState::WAIT_FOR_TIME_REPLY; - return buildCommandFromCommand(*id, nullptr, 0); - } - return NOTHING_TO_SEND; -} - -ReturnValue_t PlocSupervisorHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand, - const uint8_t* commandData, - size_t commandDataLen) { - using namespace supv; - ReturnValue_t result = returnvalue::FAILED; - spParams.buf = commandBuffer; - switch (deviceCommand) { - case GET_HK_REPORT: { - prepareEmptyCmd(Apid::HK, static_cast(tc::HkId::GET_REPORT)); - result = returnvalue::OK; - break; - } - case START_MPSOC: { - sif::info << "PLOC SUPV: Starting MPSoC" << std::endl; - prepareEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::START_MPSOC)); - result = returnvalue::OK; - break; - } - case SHUTDOWN_MPSOC: { - sif::info << "PLOC SUPV: Shutting down MPSoC" << std::endl; - prepareEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::SHUTDOWN_MPSOC)); - result = returnvalue::OK; - break; - } - case SEL_MPSOC_BOOT_IMAGE: { - prepareSelBootImageCmd(commandData); - result = returnvalue::OK; - break; - } - case RESET_MPSOC: { - sif::info << "PLOC SUPV: Resetting MPSoC" << std::endl; - prepareEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::RESET_MPSOC)); - result = returnvalue::OK; - break; - } - case SET_TIME_REF: { - result = prepareSetTimeRefCmd(); - break; - } - case SET_BOOT_TIMEOUT: { - prepareSetBootTimeoutCmd(commandData); - result = returnvalue::OK; - break; - } - case SET_MAX_RESTART_TRIES: { - prepareRestartTriesCmd(commandData); - result = returnvalue::OK; - break; - } - case DISABLE_PERIOIC_HK_TRANSMISSION: { - prepareDisableHk(); - result = returnvalue::OK; - break; - } - case GET_BOOT_STATUS_REPORT: { - prepareEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::GET_BOOT_STATUS_REPORT)); - result = returnvalue::OK; - break; - } - case ENABLE_LATCHUP_ALERT: { - result = prepareLatchupConfigCmd(commandData, deviceCommand); - break; - } - case DISABLE_LATCHUP_ALERT: { - result = prepareLatchupConfigCmd(commandData, deviceCommand); - break; - } - case SET_ALERT_LIMIT: { - result = prepareSetAlertLimitCmd(commandData); - break; - } - case GET_LATCHUP_STATUS_REPORT: { - prepareEmptyCmd(Apid::LATCHUP_MON, static_cast(tc::LatchupMonId::GET_STATUS_REPORT)); - result = returnvalue::OK; - break; - } - case RUN_AUTO_EM_TESTS: { - result = prepareRunAutoEmTest(commandData); - break; - } - case SET_GPIO: { - result = prepareSetGpioCmd(commandData, commandDataLen); - break; - } - case FACTORY_RESET: { - result = prepareFactoryResetCmd(commandData, commandDataLen); - break; - } - case READ_GPIO: { - result = prepareReadGpioCmd(commandData, commandDataLen); - break; - } - case SET_SHUTDOWN_TIMEOUT: { - prepareSetShutdownTimeoutCmd(commandData); - result = returnvalue::OK; - break; - } - case FACTORY_FLASH: { - prepareEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::FACTORY_FLASH)); - result = returnvalue::OK; - break; - } - case RESET_PL: { - prepareEmptyCmd(Apid::BOOT_MAN, static_cast(tc::BootManId::RESET_PL)); - result = returnvalue::OK; - break; - } - case SET_ADC_ENABLED_CHANNELS: { - prepareSetAdcEnabledChannelsCmd(commandData); - result = returnvalue::OK; - break; - } - case SET_ADC_WINDOW_AND_STRIDE: { - prepareSetAdcWindowAndStrideCmd(commandData); - result = returnvalue::OK; - break; - } - case SET_ADC_THRESHOLD: { - prepareSetAdcThresholdCmd(commandData); - result = returnvalue::OK; - break; - } - case WIPE_MRAM: { - 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; -} - -void PlocSupervisorHandler::fillCommandAndReplyMap() { - // Command only - insertInCommandMap(GET_HK_REPORT); - insertInCommandMap(START_MPSOC); - insertInCommandMap(SHUTDOWN_MPSOC); - insertInCommandMap(SEL_MPSOC_BOOT_IMAGE); - insertInCommandMap(SET_BOOT_TIMEOUT); - insertInCommandMap(SET_MAX_RESTART_TRIES); - insertInCommandMap(RESET_MPSOC); - insertInCommandMap(WIPE_MRAM); - insertInCommandMap(SET_TIME_REF); - insertInCommandMap(DISABLE_PERIOIC_HK_TRANSMISSION); - insertInCommandMap(GET_BOOT_STATUS_REPORT); - insertInCommandMap(ENABLE_LATCHUP_ALERT); - insertInCommandMap(DISABLE_LATCHUP_ALERT); - insertInCommandMap(SET_ALERT_LIMIT); - insertInCommandMap(GET_LATCHUP_STATUS_REPORT); - insertInCommandMap(RUN_AUTO_EM_TESTS); - insertInCommandMap(SET_GPIO); - insertInCommandMap(READ_GPIO); - insertInCommandMap(FACTORY_RESET); - insertInCommandMap(MEMORY_CHECK); - insertInCommandMap(SET_SHUTDOWN_TIMEOUT); - insertInCommandMap(FACTORY_FLASH); - insertInCommandMap(SET_ADC_ENABLED_CHANNELS); - 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); - insertInReplyMap(EXE_REPORT, 0, nullptr, SIZE_EXE_REPORT, false, &executionReportTimeout); - insertInReplyMap(MEMORY_CHECK, 5, nullptr, 0, false); - - // TM replies - 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(COUNTERS_REPORT, 3, &countersReport, SIZE_COUNTERS_REPORT); - insertInReplyMap(ADC_REPORT, 3, &adcReport, SIZE_ADC_REPORT); -} - -ReturnValue_t PlocSupervisorHandler::enableReplyInReplyMap(DeviceCommandMap::iterator command, - uint8_t expectedReplies, - bool useAlternateId, - DeviceCommandId_t alternateReplyID) { - ReturnValue_t result = OK; - - uint8_t enabledReplies = 0; - - switch (command->first) { - case GET_HK_REPORT: { - enabledReplies = 3; - result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, HK_REPORT); - if (result != returnvalue::OK) { - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " << HK_REPORT - << " not in replyMap" << std::endl; - } - break; - } - case GET_BOOT_STATUS_REPORT: { - enabledReplies = 3; - result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, - BOOT_STATUS_REPORT); - if (result != returnvalue::OK) { - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " - << BOOT_STATUS_REPORT << " not in replyMap" << std::endl; - } - break; - } - case GET_LATCHUP_STATUS_REPORT: { - enabledReplies = 3; - result = - DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, LATCHUP_REPORT); - if (result != returnvalue::OK) { - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " - << LATCHUP_REPORT << " not in replyMap" << std::endl; - } - break; - } - case REQUEST_LOGGING_COUNTERS: { - enabledReplies = 3; - result = - DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, COUNTERS_REPORT); - if (result != returnvalue::OK) { - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " - << COUNTERS_REPORT << " not in replyMap" << std::endl; - } - break; - } - case REQUEST_ADC_REPORT: { - enabledReplies = 3; - result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, ADC_REPORT); - if (result != returnvalue::OK) { - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " << ADC_REPORT - << " not in replyMap" << std::endl; - } - break; - } - case FIRST_MRAM_DUMP: { - enabledReplies = 2; // expected replies will be increased in handleMramDumpPacket - result = - DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, FIRST_MRAM_DUMP); - if (result != returnvalue::OK) { - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " - << FIRST_MRAM_DUMP << " not in replyMap" << std::endl; - } - break; - } - case CONSECUTIVE_MRAM_DUMP: { - enabledReplies = 2; // expected replies will be increased in handleMramDumpPacket - result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, - CONSECUTIVE_MRAM_DUMP); - if (result != returnvalue::OK) { - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " - << CONSECUTIVE_MRAM_DUMP << " not in replyMap" << std::endl; - } - break; - } - case MEMORY_CHECK: { - enabledReplies = 3; - result = - DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, MEMORY_CHECK); - if (result != returnvalue::OK) { - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " << MEMORY_CHECK - << " not in replyMap" << std::endl; - } - break; - } - case START_MPSOC: - case SHUTDOWN_MPSOC: - case SEL_MPSOC_BOOT_IMAGE: - case SET_BOOT_TIMEOUT: - case SET_MAX_RESTART_TRIES: - case RESET_MPSOC: - case SET_TIME_REF: - case ENABLE_LATCHUP_ALERT: - case DISABLE_LATCHUP_ALERT: - case SET_ALERT_LIMIT: - case SET_ADC_ENABLED_CHANNELS: - case SET_ADC_WINDOW_AND_STRIDE: - case SET_ADC_THRESHOLD: - case RUN_AUTO_EM_TESTS: - case WIPE_MRAM: - case SET_GPIO: - case FACTORY_RESET: - case READ_GPIO: - case DISABLE_PERIOIC_HK_TRANSMISSION: - case SET_SHUTDOWN_TIMEOUT: - case FACTORY_FLASH: - case ENABLE_AUTO_TM: - case DISABLE_AUTO_TM: - case RESET_PL: - enabledReplies = 2; - break; - default: - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Unknown command id" << std::endl; - break; - } - - /** - * Every command causes at least one acknowledgment and one execution report. Therefore both - * replies will be enabled here. - */ - result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, ACK_REPORT); - if (result != returnvalue::OK) { - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " << ACK_REPORT - << " not in replyMap" << std::endl; - } - - setExecutionTimeout(command->first); - - result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, EXE_REPORT); - if (result != returnvalue::OK) { - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " << EXE_REPORT - << " not in replyMap" << std::endl; - } - - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::scanForReply(const uint8_t* start, size_t remainingSize, - DeviceCommandId_t* foundId, size_t* foundLen) { - using namespace supv; - - tmReader.setData(start, remainingSize); - uint16_t apid = tmReader.getModuleApid(); - if (DEBUG_PLOC_SUPV) { - handlePacketPrint(); - } - - switch (apid) { - case (Apid::TMTC_MAN): { - switch (tmReader.getServiceId()) { - case (static_cast(supv::tm::TmtcId::ACK)): - case (static_cast(supv::tm::TmtcId::NAK)): { - *foundLen = tmReader.getFullPacketLen(); - *foundId = ReplyId::ACK_REPORT; - return OK; - } - case (static_cast(supv::tm::TmtcId::EXEC_ACK)): - case (static_cast(supv::tm::TmtcId::EXEC_NAK)): { - *foundLen = tmReader.getFullPacketLen(); - *foundId = EXE_REPORT; - return OK; - } - } - break; - } - 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; - } 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)) { - *foundLen = tmReader.getFullPacketLen(); - *foundId = ReplyId::BOOT_STATUS_REPORT; - return OK; - } - 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)) { - *foundLen = tmReader.getFullPacketLen(); - *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()); - *foundLen = remainingSize; - return INVALID_DATA; -} - -void PlocSupervisorHandler::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(); - 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"; - - } 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(); - 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"; - - } 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; - } - } - sif::debug << "PlocSupervisorHandler: RECV PACKET Size " << tmReader.getFullPacketLen() - << " Module APID " << (int)tmReader.getModuleApid() << " Service ID " - << (int)tmReader.getServiceId() << std::endl; -} -ReturnValue_t PlocSupervisorHandler::interpretDeviceReply(DeviceCommandId_t id, - const uint8_t* packet) { - using namespace supv; - ReturnValue_t result = returnvalue::OK; - - switch (id) { - case ACK_REPORT: { - result = handleAckReport(packet); - break; - } - case (HK_REPORT): { - result = handleHkReport(packet); - break; - } - case (BOOT_STATUS_REPORT): { - 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 = genericHandleTm("ADC", packet, adcReport); -#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_PLOC_SUPERVISOR == 1 - adcReport.printSet(); -#endif - break; - } - case (EXE_REPORT): { - result = handleExecutionReport(packet); - break; - } - case (UPDATE_STATUS_REPORT): { - // TODO: handle status report here - break; - } - default: { - sif::debug << "PlocSupervisorHandler::interpretDeviceReply: Unknown device reply id" - << std::endl; - return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY; - } - } - - return result; -} - -ReturnValue_t PlocSupervisorHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, - LocalDataPoolManager& poolManager) { - 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_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; -} - -void PlocSupervisorHandler::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) { - // Wait for a short period for the uart state machine to adjust - // TaskFactory::delayTask(5); - if (not shutdownCmdSent) { - shutdownCmdSent = true; - result = this->executeAction(supv::SHUTDOWN_MPSOC, NO_COMMANDER, nullptr, 0); - if (result != returnvalue::OK) { - triggerEvent(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; - } -} - -void PlocSupervisorHandler::setExecutionTimeout(DeviceCommandId_t command) { - using namespace supv; - switch (command) { - case FIRST_MRAM_DUMP: - case CONSECUTIVE_MRAM_DUMP: - executionReportTimeout.setTimeout(MRAM_DUMP_EXECUTION_TIMEOUT); - break; - case COPY_ADC_DATA_TO_MRAM: - executionReportTimeout.setTimeout(COPY_ADC_TO_MRAM_TIMEOUT); - break; - default: - executionReportTimeout.setTimeout(EXECUTION_DEFAULT_TIMEOUT); - break; - } -} - -ReturnValue_t PlocSupervisorHandler::verifyPacket(const uint8_t* start, size_t foundLen) { - if (CRC::crc16ccitt(start, foundLen) != 0) { - return result::CRC_FAILURE; - } - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::handleAckReport(const uint8_t* data) { - using namespace supv; - ReturnValue_t result = returnvalue::OK; - - if (not tmReader.verifyCrc()) { - sif::error << "PlocSupervisorHandler::handleAckReport: CRC failure" << std::endl; - nextReplyId = supv::NONE; - replyRawReplyIfnotWiretapped(data, supv::SIZE_ACK_REPORT); - triggerEvent(SUPV_CRC_FAILURE_EVENT); - sendFailureReport(supv::ACK_REPORT, result::CRC_FAILURE); - disableAllReplies(); - return returnvalue::OK; - } - AcknowledgmentReport ack(tmReader); - result = ack.parse(); - if (result != returnvalue::OK) { - nextReplyId = supv::NONE; - replyRawReplyIfnotWiretapped(data, supv::SIZE_ACK_REPORT); - triggerEvent(SUPV_CRC_FAILURE_EVENT); - sendFailureReport(supv::ACK_REPORT, result); - disableAllReplies(); - return result; - } - if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::NAK)) { - DeviceCommandId_t commandId = getPendingCommand(); - if (commandId != DeviceHandlerIF::NO_COMMAND_ID) { - triggerEvent(SUPV_ACK_FAILURE, commandId, static_cast(ack.getStatusCode())); - } - ack.printStatusInformation(); - printAckFailureInfo(ack.getStatusCode(), commandId); - sendFailureReport(supv::ACK_REPORT, result::RECEIVED_ACK_FAILURE); - disableAllReplies(); - nextReplyId = supv::NONE; - result = IGNORE_REPLY_DATA; - } else if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::ACK)) { - setNextReplyId(); - } - return result; -} - -ReturnValue_t PlocSupervisorHandler::handleExecutionReport(const uint8_t* data) { - using namespace supv; - ReturnValue_t result = returnvalue::OK; - - if (not tmReader.verifyCrc()) { - nextReplyId = supv::NONE; - return result::CRC_FAILURE; - } - ExecutionReport report(tmReader); - result = report.parse(); - if (result != OK) { - nextReplyId = supv::NONE; - return result; - } - if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::EXEC_ACK)) { - result = handleExecutionSuccessReport(report); - } else if (tmReader.getServiceId() == static_cast(supv::tm::TmtcId::EXEC_NAK)) { - handleExecutionFailureReport(report); - } - commandIsPending = false; - nextReplyId = supv::NONE; - return result; -} - -ReturnValue_t PlocSupervisorHandler::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; - - nextReplyId = supv::EXE_REPORT; - hkset.setValidity(true, true); - -#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 PlocSupervisorHandler::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); - - nextReplyId = supv::EXE_REPORT; - bootStatusReport.setValidity(true, true); - -#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 PlocSupervisorHandler::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); - - nextReplyId = supv::EXE_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 PlocSupervisorHandler::genericHandleTm(const char* contextString, const uint8_t* data, - LocalPoolDataSetBase& set) { - 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); - nextReplyId = supv::EXE_REPORT; - return result; -} - -void PlocSupervisorHandler::setNextReplyId() { - switch (getPendingCommand()) { - case supv::GET_HK_REPORT: - nextReplyId = supv::HK_REPORT; - break; - case supv::GET_BOOT_STATUS_REPORT: - nextReplyId = supv::BOOT_STATUS_REPORT; - break; - case supv::GET_LATCHUP_STATUS_REPORT: - nextReplyId = supv::LATCHUP_REPORT; - break; - case supv::FIRST_MRAM_DUMP: - nextReplyId = supv::FIRST_MRAM_DUMP; - break; - case supv::CONSECUTIVE_MRAM_DUMP: - nextReplyId = supv::CONSECUTIVE_MRAM_DUMP; - break; - case supv::REQUEST_LOGGING_COUNTERS: - nextReplyId = supv::COUNTERS_REPORT; - break; - case supv::REQUEST_ADC_REPORT: - nextReplyId = supv::ADC_REPORT; - break; - default: - /* If no telemetry is expected the next reply is always the execution report */ - nextReplyId = supv::EXE_REPORT; - break; - } -} - -size_t PlocSupervisorHandler::getNextReplyLength(DeviceCommandId_t commandId) { - size_t replyLen = 0; - - if (nextReplyId == supv::NONE) { - return replyLen; - } - - if (nextReplyId == supv::FIRST_MRAM_DUMP || nextReplyId == supv::CONSECUTIVE_MRAM_DUMP) { - /** - * Try to read 20 MRAM packets. If reply is larger, the packets will be read with the - * next doSendRead call. The command will be as long active as the packet with the sequence - * count indicating the last packet has not been received. - */ - replyLen = supv::MAX_PACKET_SIZE * 20; - return replyLen; - } - - DeviceReplyIter iter = deviceReplyMap.find(nextReplyId); - if (iter != deviceReplyMap.end()) { - if ((iter->second.delayCycles == 0 && iter->second.countdown == nullptr) || - (not iter->second.active && iter->second.countdown != nullptr)) { - /* Reply inactive */ - return replyLen; - } - replyLen = iter->second.replyLen; - } else { - sif::debug << "PlocSupervisorHandler::getNextReplyLength: No entry for reply with reply id " - << std::hex << nextReplyId << " in deviceReplyMap" << std::endl; - } - - return replyLen; -} - -void PlocSupervisorHandler::doOffActivity() {} - -void PlocSupervisorHandler::handleDeviceTm(const uint8_t* data, size_t dataSize, - DeviceCommandId_t replyId) { - ReturnValue_t result = returnvalue::OK; - - if (wiretappingMode == RAW) { - /* Data already sent in doGetRead() */ - return; - } - - DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId); - if (iter == deviceReplyMap.end()) { - sif::debug << "PlocSupervisorHandler::handleDeviceTM: Unknown reply id" << std::endl; - return; - } - MessageQueueId_t queueId = iter->second.command->second.sendReplyTo; - - if (queueId == NO_COMMANDER) { - return; - } - - result = actionHelper.reportData(queueId, replyId, data, dataSize); - if (result != returnvalue::OK) { - sif::debug << "PlocSupervisorHandler::handleDeviceTM: Failed to report data" << std::endl; - } -} - -ReturnValue_t PlocSupervisorHandler::prepareEmptyCmd(uint16_t apid, uint8_t serviceId) { - supv::NoPayloadPacket packet(spParams, apid, serviceId); - ReturnValue_t result = packet.buildPacket(); - if (result != returnvalue::OK) { - return result; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::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; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::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; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::prepareDisableHk() { - supv::DisablePeriodicHkTransmission packet(spParams); - ReturnValue_t result = packet.buildPacket(); - if (result != returnvalue::OK) { - return result; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::prepareSetBootTimeoutCmd(const uint8_t* commandData) { - 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; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::prepareRestartTriesCmd(const uint8_t* commandData) { - uint8_t restartTries = *(commandData); - supv::SetRestartTries packet(spParams); - ReturnValue_t result = packet.buildPacket(restartTries); - if (result != returnvalue::OK) { - return result; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::prepareLatchupConfigCmd(const uint8_t* commandData, - DeviceCommandId_t deviceCommand) { - ReturnValue_t result = returnvalue::OK; - 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; - } - finishTcPrep(packet); - break; - } - case (supv::DISABLE_LATCHUP_ALERT): { - supv::LatchupAlert packet(spParams); - result = packet.buildPacket(false, latchupId); - if (result != returnvalue::OK) { - return result; - } - finishTcPrep(packet); - break; - } - default: { - sif::debug << "PlocSupervisorHandler::prepareLatchupConfigCmd: Invalid command id" - << std::endl; - result = returnvalue::FAILED; - break; - } - } - return result; -} - -ReturnValue_t PlocSupervisorHandler::prepareSetAlertLimitCmd(const uint8_t* commandData) { - 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; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::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; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::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; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::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; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::prepareRunAutoEmTest(const uint8_t* commandData) { - uint8_t test = *commandData; - if (test != 1 && test != 2) { - return result::INVALID_TEST_PARAM; - } - supv::RunAutoEmTests packet(spParams); - ReturnValue_t result = packet.buildPacket(test); - if (result != returnvalue::OK) { - return result; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -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); - supv::SetGpio packet(spParams); - ReturnValue_t result = packet.buildPacket(port, pin, val); - if (result != returnvalue::OK) { - return result; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -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); - ReturnValue_t result = packet.buildPacket(port, pin); - if (result != returnvalue::OK) { - return result; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::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; - } - finishTcPrep(resetCmd); - return returnvalue::OK; -} - -void PlocSupervisorHandler::finishTcPrep(TcBase& tc) { - nextReplyId = supv::ACK_REPORT; - rawPacket = commandBuffer; - rawPacketLen = tc.getFullPacketLen(); - if (DEBUG_PLOC_SUPV) { - sif::debug << "PLOC SUPV: SEND PACKET Size " << tc.getFullPacketLen() << " Module APID " - << (int)tc.getModuleApid() << " Service ID " << (int)tc.getServiceId() << std::endl; - } -} - -ReturnValue_t PlocSupervisorHandler::prepareSetShutdownTimeoutCmd(const uint8_t* commandData) { - 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; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -void PlocSupervisorHandler::disableAllReplies() { - using namespace supv; - DeviceReplyMap::iterator iter; - - /* Disable ack reply */ - iter = deviceReplyMap.find(ACK_REPORT); - if (iter == deviceReplyMap.end()) { - return; - } - DeviceReplyInfo* info = &(iter->second); - if (info == nullptr) { - return; - } - info->delayCycles = 0; - info->command = deviceCommandMap.end(); - - DeviceCommandId_t commandId = getPendingCommand(); - - /* If the command expects a telemetry packet the appropriate tm reply will be disabled here */ - switch (commandId) { - case GET_HK_REPORT: { - disableReply(GET_HK_REPORT); - break; - } - case FIRST_MRAM_DUMP: - case CONSECUTIVE_MRAM_DUMP: { - disableReply(commandId); - break; - } - case REQUEST_ADC_REPORT: { - disableReply(ADC_REPORT); - break; - } - case GET_BOOT_STATUS_REPORT: { - disableReply(BOOT_STATUS_REPORT); - break; - } - case GET_LATCHUP_STATUS_REPORT: { - disableReply(LATCHUP_REPORT); - break; - } - case REQUEST_LOGGING_COUNTERS: { - disableReply(COUNTERS_REPORT); - break; - } - default: { - break; - } - } - - /* We must always disable the execution report reply here */ - disableExeReportReply(); -} - -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; - info->command = deviceCommandMap.end(); -} - -void PlocSupervisorHandler::sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status) { - DeviceReplyIter iter = deviceReplyMap.find(replyId); - - if (iter == deviceReplyMap.end()) { - sif::debug << "PlocSupervisorHandler::sendFailureReport: Reply not in reply map" << std::endl; - return; - } - - DeviceCommandInfo* info = &(iter->second.command->second); - - if (info == nullptr) { - sif::debug << "PlocSupervisorHandler::sendFailureReport: Reply has no active command" - << std::endl; - return; - } - - if (info->sendReplyTo != NO_COMMANDER) { - actionHelper.finish(false, info->sendReplyTo, iter->first, status); - } - info->isExecuting = false; -} - -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(); - info->active = false; - /* Expected replies is set to one here. The value will set to 0 in replyToReply() */ - info->command->second.expectedReplies = 1; -} - -ReturnValue_t PlocSupervisorHandler::handleMramDumpPacket(DeviceCommandId_t id) { - ReturnValue_t result = returnvalue::FAILED; - - // Prepare packet for downlink - if (packetInBuffer) { - uint16_t packetLen = readSpacePacketLength(spacePacketBuffer); - result = verifyPacket(spacePacketBuffer, ccsds::HEADER_LEN + packetLen + 1); - if (result != returnvalue::OK) { - sif::warning << "PlocSupervisorHandler::handleMramDumpPacket: CRC failure" << std::endl; - return result; - } - result = handleMramDumpFile(id); - if (result != returnvalue::OK) { - DeviceCommandMap::iterator iter = deviceCommandMap.find(id); - if (iter != deviceCommandMap.end()) { - actionHelper.finish(false, iter->second.sendReplyTo, id, result); - } - disableAllReplies(); - nextReplyId = supv::NONE; - return result; - } - packetInBuffer = false; - receivedMramDumpPackets++; - if (expectedMramDumpPackets == receivedMramDumpPackets) { - nextReplyId = supv::EXE_REPORT; - } - increaseExpectedMramReplies(id); - return returnvalue::OK; - } - return result; -} - -void PlocSupervisorHandler::increaseExpectedMramReplies(DeviceCommandId_t id) { - DeviceReplyMap::iterator mramDumpIter = deviceReplyMap.find(id); - DeviceReplyMap::iterator exeReportIter = deviceReplyMap.find(supv::EXE_REPORT); - if (mramDumpIter == deviceReplyMap.end()) { - sif::debug << "PlocSupervisorHandler::increaseExpectedMramReplies: Dump MRAM reply not " - << "in reply map" << std::endl; - return; - } - if (exeReportIter == deviceReplyMap.end()) { - sif::debug << "PlocSupervisorHandler::increaseExpectedMramReplies: Execution report not " - << "in reply map" << std::endl; - return; - } - DeviceReplyInfo* mramReplyInfo = &(mramDumpIter->second); - if (mramReplyInfo == nullptr) { - sif::debug << "PlocSupervisorHandler::increaseExpectedReplies: MRAM reply info nullptr" - << std::endl; - return; - } - DeviceReplyInfo* exeReplyInfo = &(exeReportIter->second); - if (exeReplyInfo == nullptr) { - sif::debug << "PlocSupervisorHandler::increaseExpectedReplies: Execution reply info" - << " nullptr" << std::endl; - return; - } - DeviceCommandInfo* info = &(mramReplyInfo->command->second); - if (info == nullptr) { - sif::debug << "PlocSupervisorHandler::increaseExpectedReplies: Command info nullptr" - << std::endl; - return; - } - uint8_t sequenceFlags = spacePacketBuffer[2] >> 6; - if (sequenceFlags != static_cast(ccsds::SequenceFlags::LAST_SEGMENT) && - (sequenceFlags != static_cast(ccsds::SequenceFlags::UNSEGMENTED))) { - // Command expects at least one MRAM packet more and the execution report - info->expectedReplies = 2; - mramReplyInfo->countdown->resetTimer(); - } else { - // Command expects the execution report - info->expectedReplies = 1; - mramReplyInfo->active = false; - } - exeReplyInfo->countdown->resetTimer(); - return; -} - -ReturnValue_t PlocSupervisorHandler::handleMramDumpFile(DeviceCommandId_t id) { -#ifdef XIPHOS_Q7S - if (not sdcMan->getActiveSdCard()) { - return HasFileSystemIF::FILESYSTEM_INACTIVE; - } -#endif - ReturnValue_t result = returnvalue::OK; - uint16_t packetLen = readSpacePacketLength(spacePacketBuffer); - uint8_t sequenceFlags = readSequenceFlags(spacePacketBuffer); - if (id == supv::FIRST_MRAM_DUMP) { - if (sequenceFlags == static_cast(ccsds::SequenceFlags::FIRST_SEGMENT) || - (sequenceFlags == static_cast(ccsds::SequenceFlags::UNSEGMENTED))) { - result = createMramDumpFile(); - if (result != returnvalue::OK) { - return result; - } - } - } - if (not std::filesystem::exists(activeMramFile)) { - sif::warning << "PlocSupervisorHandler::handleMramDumpFile: MRAM file does not exist" - << std::endl; - return result::MRAM_FILE_NOT_EXISTS; - } - std::ofstream file(activeMramFile, std::ios_base::app | std::ios_base::out); - file.write(reinterpret_cast(spacePacketBuffer + ccsds::HEADER_LEN), packetLen - 1); - file.close(); - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::prepareWipeMramCmd(const uint8_t* commandData) { - 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; - } - finishTcPrep(packet); - return returnvalue::OK; -} - -uint16_t PlocSupervisorHandler::readSpacePacketLength(uint8_t* spacePacket) { - return spacePacket[4] << 8 | spacePacket[5]; -} - -uint8_t PlocSupervisorHandler::readSequenceFlags(uint8_t* spacePacket) { - return spacePacketBuffer[2] >> 6; -} - -ReturnValue_t PlocSupervisorHandler::createMramDumpFile() { - ReturnValue_t result = returnvalue::OK; - std::string timeStamp; - result = getTimeStampString(timeStamp); - if (result != returnvalue::OK) { - return result; - } - - std::string filename = "mram-dump--" + timeStamp + ".bin"; - -#ifdef XIPHOS_Q7S - const char* currentMountPrefix = sdcMan->getCurrentMountPrefix(); -#else - const char* currentMountPrefix = "/mnt/sd0"; -#endif /* BOARD_TE0720 == 0 */ - if (currentMountPrefix == nullptr) { - return returnvalue::FAILED; - } - - // Check if path to PLOC directory exists - if (not std::filesystem::exists(std::string(currentMountPrefix) + "/" + supervisorFilePath)) { - sif::warning << "PlocSupervisorHandler::createMramDumpFile: Supervisor path does not exist" - << std::endl; - return result::PATH_DOES_NOT_EXIST; - } - activeMramFile = std::string(currentMountPrefix) + "/" + supervisorFilePath + "/" + filename; - // Create new file - std::ofstream file(activeMramFile, std::ios_base::out); - file.close(); - - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::getTimeStampString(std::string& timeStamp) { - Clock::TimeOfDay_t time; - ReturnValue_t result = Clock::getDateAndTime(&time); - if (result != returnvalue::OK) { - sif::warning << "PlocSupervisorHandler::getTimeStampString: Failed to get current time" - << std::endl; - return result::GET_TIME_FAILURE; - } - timeStamp = std::to_string(time.year) + "-" + std::to_string(time.month) + "-" + - std::to_string(time.day) + "--" + std::to_string(time.hour) + "-" + - std::to_string(time.minute) + "-" + std::to_string(time.second); - return returnvalue::OK; -} - -ReturnValue_t PlocSupervisorHandler::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 PlocSupervisorHandler::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; -} - -ReturnValue_t PlocSupervisorHandler::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 PlocSupervisorHandler::handleExecutionSuccessReport(ExecutionReport& report) { - DeviceCommandId_t commandId = getPendingCommand(); - 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 - 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 */ - if (iter != deviceCommandMap.end() and iter->second.sendReplyTo == NO_COMMAND_ID) { - return returnvalue::OK; - } - 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(iter->second.sendReplyTo, 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: { - // We could only allow proper bootup when the time was set successfully, but - // this makes debugging difficult. - - if (startupState == StartupState::WAIT_FOR_TIME_REPLY) { - startupState = StartupState::TIME_WAS_SET; - } - break; - } - default: - break; - } - return returnvalue::OK; -} - -void PlocSupervisorHandler::handleExecutionFailureReport(ExecutionReport& report) { - using namespace supv; - DeviceCommandId_t commandId = getPendingCommand(); - report.printStatusInformation(); - if (commandId != DeviceHandlerIF::NO_COMMAND_ID) { - triggerEvent(SUPV_EXE_FAILURE, commandId, static_cast(report.getStatusCode())); - } - sendFailureReport(EXE_REPORT, result::RECEIVED_EXE_FAILURE); - disableExeReportReply(); -} - -void PlocSupervisorHandler::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 PlocSupervisorHandler::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; - } -} - -ReturnValue_t PlocSupervisorHandler::getSwitches(const uint8_t** switches, - uint8_t* numberOfSwitches) { - if (powerSwitch == power::NO_SWITCH) { - return DeviceHandlerBase::NO_SWITCH; - } - *numberOfSwitches = 1; - *switches = &powerSwitch; - return returnvalue::OK; -} - -uint32_t PlocSupervisorHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { - 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) { - 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; - } - } - } - return DeviceHandlerBase::checkModeCommand(commandedMode, commandedSubmode, msToReachTheMode); -} diff --git a/linux/payload/PlocSupervisorHandler.h b/linux/payload/PlocSupervisorHandler.h deleted file mode 100644 index 14051c22..00000000 --- a/linux/payload/PlocSupervisorHandler.h +++ /dev/null @@ -1,386 +0,0 @@ -#ifndef MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ -#define MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ - -#include -#include -#include - -#include "OBSWConfig.h" -#include "devices/powerSwitcherList.h" -#include "fsfw/devicehandlers/DeviceHandlerBase.h" -#include "fsfw/timemanager/Countdown.h" -#include "fsfw_hal/linux/gpio/Gpio.h" -#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h" -#include "fsfw_hal/linux/serial/SerialComIF.h" - -#ifdef XIPHOS_Q7S -#include "bsp_q7s/fs/SdCardManager.h" -#endif - -using supv::ExecutionReport; -using supv::TcBase; - -/** - * @brief This is the device handler for the supervisor of the PLOC which is programmed by - * Thales. - * - * @details The PLOC uses the space packet protocol for communication. On each command the PLOC - * answers with at least one acknowledgment and one execution report. - * Flight manual: - * https://egit.irs.uni-stuttgart.de/redmine/projects/eive-flight-manual/wiki/PLOC_Commands - * ILH ICD: https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/ - * Arbeitsdaten/08_Used%20Components/PLOC&fileid=940960 - * @author J. Meier - */ -class PlocSupervisorHandler : public DeviceHandlerBase { - public: - PlocSupervisorHandler(object_id_t objectId, CookieIF* comCookie, Gpio uartIsolatorSwitch, - power::Switch_t powerSwitch, PlocSupvUartManager& supvHelper); - virtual ~PlocSupervisorHandler(); - - virtual ReturnValue_t initialize() override; - void performOperationHook() override; - ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, - const uint8_t* data, size_t size) override; - - protected: - void doStartUp() override; - void doShutDown() override; - ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t* id) override; - ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t* id) override; - void fillCommandAndReplyMap() override; - ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t* commandData, - size_t commandDataLen) override; - ReturnValue_t scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId, - size_t* foundLen) override; - ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) override; - uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; - ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, - LocalDataPoolManager& poolManager) override; - ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator command, - uint8_t expectedReplies = 1, bool useAlternateId = false, - DeviceCommandId_t alternateReplyID = 0) override; - size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override; - // ReturnValue_t doSendReadHook() override; - void doOffActivity() override; - - private: - static const uint16_t APID_MASK = 0x7FF; - static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF; - static const uint8_t EXE_STATUS_OFFSET = 10; - static const uint8_t SIZE_NULL_TERMINATOR = 1; - // 5 s - static const uint32_t EXECUTION_DEFAULT_TIMEOUT = 5000; - // 70 S - 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; - - enum class StartupState : uint8_t { - OFF, - BOOTING, - SET_TIME, - WAIT_FOR_TIME_REPLY, - TIME_WAS_SET, - ON - }; - - static constexpr bool SET_TIME_DURING_BOOT = true; - - StartupState startupState = StartupState::OFF; - - uint8_t commandBuffer[supv::MAX_COMMAND_SIZE]; - SpacePacketCreator creator; - supv::TcParams spParams = supv::TcParams(creator); - - /** - * This variable is used to store the id of the next reply to receive. This is necessary - * because the PLOC sends as reply to each command at least one acknowledgment and execution - * report. - */ - DeviceCommandId_t nextReplyId = supv::NONE; - - SerialComIF* uartComIf = nullptr; - 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::CountersReport countersReport; - supv::AdcReport adcReport; - - const power::Switch_t powerSwitch = power::NO_SWITCH; - supv::TmBase tmReader; - - PlocSupvUartManager& uartManager; - MessageQueueIF* eventQueue = nullptr; - - /** Number of expected replies following the MRAM dump command */ - uint32_t expectedMramDumpPackets = 0; - uint32_t receivedMramDumpPackets = 0; - /** Set to true as soon as a complete space packet is present in the spacePacketBuffer */ - bool packetInBuffer = false; - - /** This buffer is used to concatenate space packets received in two different read steps */ - uint8_t spacePacketBuffer[supv::MAX_PACKET_SIZE]; - -#ifdef XIPHOS_Q7S - SdCardManager* sdcMan = nullptr; -#endif - - // Path to supervisor specific files on SD card - std::string supervisorFilePath = "ploc/supervisor"; - std::string activeMramFile; - - Countdown executionReportTimeout = Countdown(EXECUTION_DEFAULT_TIMEOUT, false); - Countdown acknowledgementReportTimeout = Countdown(ACKNOWLEDGE_DEFAULT_TIMEOUT, false); - // Vorago nees some time to boot properly - 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); - PoolEntry tempSupEntry = PoolEntry(1); - - /** - * @brief Adjusts the timeout of the execution report dependent on command - */ - void setExecutionTimeout(DeviceCommandId_t command); - - void handlePacketPrint(); - - /** - * @brief Handles event messages received from the supervisor helper - */ - void handleEvent(EventMessage* eventMessage); - - ReturnValue_t getSwitches(const uint8_t** switches, uint8_t* numberOfSwitches); - - /** - * @brief This function checks the crc of the received PLOC reply. - * - * @param start Pointer to the first byte of the reply. - * @param foundLen Pointer to the length of the whole packet. - * - * @return returnvalue::OK if CRC is ok, otherwise CRC_FAILURE. - */ - ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen); - - /** - * @brief This function handles the acknowledgment report. - * - * @param data Pointer to the data holding the acknowledgment report. - * - * @return returnvalue::OK if successful, otherwise an error code. - */ - ReturnValue_t handleAckReport(const uint8_t* data); - - /** - * @brief This function handles the data of a execution report. - * - * @param data Pointer to the received data packet. - * - * @return returnvalue::OK if successful, otherwise an error code. - */ - ReturnValue_t handleExecutionReport(const uint8_t* data); - - /** - * @brief This function handles the housekeeping report. This means verifying the CRC of the - * reply and filling the appropriate dataset. - * - * @param data Pointer to the data buffer holding the housekeeping read report. - * - * @return returnvalue::OK if successful, otherwise an error code. - */ - ReturnValue_t handleHkReport(const uint8_t* data); - - /** - * @brief This function calls the function to check the CRC of the received boot status report - * and fills the associated dataset with the boot status information. - */ - 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 - * next reply after a successful acknowledgment report has been received. This is - * required by the function getNextReplyLength() to identify the length of the next - * reply to read. - */ - void setNextReplyId(); - - /** - * @brief This function handles action message replies in case the telemetry has been - * requested by another object. - * - * @param data Pointer to the telemetry data. - * @param dataSize Size of telemetry in bytes. - * @param replyId Id of the reply. This will be added to the ActionMessage. - */ - void handleDeviceTm(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId); - - /** - * @brief This function prepares a space packet which does not transport any data in the - * packet data field apart from the crc. - */ - ReturnValue_t prepareEmptyCmd(uint16_t apid, uint8_t serviceId); - - /** - * @brief This function initializes the space packet to select the boot image of the MPSoC. - */ - ReturnValue_t prepareSelBootImageCmd(const uint8_t* commandData); - - ReturnValue_t prepareDisableHk(); - - /** - * @brief This function fills the commandBuffer with the data to update the time of the - * PLOC supervisor. - */ - ReturnValue_t prepareSetTimeRefCmd(); - - /** - * @brief This function fills the commandBuffer with the data to change the boot timeout - * value in the PLOC supervisor. - */ - ReturnValue_t prepareSetBootTimeoutCmd(const uint8_t* commandData); - - ReturnValue_t prepareRestartTriesCmd(const uint8_t* commandData); - - ReturnValue_t prepareFactoryResetCmd(const uint8_t* commandData, size_t len); - - /** - * @brief This function fills the command buffer with the packet to enable or disable the - * watchdogs on the PLOC. - */ - void prepareWatchdogsEnableCmd(const uint8_t* commandData); - - /** - * @brief This function fills the command buffer with the packet to set the watchdog timer - * of one of the three watchdogs (PS, PL, INT). - */ - ReturnValue_t prepareWatchdogsConfigTimeoutCmd(const uint8_t* commandData); - - ReturnValue_t prepareLatchupConfigCmd(const uint8_t* commandData, - DeviceCommandId_t deviceCommand); - ReturnValue_t prepareSetAlertLimitCmd(const uint8_t* commandData); - ReturnValue_t prepareSetAdcEnabledChannelsCmd(const uint8_t* commandData); - ReturnValue_t prepareSetAdcWindowAndStrideCmd(const uint8_t* commandData); - 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, 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. - */ - void finishTcPrep(TcBase& tc); - - /** - * @brief In case an acknowledgment failure reply has been received this function disables - * all previously enabled commands and resets the exepected replies variable of an - * active command. - */ - void disableAllReplies(); - - void disableReply(DeviceCommandId_t replyId); - - /** - * @brief This function sends a failure report if the active action was commanded by an other - * object. - * - * @param replyId The id of the reply which signals a failure. - * @param status A status byte which gives information about the failure type. - */ - void sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status); - - /** - * @brief This function disables the execution report reply. Within this function also the - * the variable expectedReplies of an active command will be set to 0. - */ - void disableExeReportReply(); - - /** - * @brief This function generates the Service 8 packets for the MRAM dump data. - */ - ReturnValue_t handleMramDumpPacket(DeviceCommandId_t id); - - /** - * @brief With this function the number of expected replies following an MRAM dump command - * will be increased. This is necessary to release the command in case not all replies - * have been received. - */ - void increaseExpectedMramReplies(DeviceCommandId_t id); - - /** - * @brief Writes the data of the MRAM dump to a file. The file will be created when receiving - * the first packet. - */ - ReturnValue_t handleMramDumpFile(DeviceCommandId_t id); - - /** - * @brief Extracts the length field of a spacePacket referenced by the spacePacket pointer. - * - * @param spacePacket Pointer to the buffer holding the space packet. - * - * @return The value stored in the length field of the data field. - */ - uint16_t readSpacePacketLength(uint8_t* spacePacket); - - /** - * @brief Extracts the sequence flags from a space packet referenced by the spacePacket - * pointer. - * - * @param spacePacket Pointer to the buffer holding the space packet. - * - * @return uint8_t where the two least significant bits hold the sequence flags. - */ - uint8_t readSequenceFlags(uint8_t* spacePacket); - - ReturnValue_t createMramDumpFile(); - ReturnValue_t getTimeStampString(std::string& timeStamp); - - ReturnValue_t prepareSetShutdownTimeoutCmd(const uint8_t* commandData); - - 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); - ReturnValue_t eventSubscription(); - - ReturnValue_t handleExecutionSuccessReport(ExecutionReport& report); - void handleExecutionFailureReport(ExecutionReport& report); - - void printAckFailureInfo(uint16_t statusCode, DeviceCommandId_t commandId); - - pwrctrl::EnablePl enablePl = pwrctrl::EnablePl(objects::POWER_CONTROLLER); - ReturnValue_t checkModeCommand(Mode_t commandedMode, Submode_t commandedSubmode, - uint32_t* msToReachTheMode) override; -}; - -#endif /* MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ */ diff --git a/linux/payload/PlocSupvUartMan.cpp b/linux/payload/PlocSupvUartMan.cpp index 475e611b..7cde1463 100644 --- a/linux/payload/PlocSupvUartMan.cpp +++ b/linux/payload/PlocSupvUartMan.cpp @@ -80,7 +80,6 @@ ReturnValue_t PlocSupvUartManager::initializeInterface(CookieIF* cookie) { } // Flush received and unread data tcflush(serialPort, TCIOFLUSH); - sif::debug << "serial port: " << serialPort << std::endl; return OK; } @@ -98,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 @@ -112,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: { @@ -140,9 +142,7 @@ ReturnValue_t PlocSupvUartManager::performOperation(uint8_t operationCode) { ReturnValue_t PlocSupvUartManager::handleUartReception() { ReturnValue_t result = OK; ReturnValue_t status = OK; - sif::debug << "reading port " << serialPort << std::endl; - TaskFactory::delayTask(100); - ssize_t bytesRead = read(302, reinterpret_cast(recBuf.data()), + ssize_t bytesRead = read(serialPort, reinterpret_cast(recBuf.data()), static_cast(recBuf.size())); if (bytesRead == 0) { while (result != NO_PACKET_FOUND) { @@ -160,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); } @@ -575,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; @@ -621,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; @@ -631,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()), @@ -653,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; @@ -663,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()), @@ -686,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; } @@ -762,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; @@ -790,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; } @@ -966,12 +966,10 @@ 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); } - sif::debug << "writing to serial port: " << serialPort << std::endl; - TaskFactory::delayTask(50); size_t bytesWritten = write(serialPort, encodedSendBuf.data(), encodedLen); if (bytesWritten != encodedLen) { sif::warning @@ -990,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) { @@ -1090,11 +1091,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 69f938b0..562bd3bd 100644 --- a/linux/payload/PlocSupvUartMan.h +++ b/linux/payload/PlocSupvUartMan.h @@ -282,8 +282,8 @@ class PlocSupvUartManager : public DeviceCommunicationIF, std::array tmBuf{}; - bool printTc = true; - bool debugMode = true; + 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 diff --git a/linux/payload/plocSupvDefs.h b/linux/payload/plocSupvDefs.h index a87d25a3..0ac9d9b1 100644 --- a/linux/payload/plocSupvDefs.h +++ b/linux/payload/plocSupvDefs.h @@ -556,15 +556,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; } @@ -576,9 +567,6 @@ class TmBase : public ploc::SpTmReader { } return 0; } - - private: - bool crcOk = false; }; class NoPayloadPacket : public TcBase { @@ -786,8 +774,6 @@ class SetRestartTries : public TcBase { } private: - uint8_t restartTries = 0; - void initPacket(uint8_t restartTries) { payloadStart[0] = restartTries; } }; @@ -848,8 +834,6 @@ class LatchupAlert : public TcBase { } private: - uint8_t latchupId = 0; - void initPacket(uint8_t latchupId) { payloadStart[0] = latchupId; } }; @@ -879,9 +863,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; @@ -1312,8 +1293,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) { @@ -1330,27 +1311,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; @@ -1367,7 +1348,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()); @@ -1654,15 +1635,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); } @@ -1676,15 +1657,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); } @@ -1696,8 +1677,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) { 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; From e8bb8fd8f07ec8ecea80a391e49957a88e9d1433 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Nov 2023 11:33:53 +0100 Subject: [PATCH 21/69] cleaning up --- bsp_q7s/objectFactory.cpp | 1 - mission/pollingSeqTables.cpp | 8 +------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/bsp_q7s/objectFactory.cpp b/bsp_q7s/objectFactory.cpp index e4474bb8..95c15097 100644 --- a/bsp_q7s/objectFactory.cpp +++ b/bsp_q7s/objectFactory.cpp @@ -60,7 +60,6 @@ #include "linux/ipcore/Ptme.h" #include "linux/ipcore/PtmeConfig.h" #include "linux/payload/FreshSupvHandler.h" -#include "linux/payload/PlocSupervisorHandler.h" #include "mission/config/configfile.h" #include "mission/system/acs/AcsBoardFdir.h" #include "mission/system/acs/AcsSubsystem.h" diff --git a/mission/pollingSeqTables.cpp b/mission/pollingSeqTables.cpp index 7c953461..1b369292 100644 --- a/mission/pollingSeqTables.cpp +++ b/mission/pollingSeqTables.cpp @@ -623,17 +623,11 @@ ReturnValue_t pst::pstPayload(FixedTimeslotTaskIF *thisSequence) { 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); - - /* - thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE); - thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE); - thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0, DeviceHandlerIF::GET_READ); - */ static_cast(length); return thisSequence->checkSequence(); From 14813441dcb27676f209a0de6b72b53209643937 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Nov 2023 11:39:16 +0100 Subject: [PATCH 22/69] bump fsfw --- fsfw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsfw b/fsfw index 7673d8b3..8d7bb51d 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 7673d8b396764186d93c3378496ccfc3c1b2e2e8 +Subproject commit 8d7bb51d44c6fde88719c35cc51f3986a16f9956 From 03a6a06e48edee4adc14d3ea0c26128082b393f2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Nov 2023 11:46:08 +0100 Subject: [PATCH 23/69] some more improvements --- linux/payload/FreshSupvHandler.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 8fbce1da..edd40868 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -526,8 +526,12 @@ void FreshSupvHandler::handleTransitionToOff() { ReturnValue_t FreshSupvHandler::sendCommand(DeviceCommandId_t commandId, TcBase& tc, bool replyExpected, uint32_t cmdCountdownMs) { if (supv::DEBUG_PLOC_SUPV) { - sif::debug << "PLOC SUPV: SEND PACKET Size " << tc.getFullPacketLen() << " Module APID " - << (int)tc.getModuleApid() << " Service ID " << (int)tc.getServiceId() << std::endl; + 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 = @@ -924,7 +928,7 @@ void FreshSupvHandler::handlePacketPrint() { << std::endl; } } - if (supv::REDUCE_NORMAL_MODE_PRINTOUT and + 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; @@ -965,6 +969,11 @@ void FreshSupvHandler::handlePacketPrint() { 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; From 0e6d2dc79bf566ac5c50c6689b5724a4da14de3d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Nov 2023 14:17:43 +0100 Subject: [PATCH 24/69] this should work better --- linux/payload/FreshSupvHandler.cpp | 30 +++++++++++++++++++++++++----- linux/payload/FreshSupvHandler.h | 3 +++ linux/payload/plocSupvDefs.h | 1 + 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index edd40868..eefd64af 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -8,6 +8,7 @@ #include "eive/definitions.h" #include "eive/objects.h" +#include "fsfw/globalfunctions/arrayprinter.h" #include "fsfw/ipc/MessageQueueIF.h" #include "fsfw/ipc/QueueFactory.h" #include "fsfw/objectmanager/ObjectManagerIF.h" @@ -70,7 +71,9 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { handleTransitionToOff(); } } else { - if (mode == MODE_NORMAL) { + // I think the SUPV is not able to process multiple commands consecutively, so only send + // normal command if no other command is pending. + 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) { @@ -525,6 +528,9 @@ void FreshSupvHandler::handleTransitionToOff() { ReturnValue_t FreshSupvHandler::sendCommand(DeviceCommandId_t commandId, TcBase& tc, bool replyExpected, uint32_t cmdCountdownMs) { + if (interCmdCd.isBusy()) { + TaskFactory::delayTask(interCmdCd.getRemainingMillis()); + } if (supv::DEBUG_PLOC_SUPV) { if (not(supv::REDUCE_NORMAL_MODE_PRINTOUT and mode == MODE_NORMAL and commandId == supv::GET_HK_REPORT)) { @@ -552,7 +558,10 @@ ReturnValue_t FreshSupvHandler::sendCommand(DeviceCommandId_t commandId, TcBase& activeCmdIter->second.cmdCountdown.setTimeout(cmdCountdownMs); activeCmdIter->second.cmdCountdown.resetTimer(); } - return uartManager->sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen()); + ReturnValue_t result = + uartManager->sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen()); + interCmdCd.resetTimer(); + return result; } ReturnValue_t FreshSupvHandler::initialize() { @@ -824,13 +833,15 @@ ReturnValue_t FreshSupvHandler::parseTmPackets() { } tmReader.setReadOnlyData(receivedData, receivedSize); if (tmReader.checkCrc() != returnvalue::OK) { - sif::warning << "PlocSupervisorHandler::parseTmPackets: CRC failure" << std::endl; + sif::warning << "PlocSupervisorHandler::parseTmPackets: CRC failure for packet with size " + << receivedSize << std::endl; + arrayprinter::print(receivedData, receivedSize); continue; } - uint16_t apid = tmReader.getModuleApid(); if (supv::DEBUG_PLOC_SUPV) { handlePacketPrint(); } + uint16_t apid = tmReader.getModuleApid(); switch (apid) { case (Apid::TMTC_MAN): { switch (tmReader.getServiceId()) { @@ -952,7 +963,7 @@ void FreshSupvHandler::handlePacketPrint() { sif::warning << "PlocSupervisorHandler: Parsing EXE failed" << std::endl; } const char* printStr = "???"; - if (supv::REDUCE_NORMAL_MODE_PRINTOUT and + 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; @@ -1539,3 +1550,12 @@ ReturnValue_t FreshSupvHandler::genericHandleTm(const char* contextString, const 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 index be968564..86cc9147 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -101,6 +101,7 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { 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); @@ -181,6 +182,8 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { 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/plocSupvDefs.h b/linux/payload/plocSupvDefs.h index 0ac9d9b1..4423bbb3 100644 --- a/linux/payload/plocSupvDefs.h +++ b/linux/payload/plocSupvDefs.h @@ -47,6 +47,7 @@ static const Event SUPV_ACK_UNKNOWN_COMMAND = MAKE_EVENT(9, severity::LOW); 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; From cae76e17f512d4d46db279ccd46f6ee15272a30c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Nov 2023 14:38:09 +0100 Subject: [PATCH 25/69] more improvements and bugfixes --- linux/payload/FreshSupvHandler.cpp | 10 ++++++++-- linux/payload/PlocSupvUartMan.cpp | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index eefd64af..b872f41c 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -85,7 +85,7 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { } } else if (opCode == OpCode::PARSE_TM) { for (auto& activeCmd : activeActionCmds) { - if (activeCmd.second.cmdCountdown.hasTimedOut()) { + 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); @@ -238,6 +238,11 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI default: break; } + // This might not be necessary, but I think the PLOC SUPV is not able to process multiple + // commands consecutively.. + if (isCommandPending()) { + return HasActionsIF::IS_BUSY; + } if (isCommandAlreadyActive(actionId)) { return HasActionsIF::IS_BUSY; } @@ -543,8 +548,9 @@ ReturnValue_t FreshSupvHandler::sendCommand(DeviceCommandId_t commandId, TcBase& auto activeCmdIter = activeActionCmds.find(buildActiveCmdKey(tc.getModuleApid(), tc.getServiceId())); if (activeCmdIter == activeActionCmds.end()) { + info.isPending = true; + info.replyPacketExpected = replyExpected; activeActionCmds.emplace(buildActiveCmdKey(tc.getModuleApid(), tc.getServiceId()), info); - } else { if (activeCmdIter->second.isPending) { return HasActionsIF::IS_BUSY; diff --git a/linux/payload/PlocSupvUartMan.cpp b/linux/payload/PlocSupvUartMan.cpp index 7cde1463..f73ca560 100644 --- a/linux/payload/PlocSupvUartMan.cpp +++ b/linux/payload/PlocSupvUartMan.cpp @@ -1061,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; From f0536a9d771a9a0e99e77af8c2fa366af019ca90 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Nov 2023 15:21:00 +0100 Subject: [PATCH 26/69] this should do the job --- .gitignore | 4 ++ mission/tmtc/PersistentTmStore.cpp | 28 ++++++++--- mission/tmtc/PersistentTmStore.h | 1 + mission/tmtc/Service15TmStorage.cpp | 73 +++++++++++++++++++---------- mission/tmtc/Service15TmStorage.h | 6 ++- tmtc | 2 +- 6 files changed, 80 insertions(+), 34 deletions(-) diff --git a/.gitignore b/.gitignore index 5419ca42..eb6a49fa 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,7 @@ __pycache__ !/.idea/cmake.xml generators/*.db + +# Clangd LSP +/compile_commands.json +/.cache diff --git a/mission/tmtc/PersistentTmStore.cpp b/mission/tmtc/PersistentTmStore.cpp index 160348cd..4bd82880 100644 --- a/mission/tmtc/PersistentTmStore.cpp +++ b/mission/tmtc/PersistentTmStore.cpp @@ -140,12 +140,25 @@ ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore, Clock::getClock_timeval(¤tTv); store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage); auto accessor = ipcStore.getData(storeId); - uint32_t deleteUpToUnixSeconds = 0; size_t size = accessor.second.size(); - SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, accessor.second.data(), &size, - SerializeIF::Endianness::NETWORK); + if (size < 4) { + return returnvalue::FAILED; + } + const uint8_t* data = accessor.second.data(); + uint32_t deleteUpToUnixSeconds = 0; + if (size == 4) { + SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, &data, &size, + SerializeIF::Endianness::NETWORK); + deleteUpTo(deleteUpToUnixSeconds); + } else if (size == 8) { + uint32_t deleteFromUnixSeconds = 0; + SerializeAdapter::deSerialize(&deleteFromUnixSeconds, &data, &size, + SerializeIF::Endianness::NETWORK); + SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, &data, &size, + SerializeIF::Endianness::NETWORK); + deleteFromUpTo(deleteFromUnixSeconds, deleteUpToUnixSeconds); + } execCmd = cmd; - deleteUpTo(deleteUpToUnixSeconds); } else if (cmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) { Clock::getClock_timeval(¤tTv); store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage); @@ -257,7 +270,9 @@ bool PersistentTmStore::updateBaseDir() { return true; } -void PersistentTmStore::deleteUpTo(uint32_t unixSeconds) { +void PersistentTmStore::deleteUpTo(uint32_t unixSeconds) { deleteFromUpTo(0, unixSeconds); } + +void PersistentTmStore::deleteFromUpTo(uint32_t startUnixTime, uint32_t endUnixTime) { using namespace std::filesystem; for (auto const& file : directory_iterator(basePath)) { if (file.is_directory() or (activeFile.has_value() and (activeFile.value() == file.path()))) { @@ -270,7 +285,8 @@ void PersistentTmStore::deleteUpTo(uint32_t unixSeconds) { continue; } time_t fileEpoch = timegm(&fileTime); - if (fileEpoch + rolloverDiffSeconds < unixSeconds) { + if (fileEpoch + rolloverDiffSeconds < endUnixTime and + static_cast(fileEpoch) >= startUnixTime) { std::error_code e; std::filesystem::remove(file.path(), e); } diff --git a/mission/tmtc/PersistentTmStore.h b/mission/tmtc/PersistentTmStore.h index e86acaaf..4255b9d4 100644 --- a/mission/tmtc/PersistentTmStore.h +++ b/mission/tmtc/PersistentTmStore.h @@ -60,6 +60,7 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject { ReturnValue_t handleCommandQueue(StorageManagerIF& ipcStore, Command_t& execCmd); void deleteUpTo(uint32_t unixSeconds); + void deleteFromUpTo(uint32_t startUnixTime, uint32_t endUnixTime); ReturnValue_t startDumpFrom(uint32_t fromUnixSeconds); ReturnValue_t startDumpFromUpTo(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds); /** diff --git a/mission/tmtc/Service15TmStorage.cpp b/mission/tmtc/Service15TmStorage.cpp index 1c9b8611..273c406b 100644 --- a/mission/tmtc/Service15TmStorage.cpp +++ b/mission/tmtc/Service15TmStorage.cpp @@ -16,8 +16,8 @@ Service15TmStorage::Service15TmStorage(object_id_t objectId, uint16_t apid, ReturnValue_t Service15TmStorage::isValidSubservice(uint8_t subservice) { switch (subservice) { - case (Subservices::DELETE_UP_TO): - case (Subservices::START_BY_TIME_RANGE_RETRIEVAL): { + case (Subservice::DELETE_UP_TO): + case (Subservice::START_BY_TIME_RANGE_RETRIEVAL): { return OK; } default: { @@ -45,34 +45,55 @@ ReturnValue_t Service15TmStorage::getMessageQueueAndObject(uint8_t subservice, ReturnValue_t Service15TmStorage::prepareCommand(CommandMessage *message, uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, uint32_t *state, object_id_t objectId) { - if (subservice == Subservices::START_BY_TIME_RANGE_RETRIEVAL) { - // TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver - // to time reading and reply handling - if (tcDataLen != 12) { - return INVALID_TC; + switch (subservice) { + case (Subservice::START_BY_TIME_RANGE_RETRIEVAL): { + // TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver + // to time reading and reply handling + if (tcDataLen != 12) { + return INVALID_TC; + } + store_address_t storeId; + ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4); + if (result != OK) { + return result; + } + // Store timestamps + TmStoreMessage::setDownlinkContentTimeMessage(message, storeId); + return CommandingServiceBase::EXECUTION_COMPLETE; } - store_address_t storeId; - ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4); - if (result != OK) { - return result; + case (Subservice::DELETE_UP_TO): { + // TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver + // to time reading and reply handling + if (tcDataLen != 8) { + return INVALID_TC; + } + store_address_t storeId; + ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4); + if (result != OK) { + return result; + } + // Store timestamps + TmStoreMessage::setDeleteContentTimeMessage(message, storeId); + return CommandingServiceBase::EXECUTION_COMPLETE; } - // Store timestamps - TmStoreMessage::setDownlinkContentTimeMessage(message, storeId); - return CommandingServiceBase::EXECUTION_COMPLETE; - } else if (subservice == Subservices::DELETE_UP_TO) { - // TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver - // to time reading and reply handling - if (tcDataLen != 8) { - return INVALID_TC; + case (Subservice::DELETE_BY_TIME_RANGE): { + // TODO: Hardcoded two UNIX timestamps.. Should allow arbitrary timestamp and let receiver + // to time reading and reply handling + if (tcDataLen != 12) { + return INVALID_TC; + } + store_address_t storeId; + ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4); + if (result != OK) { + return result; + } + // Store timestamps + TmStoreMessage::setDeleteContentTimeMessage(message, storeId); + return CommandingServiceBase::EXECUTION_COMPLETE; } - store_address_t storeId; - ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4); - if (result != OK) { - return result; + default: { + return CommandingServiceBase::INVALID_SUBSERVICE; } - // Store timestamps - TmStoreMessage::setDeleteContentTimeMessage(message, storeId); - return CommandingServiceBase::EXECUTION_COMPLETE; } return OK; } diff --git a/mission/tmtc/Service15TmStorage.h b/mission/tmtc/Service15TmStorage.h index 33be0634..6da381ee 100644 --- a/mission/tmtc/Service15TmStorage.h +++ b/mission/tmtc/Service15TmStorage.h @@ -5,7 +5,11 @@ class Service15TmStorage : public CommandingServiceBase { public: - enum Subservices : uint8_t { START_BY_TIME_RANGE_RETRIEVAL = 9, DELETE_UP_TO = 11 }; + enum Subservice : uint8_t { + START_BY_TIME_RANGE_RETRIEVAL = 9, + DELETE_UP_TO = 11, + DELETE_BY_TIME_RANGE = 128 + }; explicit Service15TmStorage(object_id_t objectId, uint16_t apid, uint8_t numParallelCommands, uint16_t commandTimeoutSecs = 60, size_t queueDepth = 10); diff --git a/tmtc b/tmtc index 99c6c8bb..07b13c15 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 99c6c8bbd0d791d8b17720de481c6142091a54a4 +Subproject commit 07b13c153dab03c35ea3c7921f68c6ba77049d1e From 457acc3bdbfff50887ef060f3189756bd810d0e4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Nov 2023 15:27:12 +0100 Subject: [PATCH 27/69] improve structure --- mission/tmtc/PersistentTmStore.cpp | 93 +++++++++++++++++------------- mission/tmtc/PersistentTmStore.h | 3 + 2 files changed, 57 insertions(+), 39 deletions(-) diff --git a/mission/tmtc/PersistentTmStore.cpp b/mission/tmtc/PersistentTmStore.cpp index 4bd82880..0ba690c2 100644 --- a/mission/tmtc/PersistentTmStore.cpp +++ b/mission/tmtc/PersistentTmStore.cpp @@ -137,53 +137,68 @@ ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore, if (cmdMessage.getMessageType() == messagetypes::TM_STORE) { Command_t cmd = cmdMessage.getCommand(); if (cmd == TmStoreMessage::DELETE_STORE_CONTENT_TIME) { - Clock::getClock_timeval(¤tTv); - store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage); - auto accessor = ipcStore.getData(storeId); - size_t size = accessor.second.size(); - if (size < 4) { - return returnvalue::FAILED; - } - const uint8_t* data = accessor.second.data(); - uint32_t deleteUpToUnixSeconds = 0; - if (size == 4) { - SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, &data, &size, - SerializeIF::Endianness::NETWORK); - deleteUpTo(deleteUpToUnixSeconds); - } else if (size == 8) { - uint32_t deleteFromUnixSeconds = 0; - SerializeAdapter::deSerialize(&deleteFromUnixSeconds, &data, &size, - SerializeIF::Endianness::NETWORK); - SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, &data, &size, - SerializeIF::Endianness::NETWORK); - deleteFromUpTo(deleteFromUnixSeconds, deleteUpToUnixSeconds); - } + result = handleDeletionCmd(ipcStore, cmdMessage); execCmd = cmd; } else if (cmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) { - Clock::getClock_timeval(¤tTv); - store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage); - auto accessor = ipcStore.getData(storeId); - if (accessor.second.size() < 8) { - return returnvalue::FAILED; - } - uint32_t dumpFromUnixSeconds = 0; - uint32_t dumpUntilUnixSeconds = 0; - size_t size = 8; - SerializeAdapter::deSerialize(&dumpFromUnixSeconds, accessor.second.data(), &size, - SerializeIF::Endianness::NETWORK); - SerializeAdapter::deSerialize(&dumpUntilUnixSeconds, accessor.second.data() + 4, &size, - SerializeIF::Endianness::NETWORK); - result = startDumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds); - if (result == BUSY_DUMPING) { - triggerEvent(persTmStore::BUSY_DUMPING_EVENT); - return result; - } + result = handleDumpCmd(ipcStore, cmdMessage); execCmd = cmd; } } return result; } +ReturnValue_t PersistentTmStore::handleDeletionCmd(StorageManagerIF& ipcStore, + CommandMessage& cmdMessage) { + Clock::getClock_timeval(¤tTv); + store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage); + auto accessor = ipcStore.getData(storeId); + size_t size = accessor.second.size(); + if (size < 4) { + return returnvalue::FAILED; + } + const uint8_t* data = accessor.second.data(); + uint32_t deleteUpToUnixSeconds = 0; + if (size == 4) { + SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, &data, &size, + SerializeIF::Endianness::NETWORK); + deleteUpTo(deleteUpToUnixSeconds); + } else if (size == 8) { + uint32_t deleteFromUnixSeconds = 0; + SerializeAdapter::deSerialize(&deleteFromUnixSeconds, &data, &size, + SerializeIF::Endianness::NETWORK); + SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, &data, &size, + SerializeIF::Endianness::NETWORK); + deleteFromUpTo(deleteFromUnixSeconds, deleteUpToUnixSeconds); + } else { + sif::warning << "PersistentTmStore: Unknown deletion time specification" << std::endl; + return returnvalue::FAILED; + } + return returnvalue::OK; +} + +ReturnValue_t PersistentTmStore::handleDumpCmd(StorageManagerIF& ipcStore, + CommandMessage& cmdMessage) { + Clock::getClock_timeval(¤tTv); + store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage); + auto accessor = ipcStore.getData(storeId); + if (accessor.second.size() < 8) { + return returnvalue::FAILED; + } + uint32_t dumpFromUnixSeconds = 0; + uint32_t dumpUntilUnixSeconds = 0; + size_t size = 8; + SerializeAdapter::deSerialize(&dumpFromUnixSeconds, accessor.second.data(), &size, + SerializeIF::Endianness::NETWORK); + SerializeAdapter::deSerialize(&dumpUntilUnixSeconds, accessor.second.data() + 4, &size, + SerializeIF::Endianness::NETWORK); + ReturnValue_t result = startDumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds); + if (result == BUSY_DUMPING) { + triggerEvent(persTmStore::BUSY_DUMPING_EVENT); + return result; + } + return returnvalue::OK; +} + ReturnValue_t PersistentTmStore::startDumpFrom(uint32_t fromUnixSeconds) { return startDumpFromUpTo(fromUnixSeconds, currentTv.tv_sec); } diff --git a/mission/tmtc/PersistentTmStore.h b/mission/tmtc/PersistentTmStore.h index 4255b9d4..ccd6cbe6 100644 --- a/mission/tmtc/PersistentTmStore.h +++ b/mission/tmtc/PersistentTmStore.h @@ -14,6 +14,7 @@ #include "eive/eventSubsystemIds.h" #include "eive/resultClassIds.h" +#include "fsfw/ipc/CommandMessage.h" enum class RolloverInterval { MINUTELY, HOURLY, DAILY }; @@ -146,6 +147,8 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject { std::optional extractSuffix(const std::string& pathStr); bool updateBaseDir(); ReturnValue_t assignAndOrCreateMostRecentFile(); + ReturnValue_t handleDeletionCmd(StorageManagerIF& ipcStore, CommandMessage& cmdMessage); + ReturnValue_t handleDumpCmd(StorageManagerIF& ipcStore, CommandMessage& cmdMessage); }; #endif /* MISSION_TMTC_TMSTOREBACKEND_H_ */ From 05d6025dcc2c6988796c8c6bda640da872f9fc9e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 15 Nov 2023 15:41:51 +0100 Subject: [PATCH 28/69] bsp hosted fixes --- bsp_hosted/objectFactory.cpp | 11 ++++++----- linux/payload/plocSupvDefs.h | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) 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/linux/payload/plocSupvDefs.h b/linux/payload/plocSupvDefs.h index 4423bbb3..06dd7b8e 100644 --- a/linux/payload/plocSupvDefs.h +++ b/linux/payload/plocSupvDefs.h @@ -13,6 +13,7 @@ #include #include +#include "eive/eventSubsystemIds.h" #include "eive/resultClassIds.h" namespace supv { From 699cbb98ccbf07e01358d34564aa0086396bccaa Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 16 Nov 2023 11:01:56 +0100 Subject: [PATCH 29/69] add additional allowed subservice --- mission/tmtc/Service15TmStorage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/mission/tmtc/Service15TmStorage.cpp b/mission/tmtc/Service15TmStorage.cpp index 273c406b..efc9f2a6 100644 --- a/mission/tmtc/Service15TmStorage.cpp +++ b/mission/tmtc/Service15TmStorage.cpp @@ -17,6 +17,7 @@ Service15TmStorage::Service15TmStorage(object_id_t objectId, uint16_t apid, ReturnValue_t Service15TmStorage::isValidSubservice(uint8_t subservice) { switch (subservice) { case (Subservice::DELETE_UP_TO): + case (Subservice::DELETE_BY_TIME_RANGE): case (Subservice::START_BY_TIME_RANGE_RETRIEVAL): { return OK; } From 3be9cae8a5aaae8e3d57fe94685283516881f55d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 16 Nov 2023 16:57:36 +0100 Subject: [PATCH 30/69] variable cfg path --- bsp_q7s/CMakeLists.txt | 1 + bsp_q7s/acs/CMakeLists.txt | 1 + bsp_q7s/acs/StrConfigPathGetter.h | 23 +++++++++++++++++++++++ bsp_q7s/em/emObjectFactory.cpp | 2 +- bsp_q7s/fmObjectFactory.cpp | 2 +- bsp_q7s/objectFactory.cpp | 6 ++++-- bsp_q7s/objectFactory.h | 4 +++- mission/acs/str/ArcsecJsonParamBase.cpp | 2 +- mission/acs/str/ArcsecJsonParamBase.h | 2 +- mission/acs/str/StarTrackerHandler.cpp | 18 ++++++++++++------ mission/acs/str/StarTrackerHandler.h | 8 +++++--- mission/acs/str/strHelpers.h | 6 ++++++ 12 files changed, 59 insertions(+), 16 deletions(-) create mode 100644 bsp_q7s/acs/CMakeLists.txt create mode 100644 bsp_q7s/acs/StrConfigPathGetter.h diff --git a/bsp_q7s/CMakeLists.txt b/bsp_q7s/CMakeLists.txt index e3232363..0a1a9434 100644 --- a/bsp_q7s/CMakeLists.txt +++ b/bsp_q7s/CMakeLists.txt @@ -25,3 +25,4 @@ add_subdirectory(memory) add_subdirectory(callbacks) add_subdirectory(xadc) add_subdirectory(fs) +add_subdirectory(acs) diff --git a/bsp_q7s/acs/CMakeLists.txt b/bsp_q7s/acs/CMakeLists.txt new file mode 100644 index 00000000..87bf46f2 --- /dev/null +++ b/bsp_q7s/acs/CMakeLists.txt @@ -0,0 +1 @@ +# target_sources(${OBSW_NAME} PUBLIC ) diff --git a/bsp_q7s/acs/StrConfigPathGetter.h b/bsp_q7s/acs/StrConfigPathGetter.h new file mode 100644 index 00000000..58d6964c --- /dev/null +++ b/bsp_q7s/acs/StrConfigPathGetter.h @@ -0,0 +1,23 @@ +#include + +#include "bsp_q7s/fs/SdCardManager.h" +#include "mission/acs/str/strHelpers.h" + +class StrConfigPathGetter : public startracker::SdCardConfigPathGetter { + public: + StrConfigPathGetter(SdCardManager& sdcMan) : sdcMan(sdcMan) {} + + std::optional getCfgPath() override { + if (!sdcMan.isSdCardUsable(std::nullopt)) { + return std::nullopt; + } + if (sdcMan.getActiveSdCard() == sd::SdCard::SLOT_1) { + return std::string("/mnt/sd1/startracker/flight-config.json"); + } else { + return std::string("/mnt/sd0/startracker/flight-config.json"); + } + } + + private: + SdCardManager& sdcMan; +}; diff --git a/bsp_q7s/em/emObjectFactory.cpp b/bsp_q7s/em/emObjectFactory.cpp index 41dab3e6..65456d1e 100644 --- a/bsp_q7s/em/emObjectFactory.cpp +++ b/bsp_q7s/em/emObjectFactory.cpp @@ -152,7 +152,7 @@ void ObjectFactory::produce(void* args) { #endif #if OBSW_ADD_STAR_TRACKER == 1 - createStrComponents(pwrSwitcher); + createStrComponents(pwrSwitcher, *SdCardManager::instance()); #endif /* OBSW_ADD_STAR_TRACKER == 1 */ #if OBSW_ADD_PL_PCDU == 1 diff --git a/bsp_q7s/fmObjectFactory.cpp b/bsp_q7s/fmObjectFactory.cpp index b154ac52..05704abf 100644 --- a/bsp_q7s/fmObjectFactory.cpp +++ b/bsp_q7s/fmObjectFactory.cpp @@ -109,7 +109,7 @@ void ObjectFactory::produce(void* args) { createPayloadComponents(gpioComIF, *pwrSwitcher); #if OBSW_ADD_STAR_TRACKER == 1 - createStrComponents(pwrSwitcher); + createStrComponents(pwrSwitcher, *SdCardManager::instance()); #endif /* OBSW_ADD_STAR_TRACKER == 1 */ #if OBSW_ADD_CCSDS_IP_CORES == 1 diff --git a/bsp_q7s/objectFactory.cpp b/bsp_q7s/objectFactory.cpp index eadf70c6..f561e0f5 100644 --- a/bsp_q7s/objectFactory.cpp +++ b/bsp_q7s/objectFactory.cpp @@ -37,6 +37,7 @@ #include #include "OBSWConfig.h" +#include "bsp_q7s/acs/StrConfigPathGetter.h" #include "bsp_q7s/boardtest/Q7STestTask.h" #include "bsp_q7s/callbacks/gnssCallback.h" #include "bsp_q7s/callbacks/pcduSwitchCb.h" @@ -935,7 +936,7 @@ void ObjectFactory::createTestComponents(LinuxLibgpioIF* gpioComIF) { #endif } -void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher) { +void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher, SdCardManager& sdcMan) { auto* strAssy = new StrAssembly(objects::STR_ASSY); strAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM); auto* starTrackerCookie = @@ -949,9 +950,10 @@ void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher) { sif::error << "No valid Star Tracker parameter JSON file" << std::endl; } auto strFdir = new StrFdir(objects::STAR_TRACKER); + auto cfgGetter = new StrConfigPathGetter(sdcMan); auto starTracker = new StarTrackerHandler(objects::STAR_TRACKER, objects::STR_COM_IF, starTrackerCookie, - paramJsonFile, strComIF, power::PDU1_CH2_STAR_TRACKER_5V); + strComIF, power::PDU1_CH2_STAR_TRACKER_5V, *cfgGetter); starTracker->setPowerSwitcher(pwrSwitcher); starTracker->connectModeTreeParent(*strAssy); starTracker->setCustomFdir(strFdir); diff --git a/bsp_q7s/objectFactory.h b/bsp_q7s/objectFactory.h index b3dfa83b..2e10dd71 100644 --- a/bsp_q7s/objectFactory.h +++ b/bsp_q7s/objectFactory.h @@ -15,6 +15,8 @@ #include #include +#include "bsp_q7s/fs/SdCardManager.h" + class LinuxLibgpioIF; class SerialComIF; class SpiComIF; @@ -75,7 +77,7 @@ void createHeaterComponents(GpioIF* gpioIF, PowerSwitchIF* pwrSwitcher, HealthTa HeaterHandler*& heaterHandler); void createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets, const char* i2cDev); void createBpxBatteryComponent(bool enableHkSets, const char* i2cDev); -void createStrComponents(PowerSwitchIF* pwrSwitcher); +void createStrComponents(PowerSwitchIF* pwrSwitcher, SdCardManager& sdcMan); void createSolarArrayDeploymentComponents(PowerSwitchIF& pwrSwitcher, GpioIF& gpioIF); void createSyrlinksComponents(PowerSwitchIF* pwrSwitcher); void createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF& pwrSwitcher); diff --git a/mission/acs/str/ArcsecJsonParamBase.cpp b/mission/acs/str/ArcsecJsonParamBase.cpp index 58c54d30..704c23af 100644 --- a/mission/acs/str/ArcsecJsonParamBase.cpp +++ b/mission/acs/str/ArcsecJsonParamBase.cpp @@ -65,7 +65,7 @@ void ArcsecJsonParamBase::addSetParamHeader(uint8_t* buffer, uint8_t setId) { *(buffer + 1) = setId; } -ReturnValue_t ArcsecJsonParamBase::init(const std::string filename) { +ReturnValue_t ArcsecJsonParamBase::init(const std::string& filename) { ReturnValue_t result = returnvalue::OK; if (not std::filesystem::exists(filename)) { sif::warning << "ArcsecJsonParamBase::init: JSON file " << filename << " does not exist" diff --git a/mission/acs/str/ArcsecJsonParamBase.h b/mission/acs/str/ArcsecJsonParamBase.h index 4c4a7a90..b855a322 100644 --- a/mission/acs/str/ArcsecJsonParamBase.h +++ b/mission/acs/str/ArcsecJsonParamBase.h @@ -46,7 +46,7 @@ class ArcsecJsonParamBase { * @param return JSON_FILE_NOT_EXISTS if specified file does not exist, otherwise * returnvalue::OK */ - ReturnValue_t init(const std::string filename); + ReturnValue_t init(const std::string& filename); /** * @brief Fills a buffer with a parameter set diff --git a/mission/acs/str/StarTrackerHandler.cpp b/mission/acs/str/StarTrackerHandler.cpp index 541301f1..4ca85d56 100644 --- a/mission/acs/str/StarTrackerHandler.cpp +++ b/mission/acs/str/StarTrackerHandler.cpp @@ -24,8 +24,8 @@ extern "C" { std::atomic_bool JCFG_DONE(false); StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie, - const char* jsonFileStr, StrComHandler* strHelper, - power::Switch_t powerSwitch) + StrComHandler* strHelper, power::Switch_t powerSwitch, + startracker::SdCardConfigPathGetter& cfgPathGetter) : DeviceHandlerBase(objectId, comIF, comCookie), temperatureSet(this), versionSet(this), @@ -57,8 +57,8 @@ StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF, centroidsSet(this), contrastSet(this), strHelper(strHelper), - paramJsonFile(jsonFileStr), - powerSwitch(powerSwitch) { + powerSwitch(powerSwitch), + cfgPathGetter(cfgPathGetter) { if (comCookie == nullptr) { sif::error << "StarTrackerHandler: Invalid com cookie" << std::endl; } @@ -140,7 +140,13 @@ ReturnValue_t StarTrackerHandler::initialize() { // Spin up a thread to do the JSON initialization, takes 200-250 ms which would // delay whole satellite boot process. jcfgCountdown.resetTimer(); - jsonCfgTask = std::thread{setUpJsonCfgs, std::ref(jcfgs), paramJsonFile.c_str()}; + auto strCfgPath = cfgPathGetter.getCfgPath(); + if (strCfgPath.has_value()) { + jsonCfgTask = std::thread{setUpJsonCfgs, std::ref(jcfgs), strCfgPath.value()}; + } else { + // Simplified FDIR: Just continue as usual.. + JCFG_DONE = true; + } EventManagerIF* manager = ObjectManager::instance()->get(objects::EVENT_MANAGER); if (manager == nullptr) { @@ -928,7 +934,7 @@ void StarTrackerHandler::bootFirmware(Mode_t toMode) { } } -void StarTrackerHandler::setUpJsonCfgs(JsonConfigs& cfgs, const char* paramJsonFile) { +void StarTrackerHandler::setUpJsonCfgs(JsonConfigs& cfgs, std::string paramJsonFile) { cfgs.tracking.init(paramJsonFile); cfgs.logLevel.init(paramJsonFile); cfgs.logSubscription.init(paramJsonFile); diff --git a/mission/acs/str/StarTrackerHandler.h b/mission/acs/str/StarTrackerHandler.h index 3bfdc8fd..9a446065 100644 --- a/mission/acs/str/StarTrackerHandler.h +++ b/mission/acs/str/StarTrackerHandler.h @@ -42,8 +42,8 @@ class StarTrackerHandler : public DeviceHandlerBase { * to high to enable the device. */ StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie, - const char* jsonFileStr, StrComHandler* strHelper, - power::Switch_t powerSwitch); + StrComHandler* strHelper, power::Switch_t powerSwitch, + startracker::SdCardConfigPathGetter& cfgPathGetter); virtual ~StarTrackerHandler(); ReturnValue_t initialize() override; @@ -244,7 +244,7 @@ class StarTrackerHandler : public DeviceHandlerBase { Countdown jcfgCountdown = Countdown(250); bool commandExecuted = false; std::thread jsonCfgTask; - static void setUpJsonCfgs(JsonConfigs& cfgs, const char* paramJsonFile); + static void setUpJsonCfgs(JsonConfigs& cfgs, std::string paramJsonFile); std::string paramJsonFile; @@ -311,6 +311,8 @@ class StarTrackerHandler : public DeviceHandlerBase { std::set additionalRequestedTm{}; std::set::iterator currentSecondaryTmIter; + startracker::SdCardConfigPathGetter& cfgPathGetter; + /** * @brief Handles internal state */ diff --git a/mission/acs/str/strHelpers.h b/mission/acs/str/strHelpers.h index 808d6060..5337859f 100644 --- a/mission/acs/str/strHelpers.h +++ b/mission/acs/str/strHelpers.h @@ -14,6 +14,12 @@ namespace startracker { static const Submode_t SUBMODE_BOOTLOADER = 1; static const Submode_t SUBMODE_FIRMWARE = 2; +class SdCardConfigPathGetter { + public: + virtual ~SdCardConfigPathGetter() = default; + virtual std::optional getCfgPath() = 0; +}; + /** * @brief Returns the frame type field of a decoded frame. */ From 9010d1d2028b81aa69174848389d87a2351ea62e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 16 Nov 2023 17:07:47 +0100 Subject: [PATCH 31/69] add new command to reload the JSON file --- CHANGELOG.md | 18 +++++++++++++--- mission/acs/str/StarTrackerHandler.cpp | 30 +++++++++++++++++++------- mission/acs/str/StarTrackerHandler.h | 1 + mission/acs/str/strHelpers.h | 1 + 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74bd77e3..7ab784df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,18 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +## Fixed + +- STR config path was previously hardcoded to `/mnt/sd0/startracker/flight-config.json`. + A new abstraction was introduces which now uses the active SD card to build the correct + config path when initializing the star tracker. + +## Added + +- Introduced a new `RELOAD_JSON_CFG_FILE` command for the STR to reload the JSON configuration + data based on the current output of the config file path getter function. A reboot of the + device is still necessary to load the configuration to the STR. + # [v7.3.0] 2023-11-07 ## Changed @@ -696,7 +708,7 @@ This is the version which will fly on the satellite for the initial launch phase This gives other tasks some time to register the SD cards being unusable, and therefore provides a way for them to perform any re-initialization tasks necessary after SD card switches. - TCS controller now only has an OFF mode and an ON mode -- The TCS controller pauses operations related to the TCS board assembly (reading sensors and +- The TCS controller pauses operations related to the TCS board assembly (reading sensors and the primary control loop) while a TCS board recovery is on-going. - Allow specifying custom OBSW update filename. This allowed keeping a cleaner file structure where each update has a name including the version @@ -1761,8 +1773,8 @@ Syrlinks PR: PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/353 - Syrlinks Handler: Read RX frequency shift as 24 bit signed number now. Also include validity handling for datasets. PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/350 -- `GyroADIS1650XHandler`: Changed calculation of angular rate to be sensitivity based instead of - max. range based, as previous fix still left an margin of error between ADIS16505 sensors +- `GyroADIS1650XHandler`: Changed calculation of angular rate to be sensitivity based instead of + max. range based, as previous fix still left an margin of error between ADIS16505 sensors and L3GD20 sensors. PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/346 diff --git a/mission/acs/str/StarTrackerHandler.cpp b/mission/acs/str/StarTrackerHandler.cpp index 4ca85d56..98529b29 100644 --- a/mission/acs/str/StarTrackerHandler.cpp +++ b/mission/acs/str/StarTrackerHandler.cpp @@ -139,14 +139,7 @@ ReturnValue_t StarTrackerHandler::initialize() { // Spin up a thread to do the JSON initialization, takes 200-250 ms which would // delay whole satellite boot process. - jcfgCountdown.resetTimer(); - auto strCfgPath = cfgPathGetter.getCfgPath(); - if (strCfgPath.has_value()) { - jsonCfgTask = std::thread{setUpJsonCfgs, std::ref(jcfgs), strCfgPath.value()}; - } else { - // Simplified FDIR: Just continue as usual.. - JCFG_DONE = true; - } + reloadJsonCfgFile(); EventManagerIF* manager = ObjectManager::instance()->get(objects::EVENT_MANAGER); if (manager == nullptr) { @@ -175,6 +168,18 @@ ReturnValue_t StarTrackerHandler::initialize() { return returnvalue::OK; } +bool StarTrackerHandler::reloadJsonCfgFile() { + jcfgCountdown.resetTimer(); + auto strCfgPath = cfgPathGetter.getCfgPath(); + if (strCfgPath.has_value()) { + jsonCfgTask = std::thread{setUpJsonCfgs, std::ref(jcfgs), strCfgPath.value()}; + return true; + } + // Simplified FDIR: Just continue as usual.. + JCFG_DONE = true; + return false; +} + ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size) { ReturnValue_t result = returnvalue::OK; @@ -193,6 +198,15 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu addSecondaryTmForNormalMode(idToAdd); return EXECUTION_FINISHED; } + case (startracker::RELOAD_JSON_CFG_FILE): { + // It should be noted that this just reloads the JSON config structure in memory from the + // JSON file. The configuration still needs to be sent to the STR. The easiest way to achieve + // this is to simply reboot the device after a reload. + if (reloadJsonCfgFile()) { + return HasActionsIF::EXECUTION_FINISHED; + } + return returnvalue::FAILED; + } case (startracker::RESET_SECONDARY_TM_SET): { resetSecondaryTmSet(); return EXECUTION_FINISHED; diff --git a/mission/acs/str/StarTrackerHandler.h b/mission/acs/str/StarTrackerHandler.h index 9a446065..24ea55bc 100644 --- a/mission/acs/str/StarTrackerHandler.h +++ b/mission/acs/str/StarTrackerHandler.h @@ -544,6 +544,7 @@ class StarTrackerHandler : public DeviceHandlerBase { void doNormalTransition(Mode_t modeFrom, Submode_t subModeFrom); void bootFirmware(Mode_t toMode); void bootBootloader(); + bool reloadJsonCfgFile(); }; #endif /* MISSION_DEVICES_STARTRACKERHANDLER_H_ */ diff --git a/mission/acs/str/strHelpers.h b/mission/acs/str/strHelpers.h index 5337859f..8f83331d 100644 --- a/mission/acs/str/strHelpers.h +++ b/mission/acs/str/strHelpers.h @@ -387,6 +387,7 @@ static constexpr DeviceCommandId_t REQ_CENTROIDS = 94; static constexpr DeviceCommandId_t ADD_SECONDARY_TM_TO_NORMAL_MODE = 95; static constexpr DeviceCommandId_t RESET_SECONDARY_TM_SET = 96; static constexpr DeviceCommandId_t READ_SECONDARY_TM_SET = 97; +static constexpr DeviceCommandId_t RELOAD_JSON_CFG_FILE = 100; static const DeviceCommandId_t NONE = 0xFFFFFFFF; static const uint32_t VERSION_SET_ID = REQ_VERSION; From 5348188f6b4267f8666948369987a11de8d25e3c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 16 Nov 2023 17:11:19 +0100 Subject: [PATCH 32/69] changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74bd77e3..66473ad9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,11 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +## Added + +- Added new PUS 15 subservice `DELETE_BY_TIME_RANGE` which allows to also specify a deletion + start time when deleting packets from the persistent TM store. + # [v7.3.0] 2023-11-07 ## Changed From ed8f2c75bffe72f2809c800800d1455cca5d102d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 11:28:08 +0100 Subject: [PATCH 33/69] this should do the job --- mission/payload/PayloadPcduHandler.cpp | 75 ++++++++++++++---------- mission/payload/PayloadPcduHandler.h | 2 + mission/payload/payloadPcduDefinitions.h | 8 ++- 3 files changed, 52 insertions(+), 33 deletions(-) diff --git a/mission/payload/PayloadPcduHandler.cpp b/mission/payload/PayloadPcduHandler.cpp index b3b71aea..06c93842 100644 --- a/mission/payload/PayloadPcduHandler.cpp +++ b/mission/payload/PayloadPcduHandler.cpp @@ -590,6 +590,9 @@ ReturnValue_t PayloadPcduHandler::checkModeCommand(Mode_t commandedMode, Submode ReturnValue_t PayloadPcduHandler::isModeCombinationValid(Mode_t mode, Submode_t submode) { using namespace plpcdu; if (mode == MODE_NORMAL) { + if (disableChannelOrderCheck) { + return returnvalue::OK; + } uint8_t dhbSubmode = getSubmode(); diffMask = submode ^ dhbSubmode; // Also deals with the case where the mode is MODE_ON, submode should be 0 here @@ -637,56 +640,68 @@ ReturnValue_t PayloadPcduHandler::getParameter(uint8_t domainId, uint8_t uniqueI uint16_t startAtIndex) { using namespace plpcdu; switch (uniqueId) { - case (PlPcduParamIds::NEG_V_LOWER_BOUND): - case (PlPcduParamIds::NEG_V_UPPER_BOUND): - case (PlPcduParamIds::DRO_U_LOWER_BOUND): - case (PlPcduParamIds::DRO_U_UPPER_BOUND): - case (PlPcduParamIds::DRO_I_UPPER_BOUND): - case (PlPcduParamIds::X8_U_LOWER_BOUND): - case (PlPcduParamIds::X8_U_UPPER_BOUND): - case (PlPcduParamIds::X8_I_UPPER_BOUND): - case (PlPcduParamIds::TX_U_LOWER_BOUND): - case (PlPcduParamIds::TX_U_UPPER_BOUND): - case (PlPcduParamIds::TX_I_UPPER_BOUND): - case (PlPcduParamIds::MPA_U_LOWER_BOUND): - case (PlPcduParamIds::MPA_U_UPPER_BOUND): - case (PlPcduParamIds::MPA_I_UPPER_BOUND): - case (PlPcduParamIds::HPA_U_LOWER_BOUND): - case (PlPcduParamIds::HPA_U_UPPER_BOUND): - case (PlPcduParamIds::HPA_I_UPPER_BOUND): - case (PlPcduParamIds::SSR_TO_DRO_WAIT_TIME): - case (PlPcduParamIds::DRO_TO_X8_WAIT_TIME): - case (PlPcduParamIds::X8_TO_TX_WAIT_TIME): - case (PlPcduParamIds::TX_TO_MPA_WAIT_TIME): - case (PlPcduParamIds::MPA_TO_HPA_WAIT_TIME): { - handleDoubleParamUpdate(PARAM_KEY_MAP[static_cast(uniqueId)], - parameterWrapper, newValues); + case (PlPcduParamId::NEG_V_LOWER_BOUND): + case (PlPcduParamId::NEG_V_UPPER_BOUND): + case (PlPcduParamId::DRO_U_LOWER_BOUND): + case (PlPcduParamId::DRO_U_UPPER_BOUND): + case (PlPcduParamId::DRO_I_UPPER_BOUND): + case (PlPcduParamId::X8_U_LOWER_BOUND): + case (PlPcduParamId::X8_U_UPPER_BOUND): + case (PlPcduParamId::X8_I_UPPER_BOUND): + case (PlPcduParamId::TX_U_LOWER_BOUND): + case (PlPcduParamId::TX_U_UPPER_BOUND): + case (PlPcduParamId::TX_I_UPPER_BOUND): + case (PlPcduParamId::MPA_U_LOWER_BOUND): + case (PlPcduParamId::MPA_U_UPPER_BOUND): + case (PlPcduParamId::MPA_I_UPPER_BOUND): + case (PlPcduParamId::HPA_U_LOWER_BOUND): + case (PlPcduParamId::HPA_U_UPPER_BOUND): + case (PlPcduParamId::HPA_I_UPPER_BOUND): + case (PlPcduParamId::SSR_TO_DRO_WAIT_TIME): + case (PlPcduParamId::DRO_TO_X8_WAIT_TIME): + case (PlPcduParamId::X8_TO_TX_WAIT_TIME): + case (PlPcduParamId::TX_TO_MPA_WAIT_TIME): + case (PlPcduParamId::MPA_TO_HPA_WAIT_TIME): { + handleDoubleParamUpdate(PARAM_KEY_MAP[static_cast(uniqueId)], parameterWrapper, + newValues); break; } - case (PlPcduParamIds::INJECT_SSR_TO_DRO_FAILURE): { + case (PlPcduParamId::INJECT_SSR_TO_DRO_FAILURE): { ssrToDroInjectionRequested = true; break; } - case (PlPcduParamIds::INJECT_DRO_TO_X8_FAILURE): { + case (PlPcduParamId::INJECT_DRO_TO_X8_FAILURE): { droToX8InjectionRequested = true; break; } - case (PlPcduParamIds::INJECT_X8_TO_TX_FAILURE): { + case (PlPcduParamId::INJECT_X8_TO_TX_FAILURE): { x8ToTxInjectionRequested = true; break; } - case (PlPcduParamIds::INJECT_TX_TO_MPA_FAILURE): { + case (PlPcduParamId::INJECT_TX_TO_MPA_FAILURE): { txToMpaInjectionRequested = true; break; } - case (PlPcduParamIds::INJECT_MPA_TO_HPA_FAILURE): { + case (PlPcduParamId::INJECT_MPA_TO_HPA_FAILURE): { mpaToHpaInjectionRequested = true; break; } - case (PlPcduParamIds::INJECT_ALL_ON_FAILURE): { + case (PlPcduParamId::INJECT_ALL_ON_FAILURE): { allOnInjectRequested = true; break; } + case (PlPcduParamId::DISABLE_ORDER_CHECK_CHANNELS): { + uint8_t newValue = 0; + ReturnValue_t result = newValues->getElement(&newValue); + if (result != returnvalue::OK) { + return result; + } + if(newValue > 1) { + return HasParametersIF::INVALID_VALUE; + } + parameterWrapper->set(&disableChannelOrderCheck); + break; + } default: { return DeviceHandlerBase::getParameter(domainId, uniqueId, parameterWrapper, newValues, startAtIndex); diff --git a/mission/payload/PayloadPcduHandler.h b/mission/payload/PayloadPcduHandler.h index d48d0f89..088ef8b9 100644 --- a/mission/payload/PayloadPcduHandler.h +++ b/mission/payload/PayloadPcduHandler.h @@ -137,6 +137,8 @@ class PayloadPcduHandler : public DeviceHandlerBase { PoolEntry({0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}); PoolEntry tempC = PoolEntry({0.0}); + uint8_t disableChannelOrderCheck = false; + void updateSwitchGpio(gpioId_t id, gpio::Levels level); void doTransition(Mode_t modeFrom, Submode_t subModeFrom) override; diff --git a/mission/payload/payloadPcduDefinitions.h b/mission/payload/payloadPcduDefinitions.h index e6c7b653..dbd38a9d 100644 --- a/mission/payload/payloadPcduDefinitions.h +++ b/mission/payload/payloadPcduDefinitions.h @@ -35,7 +35,7 @@ enum PlPcduAdcChannels : uint8_t { NUM_CHANNELS = 12 }; -enum PlPcduParamIds : uint8_t { +enum PlPcduParamId : uint8_t { NEG_V_LOWER_BOUND = 0, NEG_V_UPPER_BOUND = 1, DRO_U_LOWER_BOUND = 2, @@ -65,10 +65,12 @@ enum PlPcduParamIds : uint8_t { INJECT_X8_TO_TX_FAILURE = 32, INJECT_TX_TO_MPA_FAILURE = 33, INJECT_MPA_TO_HPA_FAILURE = 34, - INJECT_ALL_ON_FAILURE = 35 + INJECT_ALL_ON_FAILURE = 35, + + DISABLE_ORDER_CHECK_CHANNELS = 40 }; -static std::map PARAM_KEY_MAP = { +static std::map PARAM_KEY_MAP = { {NEG_V_LOWER_BOUND, "negVoltLowerBound"}, {NEG_V_UPPER_BOUND, "negVoltUpperBound"}, {DRO_U_LOWER_BOUND, "droVoltLowerBound"}, {DRO_U_UPPER_BOUND, "droVoltUpperBound"}, {DRO_I_UPPER_BOUND, "droCurrUpperBound"}, {X8_U_LOWER_BOUND, "x8VoltLowerBound"}, From 949401e2470a2256531d7984557c122c21a056ad Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 12:51:39 +0100 Subject: [PATCH 34/69] less trashy mode checker --- fsfw | 2 +- mission/payload/PayloadPcduHandler.cpp | 76 ++++++++++++++++---------- mission/payload/PayloadPcduHandler.h | 11 +++- 3 files changed, 57 insertions(+), 32 deletions(-) diff --git a/fsfw b/fsfw index cc3e64e7..41d67bff 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit cc3e64e70d90f6a2b5c59215b2569c1771e890f0 +Subproject commit 41d67bff639192afa2e18a23db6801c75b4fea88 diff --git a/mission/payload/PayloadPcduHandler.cpp b/mission/payload/PayloadPcduHandler.cpp index 06c93842..5530e459 100644 --- a/mission/payload/PayloadPcduHandler.cpp +++ b/mission/payload/PayloadPcduHandler.cpp @@ -4,6 +4,7 @@ #include "OBSWConfig.h" #include "fsfw/thermal/tcsDefinitions.h" +#include "mission/payload/payloadPcduDefinitions.h" #ifdef XIPHOS_Q7S #include @@ -576,6 +577,7 @@ void PayloadPcduHandler::performOperationHook() { checkJsonFileInit(); } ReturnValue_t PayloadPcduHandler::checkModeCommand(Mode_t commandedMode, Submode_t commandedSubmode, uint32_t* msToReachTheMode) { + using namespace plpcdu; if (commandedMode != MODE_OFF) { PoolReadGuard pg(&enablePl); if (pg.getReadResult() == returnvalue::OK) { @@ -584,48 +586,62 @@ ReturnValue_t PayloadPcduHandler::checkModeCommand(Mode_t commandedMode, Submode } } } - return DeviceHandlerBase::checkModeCommand(commandedMode, commandedSubmode, msToReachTheMode); -} - -ReturnValue_t PayloadPcduHandler::isModeCombinationValid(Mode_t mode, Submode_t submode) { - using namespace plpcdu; - if (mode == MODE_NORMAL) { + if (commandedMode == MODE_NORMAL) { + uint8_t dhbSubmode = getSubmode(); + diffMask = commandedSubmode ^ dhbSubmode; + // For all higher level modes, SSR needs to be on. This is to ensure we have valid ADC + // measurements + if ((droOnForSubmode(commandedSubmode) or x8OnForSubmode(commandedSubmode) or + txOnForSubmode(commandedSubmode) or mpaOnForSubmode(commandedSubmode) or + hpaOnForSubmode(commandedSubmode)) and + not ssrOnForSubmode(dhbSubmode)) { + } if (disableChannelOrderCheck) { return returnvalue::OK; } - uint8_t dhbSubmode = getSubmode(); - diffMask = submode ^ dhbSubmode; - // Also deals with the case where the mode is MODE_ON, submode should be 0 here - if ((((submode >> SOLID_STATE_RELAYS_ADC_ON) & 0b1) == SOLID_STATE_RELAYS_ADC_ON) and - (getMode() == MODE_NORMAL and dhbSubmode != ALL_OFF_SUBMODE)) { + if (x8OnForSubmode(commandedSubmode) and not droOnForSubmode(dhbSubmode)) { return TRANS_NOT_ALLOWED; } - if (((((submode >> DRO_ON) & 1) == 1) and - ((dhbSubmode & 0b1) != (1 << SOLID_STATE_RELAYS_ADC_ON)))) { + if (txOnForSubmode(commandedSubmode) and + (not droOnForSubmode(dhbSubmode) or not x8OnForSubmode(dhbSubmode))) { return TRANS_NOT_ALLOWED; } - if ((((submode >> X8_ON) & 1) == 1) and - ((dhbSubmode & 0b11) != ((1 << SOLID_STATE_RELAYS_ADC_ON) | (1 << DRO_ON)))) { + if (txOnForSubmode(commandedSubmode) and + (not droOnForSubmode(dhbSubmode) or not x8OnForSubmode(dhbSubmode) or + not txOnForSubmode(dhbSubmode))) { return TRANS_NOT_ALLOWED; } - if (((((submode >> TX_ON) & 1) == 1) and - ((dhbSubmode & 0b111) != - ((1 << X8_ON) | (1 << DRO_ON) | (1 << SOLID_STATE_RELAYS_ADC_ON))))) { - return TRANS_NOT_ALLOWED; - } - if ((((submode >> MPA_ON) & 1) == 1 and - ((dhbSubmode & 0b1111) != - ((1 << TX_ON) | (1 << X8_ON) | (1 << DRO_ON) | (1 << SOLID_STATE_RELAYS_ADC_ON))))) { - return TRANS_NOT_ALLOWED; - } - if ((((submode >> HPA_ON) & 1) == 1 and - ((dhbSubmode & 0b11111) != ((1 << MPA_ON) | (1 << TX_ON) | (1 << X8_ON) | (1 << DRO_ON) | - (1 << SOLID_STATE_RELAYS_ADC_ON))))) { + if (hpaOnForSubmode(commandedSubmode) and + (not droOnForSubmode(dhbSubmode) or not x8OnForSubmode(dhbSubmode) or + not txOnForSubmode(dhbSubmode) or not mpaOnForSubmode(dhbSubmode))) { return TRANS_NOT_ALLOWED; } return returnvalue::OK; } - return DeviceHandlerBase::isModeCombinationValid(mode, submode); + return DeviceHandlerBase::checkModeCommand(commandedMode, commandedSubmode, msToReachTheMode); +} + +bool PayloadPcduHandler::ssrOnForSubmode(uint8_t submode) { + return (submode & plpcdu::SOLID_STATE_RELAYS_ADC_ON) == plpcdu::SOLID_STATE_RELAYS_ADC_ON; +} +bool PayloadPcduHandler::droOnForSubmode(uint8_t submode) { + return (submode & plpcdu::DRO_ON) == plpcdu::DRO_ON; +} + +bool PayloadPcduHandler::x8OnForSubmode(uint8_t submode) { + return (submode & plpcdu::X8_ON) == plpcdu::X8_ON; +} + +bool PayloadPcduHandler::txOnForSubmode(uint8_t submode) { + return (submode & plpcdu::TX_ON) == plpcdu::TX_ON; +} + +bool PayloadPcduHandler::mpaOnForSubmode(uint8_t submode) { + return (submode & plpcdu::MPA_ON) == plpcdu::MPA_ON; +} + +bool PayloadPcduHandler::hpaOnForSubmode(uint8_t submode) { + return (submode & plpcdu::HPA_ON) == plpcdu::HPA_ON; } ReturnValue_t PayloadPcduHandler::serializeFloat(uint32_t& param, float val) { @@ -696,7 +712,7 @@ ReturnValue_t PayloadPcduHandler::getParameter(uint8_t domainId, uint8_t uniqueI if (result != returnvalue::OK) { return result; } - if(newValue > 1) { + if (newValue > 1) { return HasParametersIF::INVALID_VALUE; } parameterWrapper->set(&disableChannelOrderCheck); diff --git a/mission/payload/PayloadPcduHandler.h b/mission/payload/PayloadPcduHandler.h index 088ef8b9..da9da1e1 100644 --- a/mission/payload/PayloadPcduHandler.h +++ b/mission/payload/PayloadPcduHandler.h @@ -137,6 +137,10 @@ class PayloadPcduHandler : public DeviceHandlerBase { PoolEntry({0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}); PoolEntry tempC = PoolEntry({0.0}); + /** + * This parameter disables all checks for the channels except the SSR on check. The SSR on check + * is kept to ensure that there is a common start point where the ADC is enabled. + */ uint8_t disableChannelOrderCheck = false; void updateSwitchGpio(gpioId_t id, gpio::Levels level); @@ -157,7 +161,6 @@ class PayloadPcduHandler : public DeviceHandlerBase { uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) override; - ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) override; ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues, uint16_t startAtIndex) override; @@ -179,6 +182,12 @@ class PayloadPcduHandler : public DeviceHandlerBase { pwrctrl::EnablePl enablePl = pwrctrl::EnablePl(objects::POWER_CONTROLLER); ReturnValue_t checkModeCommand(Mode_t commandedMode, Submode_t commandedSubmode, uint32_t* msToReachTheMode) override; + static bool ssrOnForSubmode(uint8_t submode); + static bool droOnForSubmode(uint8_t submode); + static bool x8OnForSubmode(uint8_t submode); + static bool txOnForSubmode(uint8_t submode); + static bool mpaOnForSubmode(uint8_t submode); + static bool hpaOnForSubmode(uint8_t submode); }; #endif /* LINUX_DEVICES_PLPCDUHANDLER_H_ */ From bd383cfe0482ab6dee70a433a5dcd7b2e1849f0d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 12:54:36 +0100 Subject: [PATCH 35/69] bugfix --- mission/payload/PayloadPcduHandler.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mission/payload/PayloadPcduHandler.cpp b/mission/payload/PayloadPcduHandler.cpp index 5530e459..bba80901 100644 --- a/mission/payload/PayloadPcduHandler.cpp +++ b/mission/payload/PayloadPcduHandler.cpp @@ -622,26 +622,26 @@ ReturnValue_t PayloadPcduHandler::checkModeCommand(Mode_t commandedMode, Submode } bool PayloadPcduHandler::ssrOnForSubmode(uint8_t submode) { - return (submode & plpcdu::SOLID_STATE_RELAYS_ADC_ON) == plpcdu::SOLID_STATE_RELAYS_ADC_ON; + return submode & (1 << plpcdu::SOLID_STATE_RELAYS_ADC_ON); } bool PayloadPcduHandler::droOnForSubmode(uint8_t submode) { - return (submode & plpcdu::DRO_ON) == plpcdu::DRO_ON; + return submode & (1 << plpcdu::DRO_ON); } bool PayloadPcduHandler::x8OnForSubmode(uint8_t submode) { - return (submode & plpcdu::X8_ON) == plpcdu::X8_ON; + return submode & (1 << plpcdu::X8_ON); } bool PayloadPcduHandler::txOnForSubmode(uint8_t submode) { - return (submode & plpcdu::TX_ON) == plpcdu::TX_ON; + return submode & (1 << plpcdu::TX_ON); } bool PayloadPcduHandler::mpaOnForSubmode(uint8_t submode) { - return (submode & plpcdu::MPA_ON) == plpcdu::MPA_ON; + return submode & (1 << plpcdu::MPA_ON); } bool PayloadPcduHandler::hpaOnForSubmode(uint8_t submode) { - return (submode & plpcdu::HPA_ON) == plpcdu::HPA_ON; + return submode & (1 << plpcdu::HPA_ON); } ReturnValue_t PayloadPcduHandler::serializeFloat(uint32_t& param, float val) { From 8c51f53a269083bb62bb33cb8490968170ac750f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 12:55:05 +0100 Subject: [PATCH 36/69] bump fsfw --- fsfw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsfw b/fsfw index cc3e64e7..41d67bff 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit cc3e64e70d90f6a2b5c59215b2569c1771e890f0 +Subproject commit 41d67bff639192afa2e18a23db6801c75b4fea88 From a648b4be37422b82d8a3a89c57ec191fdd5f6fc9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 14:17:19 +0100 Subject: [PATCH 37/69] better thread and startup handling --- mission/acs/str/StarTrackerHandler.cpp | 34 +++++++++++++++++++------- mission/acs/str/StarTrackerHandler.h | 3 ++- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/mission/acs/str/StarTrackerHandler.cpp b/mission/acs/str/StarTrackerHandler.cpp index 98529b29..9e7d3b5e 100644 --- a/mission/acs/str/StarTrackerHandler.cpp +++ b/mission/acs/str/StarTrackerHandler.cpp @@ -82,17 +82,13 @@ void StarTrackerHandler::doStartUp() { // the device handler's submode to the star tracker's mode return; case StartupState::DONE: - if (jcfgCountdown.isBusy()) { + if (!JCFG_DONE) { startupState = StartupState::WAIT_JCFG; return; } startupState = StartupState::IDLE; break; case StartupState::WAIT_JCFG: { - if (jcfgCountdown.hasTimedOut()) { - startupState = StartupState::IDLE; - break; - } return; } default: @@ -172,6 +168,7 @@ bool StarTrackerHandler::reloadJsonCfgFile() { jcfgCountdown.resetTimer(); auto strCfgPath = cfgPathGetter.getCfgPath(); if (strCfgPath.has_value()) { + jcfgPending = true; jsonCfgTask = std::thread{setUpJsonCfgs, std::ref(jcfgs), strCfgPath.value()}; return true; } @@ -199,13 +196,14 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu return EXECUTION_FINISHED; } case (startracker::RELOAD_JSON_CFG_FILE): { + if (jcfgPending) { + return HasActionsIF::IS_BUSY; + } // It should be noted that this just reloads the JSON config structure in memory from the // JSON file. The configuration still needs to be sent to the STR. The easiest way to achieve // this is to simply reboot the device after a reload. - if (reloadJsonCfgFile()) { - return HasActionsIF::EXECUTION_FINISHED; - } - return returnvalue::FAILED; + reloadJsonCfgFile(); + return returnvalue::OK; } case (startracker::RESET_SECONDARY_TM_SET): { resetSecondaryTmSet(); @@ -355,6 +353,24 @@ void StarTrackerHandler::performOperationHook() { break; } } + if (jcfgPending) { + if (JCFG_DONE) { + auto iter = deviceCommandMap.find(startracker::RELOAD_JSON_CFG_FILE); + if (iter != deviceCommandMap.end()) { + if (iter->second.sendReplyTo != MessageQueueIF::NO_QUEUE) { + actionHelper.finish(true, iter->second.sendReplyTo, startracker::RELOAD_JSON_CFG_FILE); + } + } + jsonCfgTask.join(); + jcfgPending = false; + } else if (jcfgCountdown.hasTimedOut()) { + auto iter = deviceCommandMap.find(startracker::RELOAD_JSON_CFG_FILE); + if (iter->second.sendReplyTo != MessageQueueIF::NO_QUEUE) { + actionHelper.finish(false, iter->second.sendReplyTo, startracker::RELOAD_JSON_CFG_FILE, + returnvalue::FAILED); + } + } + } } Submode_t StarTrackerHandler::getInitialSubmode() { return startracker::SUBMODE_BOOTLOADER; } diff --git a/mission/acs/str/StarTrackerHandler.h b/mission/acs/str/StarTrackerHandler.h index 24ea55bc..ad37557d 100644 --- a/mission/acs/str/StarTrackerHandler.h +++ b/mission/acs/str/StarTrackerHandler.h @@ -240,8 +240,9 @@ class StarTrackerHandler : public DeviceHandlerBase { Subscription subscription; AutoThreshold autoThreshold; }; + bool jcfgPending = false; JsonConfigs jcfgs; - Countdown jcfgCountdown = Countdown(250); + Countdown jcfgCountdown = Countdown(1000); bool commandExecuted = false; std::thread jsonCfgTask; static void setUpJsonCfgs(JsonConfigs& cfgs, std::string paramJsonFile); From f9d2d35f86cd27adccb634ca36f4c2231cc28211 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 14:34:15 +0100 Subject: [PATCH 38/69] this is stupid --- mission/acs/str/StarTrackerHandler.cpp | 41 +++++++++++++------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/mission/acs/str/StarTrackerHandler.cpp b/mission/acs/str/StarTrackerHandler.cpp index 9e7d3b5e..0b58d61e 100644 --- a/mission/acs/str/StarTrackerHandler.cpp +++ b/mission/acs/str/StarTrackerHandler.cpp @@ -169,6 +169,7 @@ bool StarTrackerHandler::reloadJsonCfgFile() { auto strCfgPath = cfgPathGetter.getCfgPath(); if (strCfgPath.has_value()) { jcfgPending = true; + JCFG_DONE = false; jsonCfgTask = std::thread{setUpJsonCfgs, std::ref(jcfgs), strCfgPath.value()}; return true; } @@ -182,6 +183,21 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu ReturnValue_t result = returnvalue::OK; switch (actionId) { + case (startracker::RELOAD_JSON_CFG_FILE): { + if (jcfgPending) { + return HasActionsIF::IS_BUSY; + } + // It should be noted that this just reloads the JSON config structure in memory from the + // JSON file. The configuration still needs to be sent to the STR. The easiest way to achieve + // this is to simply reboot the device after a reload. + if(reloadJsonCfgFile()) { + // Could trigger this after the thread has finished, but the base class does not accept + // commands for buildCommandForCommand when it is OFF. I am sure there is way to solve + // this, but I don't care anymore. This is fine. + return HasActionsIF::EXECUTION_FINISHED; + }; + return returnvalue::OK; + } case (startracker::ADD_SECONDARY_TM_TO_NORMAL_MODE): { if (size < 4) { return HasActionsIF::INVALID_PARAMETERS; @@ -195,16 +211,6 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu addSecondaryTmForNormalMode(idToAdd); return EXECUTION_FINISHED; } - case (startracker::RELOAD_JSON_CFG_FILE): { - if (jcfgPending) { - return HasActionsIF::IS_BUSY; - } - // It should be noted that this just reloads the JSON config structure in memory from the - // JSON file. The configuration still needs to be sent to the STR. The easiest way to achieve - // this is to simply reboot the device after a reload. - reloadJsonCfgFile(); - return returnvalue::OK; - } case (startracker::RESET_SECONDARY_TM_SET): { resetSecondaryTmSet(); return EXECUTION_FINISHED; @@ -355,20 +361,11 @@ void StarTrackerHandler::performOperationHook() { } if (jcfgPending) { if (JCFG_DONE) { - auto iter = deviceCommandMap.find(startracker::RELOAD_JSON_CFG_FILE); - if (iter != deviceCommandMap.end()) { - if (iter->second.sendReplyTo != MessageQueueIF::NO_QUEUE) { - actionHelper.finish(true, iter->second.sendReplyTo, startracker::RELOAD_JSON_CFG_FILE); - } - } jsonCfgTask.join(); jcfgPending = false; + JCFG_DONE = false; } else if (jcfgCountdown.hasTimedOut()) { - auto iter = deviceCommandMap.find(startracker::RELOAD_JSON_CFG_FILE); - if (iter->second.sendReplyTo != MessageQueueIF::NO_QUEUE) { - actionHelper.finish(false, iter->second.sendReplyTo, startracker::RELOAD_JSON_CFG_FILE, - returnvalue::FAILED); - } + JCFG_DONE = false; } } } @@ -549,6 +546,7 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi rawPacket = commandBuffer; return returnvalue::OK; } + case (startracker::REQ_TIME): { prepareTimeRequest(); return returnvalue::OK; @@ -762,6 +760,7 @@ void StarTrackerHandler::fillCommandAndReplyMap() { startracker::MAX_FRAME_SIZE * 2 + 2); this->insertInCommandMap(startracker::UPLOAD_IMAGE); this->insertInCommandMap(startracker::DOWNLOAD_IMAGE); + this->insertInCommandMap(startracker::RELOAD_JSON_CFG_FILE); this->insertInCommandAndReplyMap(startracker::REQ_POWER, 3, &powerSet, startracker::MAX_FRAME_SIZE * 2 + 2); this->insertInCommandAndReplyMap(startracker::REQ_INTERFACE, 3, &interfaceSet, From cdad099f32e14771209e70204b096b7987d1fc67 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 14:54:21 +0100 Subject: [PATCH 39/69] PLEASE WORK --- mission/acs/str/StarTrackerHandler.cpp | 39 ++++++++++++++++---------- mission/acs/str/StarTrackerHandler.h | 5 +++- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/mission/acs/str/StarTrackerHandler.cpp b/mission/acs/str/StarTrackerHandler.cpp index 0b58d61e..79f29a7f 100644 --- a/mission/acs/str/StarTrackerHandler.cpp +++ b/mission/acs/str/StarTrackerHandler.cpp @@ -5,6 +5,8 @@ #include #include +#include "fsfw/ipc/MessageQueueIF.h" + extern "C" { #include #include @@ -183,21 +185,6 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu ReturnValue_t result = returnvalue::OK; switch (actionId) { - case (startracker::RELOAD_JSON_CFG_FILE): { - if (jcfgPending) { - return HasActionsIF::IS_BUSY; - } - // It should be noted that this just reloads the JSON config structure in memory from the - // JSON file. The configuration still needs to be sent to the STR. The easiest way to achieve - // this is to simply reboot the device after a reload. - if(reloadJsonCfgFile()) { - // Could trigger this after the thread has finished, but the base class does not accept - // commands for buildCommandForCommand when it is OFF. I am sure there is way to solve - // this, but I don't care anymore. This is fine. - return HasActionsIF::EXECUTION_FINISHED; - }; - return returnvalue::OK; - } case (startracker::ADD_SECONDARY_TM_TO_NORMAL_MODE): { if (size < 4) { return HasActionsIF::INVALID_PARAMETERS; @@ -361,11 +348,21 @@ void StarTrackerHandler::performOperationHook() { } if (jcfgPending) { if (JCFG_DONE) { + sif::debug << "jcfg fucking done" << std::endl; jsonCfgTask.join(); jcfgPending = false; JCFG_DONE = false; + auto iter = deviceCommandMap.find(startracker::RELOAD_JSON_CFG_FILE); + if (iter != deviceCommandMap.end() and iter->second.sendReplyTo != MessageQueueIF::NO_QUEUE) { + sif::debug << "jcfg sending finished" << std::endl; + actionHelper.finish(true, iter->second.sendReplyTo, startracker::RELOAD_JSON_CFG_FILE); + } } else if (jcfgCountdown.hasTimedOut()) { JCFG_DONE = false; + auto iter = deviceCommandMap.find(startracker::RELOAD_JSON_CFG_FILE); + if (iter != deviceCommandMap.end() and iter->second.sendReplyTo != MessageQueueIF::NO_QUEUE) { + actionHelper.finish(false, iter->second.sendReplyTo, startracker::RELOAD_JSON_CFG_FILE); + } } } } @@ -532,6 +529,16 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi preparePingRequest(); return returnvalue::OK; } + case (startracker::RELOAD_JSON_CFG_FILE): { + if (jcfgPending) { + return HasActionsIF::IS_BUSY; + } + // It should be noted that this just reloads the JSON config structure in memory from the + // JSON file. The configuration still needs to be sent to the STR. The easiest way to achieve + // this is to simply reboot the device after a reload. + reloadJsonCfgFile(); + return returnvalue::OK; + } case (startracker::SET_TIME_FROM_SYS_TIME): { SetTimeActionRequest setTimeRequest{}; timeval tv; @@ -2846,3 +2853,5 @@ ReturnValue_t StarTrackerHandler::checkCommand(ActionId_t actionId) { } return returnvalue::OK; } + +ReturnValue_t StarTrackerHandler::acceptExternalDeviceCommands() { return returnvalue::OK; } diff --git a/mission/acs/str/StarTrackerHandler.h b/mission/acs/str/StarTrackerHandler.h index ad37557d..6bc1ff09 100644 --- a/mission/acs/str/StarTrackerHandler.h +++ b/mission/acs/str/StarTrackerHandler.h @@ -27,7 +27,9 @@ extern "C" { * @details Datasheet: https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/ * Arbeitsdaten/08_Used%20Components/ArcSec_KULeuven_Startracker/ * Sagitta%201.0%20Datapack&fileid=659181 - * @author J. Meier + * @note The STR code is a chaotic inconsistent mess and should be re-written with a simpler base + * class. DO NOT USE THIS AS REFERENCE. Stay away from it. + * @author J. Meier, R. Mueller */ class StarTrackerHandler : public DeviceHandlerBase { public: @@ -546,6 +548,7 @@ class StarTrackerHandler : public DeviceHandlerBase { void bootFirmware(Mode_t toMode); void bootBootloader(); bool reloadJsonCfgFile(); + ReturnValue_t acceptExternalDeviceCommands() override; }; #endif /* MISSION_DEVICES_STARTRACKERHANDLER_H_ */ From 518b265b4afacbe73d5750cad071f5cc0f19825b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 15:22:24 +0100 Subject: [PATCH 40/69] remove the printouts, done --- mission/acs/str/StarTrackerHandler.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/mission/acs/str/StarTrackerHandler.cpp b/mission/acs/str/StarTrackerHandler.cpp index 79f29a7f..9ad70d41 100644 --- a/mission/acs/str/StarTrackerHandler.cpp +++ b/mission/acs/str/StarTrackerHandler.cpp @@ -88,7 +88,6 @@ void StarTrackerHandler::doStartUp() { startupState = StartupState::WAIT_JCFG; return; } - startupState = StartupState::IDLE; break; case StartupState::WAIT_JCFG: { return; @@ -348,17 +347,16 @@ void StarTrackerHandler::performOperationHook() { } if (jcfgPending) { if (JCFG_DONE) { - sif::debug << "jcfg fucking done" << std::endl; + if(startupState == StartupState::WAIT_JCFG) { + startupState = StartupState::DONE; + } jsonCfgTask.join(); jcfgPending = false; - JCFG_DONE = false; auto iter = deviceCommandMap.find(startracker::RELOAD_JSON_CFG_FILE); if (iter != deviceCommandMap.end() and iter->second.sendReplyTo != MessageQueueIF::NO_QUEUE) { - sif::debug << "jcfg sending finished" << std::endl; actionHelper.finish(true, iter->second.sendReplyTo, startracker::RELOAD_JSON_CFG_FILE); } } else if (jcfgCountdown.hasTimedOut()) { - JCFG_DONE = false; auto iter = deviceCommandMap.find(startracker::RELOAD_JSON_CFG_FILE); if (iter != deviceCommandMap.end() and iter->second.sendReplyTo != MessageQueueIF::NO_QUEUE) { actionHelper.finish(false, iter->second.sendReplyTo, startracker::RELOAD_JSON_CFG_FILE); From 1aef8b6973efefe9d2d3cbcdcca68fece958ae4d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 15:26:21 +0100 Subject: [PATCH 41/69] bump fsfw --- fsfw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsfw b/fsfw index 8d7bb51d..41d67bff 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 8d7bb51d44c6fde88719c35cc51f3986a16f9956 +Subproject commit 41d67bff639192afa2e18a23db6801c75b4fea88 From 92bae9049f9742d5a143308cb159c5cdec52aa39 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 16:35:34 +0100 Subject: [PATCH 42/69] decline commands in wrong mode --- linux/payload/FreshSupvHandler.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index b872f41c..9fee6066 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -198,6 +198,11 @@ ReturnValue_t FreshSupvHandler::initializeLocalDataPool(localpool::DataPool& loc 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; @@ -238,8 +243,7 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI default: break; } - // This might not be necessary, but I think the PLOC SUPV is not able to process multiple - // commands consecutively.. + // The PLOC SUPV is not able to process multiple commands consecutively. if (isCommandPending()) { return HasActionsIF::IS_BUSY; } From a07018bdd4dadc6374637660ec5d37e498864b5d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 16:36:36 +0100 Subject: [PATCH 43/69] clear debug flag --- linux/payload/FreshSupvHandler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index 86cc9147..07756d41 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -14,8 +14,8 @@ using supv::TcBase; -static constexpr bool DEBUG_PLOC_SUPV = true; -static constexpr bool REDUCE_NORMAL_MODE_PRINTOUT = false; +static constexpr bool DEBUG_PLOC_SUPV = false; +static constexpr bool REDUCE_NORMAL_MODE_PRINTOUT = true; class FreshSupvHandler : public FreshDeviceHandlerBase { public: From 19594bc17315c108094ad95104209249b354a2df Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 16:45:35 +0100 Subject: [PATCH 44/69] update generated files --- .../fsfwconfig/events/translateEvents.cpp | 10 ++++++++-- .../fsfwconfig/objects/translateObjects.cpp | 2 +- generators/bsp_hosted_events.csv | 18 ++++++++++-------- generators/bsp_q7s_events.csv | 18 ++++++++++-------- generators/events/translateEvents.cpp | 10 ++++++++-- generators/objects/translateObjects.cpp | 2 +- linux/fsfwconfig/events/translateEvents.cpp | 10 ++++++++-- linux/fsfwconfig/objects/translateObjects.cpp | 2 +- tmtc | 2 +- 9 files changed, 48 insertions(+), 26 deletions(-) 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/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/tmtc b/tmtc index 07b13c15..2642a772 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 07b13c153dab03c35ea3c7921f68c6ba77049d1e +Subproject commit 2642a772ad1514305b2eab78d6c3270fe8161d26 From b1ddf1d4fd44ae05587c33b41f75e38b17073b91 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 16:49:37 +0100 Subject: [PATCH 45/69] clear active action cmds on OFF mode --- linux/payload/FreshSupvHandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 9fee6066..f414bec6 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -522,6 +522,7 @@ void FreshSupvHandler::handleTransitionToOff() { hkSet.setReportingEnabled(false); hkSet.setValidity(false, true); uartManager->stop(); + activeActionCmds.clear(); uartIsolatorSwitch.pullLow(); switchIF.sendSwitchCommand(switchId, PowerSwitchIF::SWITCH_OFF); shutdownState = ShutdownState::POWER_SWITCHING; From 1176c4397d73a7df717d6dc948f22234eced5736 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 17:20:41 +0100 Subject: [PATCH 46/69] more bugfixes --- linux/payload/FreshSupvHandler.cpp | 20 ++++++++++++-------- linux/payload/FreshSupvHandler.h | 5 +++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index f414bec6..640c5535 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -8,7 +8,9 @@ #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" @@ -78,6 +80,7 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { 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); } @@ -200,7 +203,7 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI 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) { + if (mode != MODE_ON and mode != MODE_NORMAL) { return HasModesIF::INVALID_MODE; } ReturnValue_t result; @@ -392,6 +395,9 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI result = DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; break; } + if (result == returnvalue::OK) { + this->commandedByCached = commandedBy; + } return result; } @@ -538,9 +544,6 @@ void FreshSupvHandler::handleTransitionToOff() { ReturnValue_t FreshSupvHandler::sendCommand(DeviceCommandId_t commandId, TcBase& tc, bool replyExpected, uint32_t cmdCountdownMs) { - if (interCmdCd.isBusy()) { - TaskFactory::delayTask(interCmdCd.getRemainingMillis()); - } if (supv::DEBUG_PLOC_SUPV) { if (not(supv::REDUCE_NORMAL_MODE_PRINTOUT and mode == MODE_NORMAL and commandId == supv::GET_HK_REPORT)) { @@ -555,6 +558,7 @@ ReturnValue_t FreshSupvHandler::sendCommand(DeviceCommandId_t commandId, TcBase& if (activeCmdIter == activeActionCmds.end()) { info.isPending = true; info.replyPacketExpected = replyExpected; + info.commandedBy = commandedByCached; activeActionCmds.emplace(buildActiveCmdKey(tc.getModuleApid(), tc.getServiceId()), info); } else { if (activeCmdIter->second.isPending) { @@ -562,6 +566,7 @@ ReturnValue_t FreshSupvHandler::sendCommand(DeviceCommandId_t commandId, TcBase& } activeCmdIter->second.isPending = true; activeCmdIter->second.commandId = commandId; + activeCmdIter->second.commandedBy = commandedByCached; activeCmdIter->second.ackRecv = false; activeCmdIter->second.ackExeRecv = false; activeCmdIter->second.replyPacketExpected = replyExpected; @@ -571,7 +576,6 @@ ReturnValue_t FreshSupvHandler::sendCommand(DeviceCommandId_t commandId, TcBase& } ReturnValue_t result = uartManager->sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen()); - interCmdCd.resetTimer(); return result; } @@ -1099,10 +1103,10 @@ void FreshSupvHandler::handleEvent(EventMessage* eventMessage) { event == PlocSupvUartManager::SUPV_CONTINUE_UPDATE_SUCCESSFUL || event == PlocSupvUartManager::SUPV_MEM_CHECK_FAIL || event == PlocSupvUartManager::SUPV_MEM_CHECK_OK) { - // Wait for a short period for the uart state machine to adjust - // TaskFactory::delayTask(5); if (not isCommandAlreadyActive(supv::SHUTDOWN_MPSOC)) { - result = this->executeAction(supv::SHUTDOWN_MPSOC, MessageQueueIF::NO_QUEUE, nullptr, 0); + 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 " diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index 07756d41..f938a771 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -14,7 +14,7 @@ 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; class FreshSupvHandler : public FreshDeviceHandlerBase { @@ -101,7 +101,7 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { 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); + // Countdown interCmdCd = Countdown(supv::INTER_COMMAND_DELAY); PoolEntry adcRawEntry = PoolEntry(16); PoolEntry adcEngEntry = PoolEntry(16); @@ -136,6 +136,7 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { std::array commandBuffer{}; SpacePacketCreator creator; supv::TcParams spParams = supv::TcParams(creator); + DeviceCommandId_t commandedByCached = MessageQueueIF::NO_QUEUE; ReturnValue_t parseTmPackets(); From 73ed59928e97efb17133de7a4246d51a638b7a9f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 17:37:26 +0100 Subject: [PATCH 47/69] check TM before normal periodic OP --- fsfw | 2 +- linux/payload/FreshSupvHandler.cpp | 16 ++++++++++++---- linux/payload/FreshSupvHandler.h | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/fsfw b/fsfw index 41d67bff..0021aa29 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 41d67bff639192afa2e18a23db6801c75b4fea88 +Subproject commit 0021aa29f54838a21658dbbaca98fe0e54318d8a diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 640c5535..b97d1e8a 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -74,7 +74,8 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { } } else { // I think the SUPV is not able to process multiple commands consecutively, so only send - // normal command if no other command is pending. + // 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))); @@ -101,6 +102,15 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { } } +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; @@ -254,6 +264,7 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI 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); @@ -395,9 +406,6 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI result = DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; break; } - if (result == returnvalue::OK) { - this->commandedByCached = commandedBy; - } return result; } diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index f938a771..259b70b6 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -57,6 +57,7 @@ class FreshSupvHandler : public FreshDeviceHandlerBase { */ void startTransition(Mode_t newMode, Submode_t submode) override; + ReturnValue_t performDeviceOperationPreQueueHandling(uint8_t opCode) override; void handleTransitionToOn(); void handleTransitionToOff(); From 8b5ca26cf1d65b689d79be84df7d734dcb73f80c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 17:40:25 +0100 Subject: [PATCH 48/69] bump fsfw --- fsfw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsfw b/fsfw index 0021aa29..c02d9e00 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 0021aa29f54838a21658dbbaca98fe0e54318d8a +Subproject commit c02d9e009efed98e5cbf8fd1eeeaedd98d3e6649 From 3a76e24fc27d1f88e28d6a9b8b1b4a76cfe81987 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 17:43:17 +0100 Subject: [PATCH 49/69] dsable debug flag --- linux/payload/FreshSupvHandler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index 259b70b6..8821fa1f 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -14,7 +14,7 @@ using supv::TcBase; -static constexpr bool DEBUG_PLOC_SUPV = true; +static constexpr bool DEBUG_PLOC_SUPV = false; static constexpr bool REDUCE_NORMAL_MODE_PRINTOUT = true; class FreshSupvHandler : public FreshDeviceHandlerBase { From 66619909a618d125bd36346097d1e8cf3278cdbe Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 17:44:51 +0100 Subject: [PATCH 50/69] changelog --- CHANGELOG.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74bd77e3..6323ec9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ 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. + # [v7.3.0] 2023-11-07 ## Changed @@ -696,7 +700,7 @@ This is the version which will fly on the satellite for the initial launch phase This gives other tasks some time to register the SD cards being unusable, and therefore provides a way for them to perform any re-initialization tasks necessary after SD card switches. - TCS controller now only has an OFF mode and an ON mode -- The TCS controller pauses operations related to the TCS board assembly (reading sensors and +- The TCS controller pauses operations related to the TCS board assembly (reading sensors and the primary control loop) while a TCS board recovery is on-going. - Allow specifying custom OBSW update filename. This allowed keeping a cleaner file structure where each update has a name including the version @@ -1761,8 +1765,8 @@ Syrlinks PR: PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/353 - Syrlinks Handler: Read RX frequency shift as 24 bit signed number now. Also include validity handling for datasets. PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/350 -- `GyroADIS1650XHandler`: Changed calculation of angular rate to be sensitivity based instead of - max. range based, as previous fix still left an margin of error between ADIS16505 sensors +- `GyroADIS1650XHandler`: Changed calculation of angular rate to be sensitivity based instead of + max. range based, as previous fix still left an margin of error between ADIS16505 sensors and L3GD20 sensors. PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/346 From fa21790003e018e62a0e87e272861f4dde344940 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Nov 2023 17:49:08 +0100 Subject: [PATCH 51/69] bump tmtc --- tmtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtc b/tmtc index 2642a772..1508acb7 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 2642a772ad1514305b2eab78d6c3270fe8161d26 +Subproject commit 1508acb7aefc62a6242ee316b2442c6d651a320f From b7ff78712cbb9b24c3c46bdfc5d0213f3b127cab Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 23 Nov 2023 13:18:05 +0100 Subject: [PATCH 52/69] revert some changes in com IF --- linux/acs/StrComHandler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/acs/StrComHandler.cpp b/linux/acs/StrComHandler.cpp index 2db73f35..0bb4d749 100644 --- a/linux/acs/StrComHandler.cpp +++ b/linux/acs/StrComHandler.cpp @@ -54,7 +54,7 @@ ReturnValue_t StrComHandler::performOperation(uint8_t operationCode) { switch (state) { case InternalState::POLL_ONE_REPLY: { // Stopwatch watch; - replyTimeout.setTimeout(200); + replyTimeout.setTimeout(400); readOneReply(static_cast(state)); { MutexGuard mg(lock); @@ -720,7 +720,7 @@ ReturnValue_t StrComHandler::readReceivedMessage(CookieIF* cookie, uint8_t** buf { MutexGuard mg(lock); if (state != InternalState::SLEEPING) { - return returnvalue::OK; + return BUSY; } replyWasReceived = this->replyWasReceived; } @@ -733,7 +733,7 @@ ReturnValue_t StrComHandler::readReceivedMessage(CookieIF* cookie, uint8_t** buf *size = replyLen; } replyLen = 0; - return returnvalue::OK; + return replyResult; } ReturnValue_t StrComHandler::unlockAndEraseRegions(uint32_t from, uint32_t to) { From 314df7a02105b29852b9e1d5f6393a17770526c0 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 23 Nov 2023 16:48:40 +0100 Subject: [PATCH 53/69] bugfix for virt channel: clear invalid state --- mission/com/LiveTmTask.cpp | 9 +++++---- mission/com/TmStoreTaskBase.cpp | 7 ++++--- mission/com/VirtualChannel.cpp | 4 +++- mission/com/VirtualChannelWithQueue.cpp | 2 +- mission/tmtc/DirectTmSinkIF.h | 1 + 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/mission/com/LiveTmTask.cpp b/mission/com/LiveTmTask.cpp index 56fe5a51..c671090c 100644 --- a/mission/com/LiveTmTask.cpp +++ b/mission/com/LiveTmTask.cpp @@ -173,15 +173,16 @@ ReturnValue_t LiveTmTask::handleGenericTmQueue(MessageQueueIF& queue, bool isCfd size_t writtenSize = 0; result = channel.write(data, size, writtenSize); if (result == DirectTmSinkIF::PARTIALLY_WRITTEN) { - result = channel.handleWriteCompletionSynchronously(writtenSize, 200); + result = channel.handleWriteCompletionSynchronously(writtenSize, 400); if (result != returnvalue::OK) { // TODO: Event? Might lead to dangerous spam though.. sif::warning << "LiveTmTask: Synchronous write of last segment failed with code 0x" - << std::setw(4) << std::hex << result << std::dec << std::endl; + << std::setfill('0') << std::setw(4) << std::hex << result << std::dec + << std::endl; } } else if (result != returnvalue::OK) { - sif::error << "LiveTmTask: Channel write failed with code 0x" << std::hex << std::setw(4) - << result << std::dec << std::endl; + sif::error << "LiveTmTask: Channel write failed with code 0x" << std::setfill('0') << std::hex + << std::setw(4) << result << std::dec << std::endl; } } // Try delete in any case, ignore failures (which should not happen), it is more important to diff --git a/mission/com/TmStoreTaskBase.cpp b/mission/com/TmStoreTaskBase.cpp index 215cef08..9e86ba08 100644 --- a/mission/com/TmStoreTaskBase.cpp +++ b/mission/com/TmStoreTaskBase.cpp @@ -141,11 +141,12 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store, size_t writtenSize = 0; result = channel.write(tmReader.getFullData(), dumpedLen, writtenSize); if (result == VirtualChannelIF::PARTIALLY_WRITTEN) { - result = channel.handleWriteCompletionSynchronously(writtenSize, 200); + result = channel.handleWriteCompletionSynchronously(writtenSize, 400); if (result != returnvalue::OK) { // TODO: Event? Might lead to dangerous spam though.. - sif::warning << "PersistentTmStore: Synchronous write of last segment failed with code 0x" - << std::setw(4) << std::hex << result << std::dec << std::endl; + sif::warning << "LiveTmTask: Synchronous write of last segment failed with code 0x" + << std::setfill('0') << std::setw(4) << std::hex << result << std::dec + << std::endl; } } else if (result == DirectTmSinkIF::IS_BUSY) { sif::warning << "PersistentTmStore: Unexpected VC channel busy" << std::endl; diff --git a/mission/com/VirtualChannel.cpp b/mission/com/VirtualChannel.cpp index e531727e..a75959e6 100644 --- a/mission/com/VirtualChannel.cpp +++ b/mission/com/VirtualChannel.cpp @@ -74,5 +74,7 @@ ReturnValue_t VirtualChannel::handleWriteCompletionSynchronously(size_t& written return result; } } - return returnvalue::FAILED; + // Timeout. Cancel the transfer + cancelTransfer(); + return TIMEOUT; } diff --git a/mission/com/VirtualChannelWithQueue.cpp b/mission/com/VirtualChannelWithQueue.cpp index 0d9e4d11..fb3375dc 100644 --- a/mission/com/VirtualChannelWithQueue.cpp +++ b/mission/com/VirtualChannelWithQueue.cpp @@ -41,7 +41,7 @@ ReturnValue_t VirtualChannelWithQueue::handleNextTm(bool performWriteOp) { if (performWriteOp) { result = write(data, size, writtenSize); if (result == PARTIALLY_WRITTEN) { - result = handleWriteCompletionSynchronously(writtenSize, 200); + result = handleWriteCompletionSynchronously(writtenSize, 400); if (result != returnvalue::OK) { // TODO: Event? Might lead to dangerous spam though.. sif::warning diff --git a/mission/tmtc/DirectTmSinkIF.h b/mission/tmtc/DirectTmSinkIF.h index ff8ab6fe..546b293e 100644 --- a/mission/tmtc/DirectTmSinkIF.h +++ b/mission/tmtc/DirectTmSinkIF.h @@ -15,6 +15,7 @@ class DirectTmSinkIF { static constexpr ReturnValue_t IS_BUSY = returnvalue::makeCode(CLASS_ID, 0); static constexpr ReturnValue_t PARTIALLY_WRITTEN = returnvalue::makeCode(CLASS_ID, 1); static constexpr ReturnValue_t NO_WRITE_ACTIVE = returnvalue::makeCode(CLASS_ID, 2); + static constexpr ReturnValue_t TIMEOUT = returnvalue::makeCode(CLASS_ID, 3); /** * @brief Implements the functionality to write to a TM sink directly. From 352043cb51de23b5c598632e48e2fad23b0ea370 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 23 Nov 2023 17:20:55 +0100 Subject: [PATCH 54/69] printout improvements --- linux/ipcore/PapbVcInterface.cpp | 1 + mission/com/LiveTmTask.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/linux/ipcore/PapbVcInterface.cpp b/linux/ipcore/PapbVcInterface.cpp index c02d0935..a176c3af 100644 --- a/linux/ipcore/PapbVcInterface.cpp +++ b/linux/ipcore/PapbVcInterface.cpp @@ -30,6 +30,7 @@ ReturnValue_t PapbVcInterface::initialize() { ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size, size_t& writtenSize) { // There are no packets smaller than 4, this is considered a configuration error. if (size < 4) { + sif::warning << "PapbVcInterface::write: Passed packet smaller than 4 bytes" << std::endl; return returnvalue::FAILED; } // The user must call advance until completion before starting a new packet transfer. diff --git a/mission/com/LiveTmTask.cpp b/mission/com/LiveTmTask.cpp index c671090c..33b9322a 100644 --- a/mission/com/LiveTmTask.cpp +++ b/mission/com/LiveTmTask.cpp @@ -54,8 +54,13 @@ ReturnValue_t LiveTmTask::performOperation(uint8_t opCode) { } } } else if (result != MessageQueueIF::EMPTY) { - sif::warning << "LiveTmTask: TM queue failure, returncode 0x" << std::hex << std::setw(4) - << result << std::dec << std::endl; + const char* contextStr = "Regular TM queue"; + if (isCfdp) { + contextStr = "CFDP TM queue"; + } + sif::warning << "LiveTmTask: " << contextStr << " handling failure, returncode 0x" + << std::setfill('0') << std::hex << std::setw(4) << result << std::dec + << std::endl; } } From ef948af5f33a4aea98ecb6ec973b1f019e1dd2ca Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 23 Nov 2023 17:22:36 +0100 Subject: [PATCH 55/69] small possible fix --- linux/ipcore/PapbVcInterface.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linux/ipcore/PapbVcInterface.cpp b/linux/ipcore/PapbVcInterface.cpp index a176c3af..e4414363 100644 --- a/linux/ipcore/PapbVcInterface.cpp +++ b/linux/ipcore/PapbVcInterface.cpp @@ -84,6 +84,9 @@ ReturnValue_t PapbVcInterface::advanceWrite(size_t& writtenSize) { writtenSize++; } if (not pollReadyForOctet(MAX_BUSY_POLLS)) { + if (not pollReadyForPacket()) { + return PARTIALLY_WRITTEN; + } abortPacketTransfer(); return returnvalue::FAILED; } From 9e31c065632807e6c3b0eaf3c6add65c467af110 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 23 Nov 2023 17:47:44 +0100 Subject: [PATCH 56/69] changelog update --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74bd77e3..7369c89f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,13 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +## Fixed + +- Increase allowed time for PTME writers to finish partial transfers. A duration of 200 ms was + not sufficient for cases where 3 writers write concurrently. +- Fixed state issue for PTME writer object where the writer was not reset properly after a timeout + of a partial transfer. This bloked the whole VC. + # [v7.3.0] 2023-11-07 ## Changed From c0b4761ba0ce0c81b7a9cc6aeab98fa199bb5ad9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 27 Nov 2023 11:22:23 +0100 Subject: [PATCH 57/69] smaller bugfixes --- mission/payload/PayloadPcduHandler.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/mission/payload/PayloadPcduHandler.cpp b/mission/payload/PayloadPcduHandler.cpp index bba80901..db4ed662 100644 --- a/mission/payload/PayloadPcduHandler.cpp +++ b/mission/payload/PayloadPcduHandler.cpp @@ -429,20 +429,20 @@ void PayloadPcduHandler::checkAdcValues() { params.getValue(PARAM_KEY_MAP[NEG_V_UPPER_BOUND], upperBound); if (not checkVoltage(adcSet.processed[U_NEG_V_FB], lowerBound, upperBound, NEG_V_OUT_OF_BOUNDS)) { + sif::warning << "Negative voltage was out of bounds, went back to OFF" << std::endl; return; } params.getValue(PARAM_KEY_MAP[DRO_U_LOWER_BOUND], lowerBound); params.getValue(PARAM_KEY_MAP[DRO_U_UPPER_BOUND], upperBound); if (not checkVoltage(adcSet.processed[U_DRO_DIV_6], lowerBound, upperBound, U_DRO_OUT_OF_BOUNDS)) { + sif::warning << "DRO voltage was out of bounds, went back to OFF" << std::endl; return; } params.getValue(PARAM_KEY_MAP[DRO_I_UPPER_BOUND], upperBound); if (not checkCurrent(adcSet.processed[I_DRO], upperBound, I_DRO_OUT_OF_BOUNDS)) { -#if OBSW_VERBOSE_LEVEL >= 1 sif::warning << "Detected out of bounds current for DRO: " << adcSet.processed[I_DRO] << ", Raw: " << adcSet.channels[I_DRO] << std::endl; -#endif return; } } @@ -456,10 +456,12 @@ void PayloadPcduHandler::checkAdcValues() { params.getValue(PARAM_KEY_MAP[X8_U_UPPER_BOUND], upperBound); if (not checkVoltage(adcSet.processed[U_X8_DIV_6], lowerBound, upperBound, U_X8_OUT_OF_BOUNDS)) { + sif::warning << "X8 voltage was out of bounds, went back to OFF" << std::endl; return; } params.getValue(PARAM_KEY_MAP[X8_I_UPPER_BOUND], upperBound); if (not checkCurrent(adcSet.processed[I_X8], upperBound, I_X8_OUT_OF_BOUNDS)) { + sif::warning << "X8 current was out of bounds, went back to OFF" << std::endl; return; } } @@ -473,10 +475,12 @@ void PayloadPcduHandler::checkAdcValues() { params.getValue(PARAM_KEY_MAP[TX_U_UPPER_BOUND], upperBound); if (not checkVoltage(adcSet.processed[U_TX_DIV_6], lowerBound, upperBound, U_TX_OUT_OF_BOUNDS)) { + sif::warning << "TX voltage was out of bounds, went back to OFF" << std::endl; return; } params.getValue(PARAM_KEY_MAP[TX_I_UPPER_BOUND], upperBound); if (not checkCurrent(adcSet.processed[I_TX], upperBound, I_TX_OUT_OF_BOUNDS)) { + sif::warning << "TX current was out of bounds, went back to OFF" << std::endl; return; } } @@ -490,10 +494,12 @@ void PayloadPcduHandler::checkAdcValues() { params.getValue(PARAM_KEY_MAP[MPA_U_UPPER_BOUND], upperBound); if (not checkVoltage(adcSet.processed[U_MPA_DIV_6], lowerBound, upperBound, U_MPA_OUT_OF_BOUNDS)) { + sif::warning << "MPA voltage was out of bounds, went back to OFF" << std::endl; return; } params.getValue(PARAM_KEY_MAP[MPA_I_UPPER_BOUND], upperBound); if (not checkCurrent(adcSet.processed[I_MPA], upperBound, I_MPA_OUT_OF_BOUNDS)) { + sif::warning << "MPA current was out of bounds, went back to OFF" << std::endl; return; } } @@ -507,6 +513,7 @@ void PayloadPcduHandler::checkAdcValues() { params.getValue(PARAM_KEY_MAP[HPA_U_UPPER_BOUND], upperBound); if (not checkVoltage(adcSet.processed[U_HPA_DIV_6], lowerBound, upperBound, U_HPA_OUT_OF_BOUNDS)) { + sif::warning << "HPA voltage was out of bounds, went back to OFF" << std::endl; return; } params.getValue(PARAM_KEY_MAP[HPA_I_UPPER_BOUND], upperBound); @@ -595,6 +602,7 @@ ReturnValue_t PayloadPcduHandler::checkModeCommand(Mode_t commandedMode, Submode txOnForSubmode(commandedSubmode) or mpaOnForSubmode(commandedSubmode) or hpaOnForSubmode(commandedSubmode)) and not ssrOnForSubmode(dhbSubmode)) { + return TRANS_NOT_ALLOWED; } if (disableChannelOrderCheck) { return returnvalue::OK; @@ -606,7 +614,7 @@ ReturnValue_t PayloadPcduHandler::checkModeCommand(Mode_t commandedMode, Submode (not droOnForSubmode(dhbSubmode) or not x8OnForSubmode(dhbSubmode))) { return TRANS_NOT_ALLOWED; } - if (txOnForSubmode(commandedSubmode) and + if (mpaOnForSubmode(commandedSubmode) and (not droOnForSubmode(dhbSubmode) or not x8OnForSubmode(dhbSubmode) or not txOnForSubmode(dhbSubmode))) { return TRANS_NOT_ALLOWED; @@ -628,13 +636,9 @@ bool PayloadPcduHandler::droOnForSubmode(uint8_t submode) { return submode & (1 << plpcdu::DRO_ON); } -bool PayloadPcduHandler::x8OnForSubmode(uint8_t submode) { - return submode & (1 << plpcdu::X8_ON); -} +bool PayloadPcduHandler::x8OnForSubmode(uint8_t submode) { return submode & (1 << plpcdu::X8_ON); } -bool PayloadPcduHandler::txOnForSubmode(uint8_t submode) { - return submode & (1 << plpcdu::TX_ON); -} +bool PayloadPcduHandler::txOnForSubmode(uint8_t submode) { return submode & (1 << plpcdu::TX_ON); } bool PayloadPcduHandler::mpaOnForSubmode(uint8_t submode) { return submode & (1 << plpcdu::MPA_ON); From b0f81d1cceccb07d03d91837d41257d579696cba Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 27 Nov 2023 12:04:55 +0100 Subject: [PATCH 58/69] this should fix the param setting --- mission/payload/PayloadPcduHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mission/payload/PayloadPcduHandler.cpp b/mission/payload/PayloadPcduHandler.cpp index db4ed662..1fc3fa99 100644 --- a/mission/payload/PayloadPcduHandler.cpp +++ b/mission/payload/PayloadPcduHandler.cpp @@ -719,7 +719,7 @@ ReturnValue_t PayloadPcduHandler::getParameter(uint8_t domainId, uint8_t uniqueI if (newValue > 1) { return HasParametersIF::INVALID_VALUE; } - parameterWrapper->set(&disableChannelOrderCheck); + parameterWrapper->set(disableChannelOrderCheck); break; } default: { From aef8db62b1eb941f5d6f13d539fb6ecf6c2a4f3c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 27 Nov 2023 12:19:00 +0100 Subject: [PATCH 59/69] bump tmtc --- tmtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtc b/tmtc index 99c6c8bb..62b16028 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 99c6c8bbd0d791d8b17720de481c6142091a54a4 +Subproject commit 62b16028e662ab3dc6ec2f8b54732220e3ef8378 From f321d7f0b6300fcb72c98d31466d33117534ba76 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 27 Nov 2023 12:20:14 +0100 Subject: [PATCH 60/69] bump tmtc again --- tmtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtc b/tmtc index 62b16028..fc243b76 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 62b16028e662ab3dc6ec2f8b54732220e3ef8378 +Subproject commit fc243b76cf8e117894358b180369da8314b5b04c From b987566947ea2c7987bdd5791a1578492507637c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 27 Nov 2023 15:41:58 +0100 Subject: [PATCH 61/69] changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74bd77e3..0f2e99f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +## Added + +- PL PCDU: Add command to enable and disable channel order checks. + # [v7.3.0] 2023-11-07 ## Changed From 112fa2b8ff90667410e1387e125c5f8d6d5c9e87 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Nov 2023 15:31:37 +0100 Subject: [PATCH 62/69] important bugfix --- linux/payload/FreshSupvHandler.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index b97d1e8a..5f155a7c 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -90,6 +90,7 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { } else if (opCode == OpCode::PARSE_TM) { for (auto& activeCmd : activeActionCmds) { if (activeCmd.second.isPending and activeCmd.second.cmdCountdown.hasTimedOut()) { + sif::warning << "hello im stupid" << std::endl; if (activeCmd.second.commandedBy != MessageQueueIF::NO_QUEUE) { actionHelper.finish(false, activeCmd.second.commandedBy, activeCmd.first, DeviceHandlerIF::TIMEOUT); @@ -567,6 +568,7 @@ ReturnValue_t FreshSupvHandler::sendCommand(DeviceCommandId_t commandId, TcBase& 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) { @@ -901,6 +903,7 @@ ReturnValue_t FreshSupvHandler::parseTmPackets() { } case (Apid::ADC_MON): { if (tmReader.getServiceId() == static_cast(supv::tm::AdcMonId::ADC_REPORT)) { + sif::debug << "recv ADC report" << std::endl; genericHandleTm("ADC", receivedData, adcReport, supv::Apid::ADC_MON, static_cast(supv::tc::AdcMonId::REQUEST_ADC_SAMPLE)); continue; @@ -1295,8 +1298,7 @@ void FreshSupvHandler::handleExecutionFailureReport(ActiveCmdInfo& info, Executi } void FreshSupvHandler::confirmReplyPacketReceived(supv::Apid apid, uint8_t serviceId) { - auto infoIter = activeActionCmds.find( - buildActiveCmdKey(supv::Apid::HK, static_cast(supv::tc::HkId::GET_REPORT))); + auto infoIter = activeActionCmds.find(buildActiveCmdKey(apid, serviceId)); if (infoIter != activeActionCmds.end()) { ActiveCmdInfo& info = infoIter->second; info.replyPacketReceived = true; From a765e67b53b4a60ccfcc744635ae48a3832233e0 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Nov 2023 15:32:08 +0100 Subject: [PATCH 63/69] remove some printouts --- linux/payload/FreshSupvHandler.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 5f155a7c..0d34b63f 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -90,7 +90,6 @@ void FreshSupvHandler::performDeviceOperation(uint8_t opCode) { } else if (opCode == OpCode::PARSE_TM) { for (auto& activeCmd : activeActionCmds) { if (activeCmd.second.isPending and activeCmd.second.cmdCountdown.hasTimedOut()) { - sif::warning << "hello im stupid" << std::endl; if (activeCmd.second.commandedBy != MessageQueueIF::NO_QUEUE) { actionHelper.finish(false, activeCmd.second.commandedBy, activeCmd.first, DeviceHandlerIF::TIMEOUT); @@ -903,7 +902,6 @@ ReturnValue_t FreshSupvHandler::parseTmPackets() { } case (Apid::ADC_MON): { if (tmReader.getServiceId() == static_cast(supv::tm::AdcMonId::ADC_REPORT)) { - sif::debug << "recv ADC report" << std::endl; genericHandleTm("ADC", receivedData, adcReport, supv::Apid::ADC_MON, static_cast(supv::tc::AdcMonId::REQUEST_ADC_SAMPLE)); continue; From 5714abda109d5c6d9028de9944f4b9eb5a9c5ea5 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Nov 2023 15:37:25 +0100 Subject: [PATCH 64/69] remove duplicate constants --- linux/payload/FreshSupvHandler.h | 3 --- linux/payload/plocSupvDefs.h | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/linux/payload/FreshSupvHandler.h b/linux/payload/FreshSupvHandler.h index 8821fa1f..2c700deb 100644 --- a/linux/payload/FreshSupvHandler.h +++ b/linux/payload/FreshSupvHandler.h @@ -14,9 +14,6 @@ using supv::TcBase; -static constexpr bool DEBUG_PLOC_SUPV = false; -static constexpr bool REDUCE_NORMAL_MODE_PRINTOUT = true; - class FreshSupvHandler : public FreshDeviceHandlerBase { public: enum OpCode { DEFAULT_OPERATION = 0, PARSE_TM = 1 }; diff --git a/linux/payload/plocSupvDefs.h b/linux/payload/plocSupvDefs.h index 06dd7b8e..a770fb49 100644 --- a/linux/payload/plocSupvDefs.h +++ b/linux/payload/plocSupvDefs.h @@ -11,14 +11,13 @@ #include #include -#include #include "eive/eventSubsystemIds.h" #include "eive/resultClassIds.h" namespace supv { -static constexpr bool DEBUG_PLOC_SUPV = true; +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; From f92642623ee27e0eb2f702896fc24d2fb3f3a4b6 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Nov 2023 15:38:57 +0100 Subject: [PATCH 65/69] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6323ec9d..0b79662d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ will consitute of a breaking change warranting a new major release: ## 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. # [v7.3.0] 2023-11-07 From 14e545618c8a602e5cf8d23a633cd0809a6ae6a7 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Nov 2023 15:42:36 +0100 Subject: [PATCH 66/69] typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7369c89f..19159f5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ will consitute of a breaking change warranting a new major release: - Increase allowed time for PTME writers to finish partial transfers. A duration of 200 ms was not sufficient for cases where 3 writers write concurrently. - Fixed state issue for PTME writer object where the writer was not reset properly after a timeout - of a partial transfer. This bloked the whole VC. + of a partial transfer. This was a major bug blocking the whole VC if it occured. # [v7.3.0] 2023-11-07 From 178da2fec15de2365c5d727a9e8e5cc7cb096a93 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 29 Nov 2023 14:17:17 +0100 Subject: [PATCH 67/69] changelog update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74bd77e3..019a9ea3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ will consitute of a breaking change warranting a new major release: - Changed PDEC addresses depending on which firmware version is used. It is suspected that the previous addresses were invalid and not properly covered by the Linux memory protection. The OBSW will use the old addresses for older FW versions. +- Reverted some STR ComIF behaviour back to an older software version. ## Added From 8c1e7ae41814cf559cc9226d315e8fa4cd220020 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 29 Nov 2023 14:23:29 +0100 Subject: [PATCH 68/69] bump fsfw and tmtc --- fsfw | 2 +- tmtc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fsfw b/fsfw index c02d9e00..b28174db 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit c02d9e009efed98e5cbf8fd1eeeaedd98d3e6649 +Subproject commit b28174db249cb33b541f665270fd6af14c382351 diff --git a/tmtc b/tmtc index 1508acb7..a41dc9b6 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 1508acb7aefc62a6242ee316b2442c6d651a320f +Subproject commit a41dc9b691ab51b8526b3a3982f35072f5d82632 From 89b6a2de2d8171c415bdcdd262d5d6377ded9214 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 29 Nov 2023 15:15:29 +0100 Subject: [PATCH 69/69] run afmt, re-run generators --- bsp_hosted/fsfwconfig/events/translateEvents.cpp | 2 +- bsp_hosted/fsfwconfig/objects/translateObjects.cpp | 2 +- generators/bsp_hosted_returnvalues.csv | 1 + generators/bsp_q7s_returnvalues.csv | 1 + generators/events/translateEvents.cpp | 2 +- generators/objects/translateObjects.cpp | 2 +- linux/fsfwconfig/events/translateEvents.cpp | 2 +- linux/fsfwconfig/objects/translateObjects.cpp | 2 +- mission/acs/str/StarTrackerHandler.cpp | 2 +- tmtc | 2 +- 10 files changed, 10 insertions(+), 8 deletions(-) diff --git a/bsp_hosted/fsfwconfig/events/translateEvents.cpp b/bsp_hosted/fsfwconfig/events/translateEvents.cpp index d4e113af..92401ab1 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 317 translations. * @details - * Generated on: 2023-11-21 16:44:58 + * Generated on: 2023-11-29 15:14:46 */ #include "translateEvents.h" diff --git a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp index 145bf9aa..834bdf41 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-11-21 16:44:58 + * Generated on: 2023-11-29 15:14:46 */ #include "translateObjects.h" diff --git a/generators/bsp_hosted_returnvalues.csv b/generators/bsp_hosted_returnvalues.csv index 1964e00e..abc43314 100644 --- a/generators/bsp_hosted_returnvalues.csv +++ b/generators/bsp_hosted_returnvalues.csv @@ -522,4 +522,5 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x6f00;TMS_IsBusy;No description;0;TM_SINK;mission/tmtc/DirectTmSinkIF.h 0x6f01;TMS_PartiallyWritten;No description;1;TM_SINK;mission/tmtc/DirectTmSinkIF.h 0x6f02;TMS_NoWriteActive;No description;2;TM_SINK;mission/tmtc/DirectTmSinkIF.h +0x6f03;TMS_Timeout;No description;3;TM_SINK;mission/tmtc/DirectTmSinkIF.h 0x7000;VCS_ChannelDoesNotExist;No description;0;VIRTUAL_CHANNEL;mission/com/VirtualChannel.h diff --git a/generators/bsp_q7s_returnvalues.csv b/generators/bsp_q7s_returnvalues.csv index 9aa12b12..d2922a1c 100644 --- a/generators/bsp_q7s_returnvalues.csv +++ b/generators/bsp_q7s_returnvalues.csv @@ -617,5 +617,6 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x6f00;TMS_IsBusy;No description;0;TM_SINK;mission/tmtc/DirectTmSinkIF.h 0x6f01;TMS_PartiallyWritten;No description;1;TM_SINK;mission/tmtc/DirectTmSinkIF.h 0x6f02;TMS_NoWriteActive;No description;2;TM_SINK;mission/tmtc/DirectTmSinkIF.h +0x6f03;TMS_Timeout;No description;3;TM_SINK;mission/tmtc/DirectTmSinkIF.h 0x7000;VCS_ChannelDoesNotExist;No description;0;VIRTUAL_CHANNEL;mission/com/VirtualChannel.h 0x7200;SCBU_KeyNotFound;No description;0;SCRATCH_BUFFER;bsp_q7s/memory/scratchApi.h diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index d4e113af..92401ab1 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 317 translations. * @details - * Generated on: 2023-11-21 16:44:58 + * Generated on: 2023-11-29 15:14:46 */ #include "translateEvents.h" diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index d7ff5f77..2af38f77 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-11-21 16:44:58 + * Generated on: 2023-11-29 15:14:46 */ #include "translateObjects.h" diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index d4e113af..92401ab1 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 317 translations. * @details - * Generated on: 2023-11-21 16:44:58 + * Generated on: 2023-11-29 15:14:46 */ #include "translateEvents.h" diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index d7ff5f77..2af38f77 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-11-21 16:44:58 + * Generated on: 2023-11-29 15:14:46 */ #include "translateObjects.h" diff --git a/mission/acs/str/StarTrackerHandler.cpp b/mission/acs/str/StarTrackerHandler.cpp index 9ad70d41..147c04d8 100644 --- a/mission/acs/str/StarTrackerHandler.cpp +++ b/mission/acs/str/StarTrackerHandler.cpp @@ -347,7 +347,7 @@ void StarTrackerHandler::performOperationHook() { } if (jcfgPending) { if (JCFG_DONE) { - if(startupState == StartupState::WAIT_JCFG) { + if (startupState == StartupState::WAIT_JCFG) { startupState = StartupState::DONE; } jsonCfgTask.join(); diff --git a/tmtc b/tmtc index 3b047094..098843a7 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 3b047094e691abfe114fd5b87dd85a4c69403394 +Subproject commit 098843a74f93a7ec94500bc0fc9faa1abb165508