diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index a1ac3868..a5e045cb 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -170,7 +170,8 @@ void ObjectFactory::produce(void* args){ /* Configuration for MIO0 on TE0720-03-1CFA */ UartCookie* plocSupervisorCookie = new UartCookie(objects::PLOC_SUPERVISOR_HANDLER, std::string("/dev/ttyUL3"), UartModes::NON_CANONICAL, 115200, - PLOC_SPV::MAX_REPLY_SIZE); + PLOC_SPV::MAX_PACKET_SIZE * 20); + plocSupervisorCookie->setNoFixedSizeReply(); PlocSupervisorHandler* plocSupervisor = new PlocSupervisorHandler( objects::PLOC_SUPERVISOR_HANDLER, objects::UART_COM_IF, plocSupervisorCookie); plocSupervisor->setStartUpImmediately(); @@ -802,7 +803,7 @@ void ObjectFactory::createTestComponents() { radSensor->setStartUpImmediately(); #endif -#if BOARD_TE0720 == 1 && TEST_PLOC_HANDLER == 1 +#if BOARD_TE0720 == 1 && ADD_PLOC_MPSOC == 1 UartCookie* plocUartCookie = new UartCookie(std::string("/dev/ttyPS1"), 115200, PLOC_MPSOC::MAX_REPLY_SIZE); /* Testing PlocMPSoCHandler on TE0720-03-1CFA */ @@ -820,7 +821,7 @@ void ObjectFactory::createTestComponents() { pcduSwitches::TCS_BOARD_8V_HEATER_IN); #endif -#if TE0720 == 1 && ADD_PLOC_SUPERVISOR == 1 +#if BOARD_TE0720 == 1 && ADD_PLOC_SUPERVISOR == 1 /* Configuration for MIO0 on TE0720-03-1CFA */ UartCookie* plocSupervisorCookie = new UartCookie(objects::PLOC_SUPERVISOR_HANDLER, std::string("/dev/ttyPS1"), UartModes::NON_CANONICAL, 115200, diff --git a/mission/core/GenericFactory.cpp b/mission/core/GenericFactory.cpp index a6708f98..cc1b88e5 100644 --- a/mission/core/GenericFactory.cpp +++ b/mission/core/GenericFactory.cpp @@ -36,14 +36,14 @@ void ObjectFactory::produceGenericObjects() { { PoolManager::LocalPoolConfig poolCfg = { - {100, 16}, {50, 32}, {25, 64}, {15, 128}, {5, 1024} + {100, 16}, {50, 32}, {25, 64}, {15, 128}, {10, 1024}, {5, 2048} }; new PoolManager(objects::TC_STORE, poolCfg); } { PoolManager::LocalPoolConfig poolCfg = { - {100, 16}, {50, 32}, {25, 64}, {15, 128}, {5, 1024} + {100, 16}, {50, 32}, {25, 64}, {15, 128}, {10, 1024}, {5, 2048} }; new PoolManager(objects::TM_STORE, poolCfg); } diff --git a/mission/devices/PlocSupervisorHandler.cpp b/mission/devices/PlocSupervisorHandler.cpp index 5af3693b..9c4dc73e 100644 --- a/mission/devices/PlocSupervisorHandler.cpp +++ b/mission/devices/PlocSupervisorHandler.cpp @@ -5,8 +5,10 @@ #include #include -PlocSupervisorHandler::PlocSupervisorHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF * comCookie) : - DeviceHandlerBase(objectId, uartComIFid, comCookie), hkset(this), bootStatusReport(this) { +PlocSupervisorHandler::PlocSupervisorHandler(object_id_t objectId, object_id_t uartComIFid, + CookieIF * comCookie) : + DeviceHandlerBase(objectId, uartComIFid, comCookie), hkset(this), bootStatusReport(this), latchupStatusReport( + this) { if (comCookie == NULL) { sif::error << "PlocSupervisorHandler: Invalid com cookie" << std::endl; } @@ -115,6 +117,129 @@ ReturnValue_t PlocSupervisorHandler::buildCommandFromCommand( prepareUpdateAvailableCmd(commandData); result = RETURN_OK; break; + } + case(PLOC_SPV::WATCHDOGS_ENABLE): { + prepareWatchdogsEnableCmd(commandData); + result = RETURN_OK; + break; + } + case(PLOC_SPV::WATCHDOGS_CONFIG_TIMEOUT): { + result = prepareWatchdogsConfigTimeoutCmd(commandData); + break; + } + case(PLOC_SPV::ENABLE_LATCHUP_ALERT): { + result = prepareLatchupConfigCmd(commandData, deviceCommand); + break; + } + case(PLOC_SPV::DISABLE_LATCHUP_ALERT): { + result = prepareLatchupConfigCmd(commandData, deviceCommand); + break; + } + case(PLOC_SPV::AUTO_CALIBRATE_ALERT): { + result = prepareAutoCalibrateAlertCmd(commandData); + break; + } + case(PLOC_SPV::SET_ALERT_LIMIT): { + result = prepareSetAlertLimitCmd(commandData); + break; + } + case(PLOC_SPV::SET_ALERT_IRQ_FILTER): { + result = prepareSetAlertIrqFilterCmd(commandData); + break; + } + case(PLOC_SPV::SET_ADC_SWEEP_PERIOD): { + result = prepareSetAdcSweetPeriodCmd(commandData); + break; + } + case(PLOC_SPV::SET_ADC_ENABLED_CHANNELS): { + prepareSetAdcEnabledChannelsCmd(commandData); + result = RETURN_OK; + break; + } + case(PLOC_SPV::SET_ADC_WINDOW_AND_STRIDE): { + prepareSetAdcWindowAndStrideCmd(commandData); + result = RETURN_OK; + break; + } + case(PLOC_SPV::SET_ADC_THRESHOLD): { + prepareSetAdcThresholdCmd(commandData); + result = RETURN_OK; + break; + } + case(PLOC_SPV::GET_LATCHUP_STATUS_REPORT): { + prepareEmptyCmd(PLOC_SPV::APID_GET_LATCHUP_STATUS_REPORT); + result = RETURN_OK; + break; + } + case(PLOC_SPV::COPY_ADC_DATA_TO_MRAM): { + prepareEmptyCmd(PLOC_SPV::APID_COPY_ADC_DATA_TO_MRAM); + result = RETURN_OK; + break; + } + case(PLOC_SPV::ENABLE_NVMS): { + prepareEnableNvmsCmd(commandData); + result = RETURN_OK; + break; + } + case(PLOC_SPV::SELECT_NVM): { + prepareSelectNvmCmd(commandData); + result = RETURN_OK; + break; + } + case(PLOC_SPV::RUN_AUTO_EM_TESTS): { + result = prepareRunAutoEmTest(commandData); + break; + } + case(PLOC_SPV::WIPE_MRAM): { + result = prepareWipeMramCmd(commandData); + break; + } + case(PLOC_SPV::DUMP_MRAM): { + result = prepareDumpMramCmd(commandData); + break; + } + case(PLOC_SPV::PRINT_CPU_STATS): { + preparePrintCpuStatsCmd(commandData); + result = RETURN_OK; + break; + } + case(PLOC_SPV::SET_DBG_VERBOSITY): { + prepareSetDbgVerbosityCmd(commandData); + result = RETURN_OK; + break; + } + case(PLOC_SPV::SET_GPIO): { + prepareSetGpioCmd(commandData); + result = RETURN_OK; + break; + } + case(PLOC_SPV::READ_GPIO): { + prepareReadGpioCmd(commandData); + result = RETURN_OK; + break; + } + case(PLOC_SPV::RESTART_SUPERVISOR): { + prepareEmptyCmd(PLOC_SPV::APID_RESTART_SUPERVISOR); + result = RETURN_OK; + break; + } + case(PLOC_SPV::FACTORY_RESET_CLEAR_ALL): { + PLOC_SPV::FactoryReset packet(PLOC_SPV::FactoryReset::Op::CLEAR_ALL); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); + result = RETURN_OK; + break; + } + case(PLOC_SPV::FACTORY_RESET_CLEAR_MIRROR): { + PLOC_SPV::FactoryReset packet(PLOC_SPV::FactoryReset::Op::MIRROR_ENTRIES); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); + result = RETURN_OK; + break; + } + case(PLOC_SPV::FACTORY_RESET_CLEAR_CIRCULAR): { + PLOC_SPV::FactoryReset packet(PLOC_SPV::FactoryReset::Op::CIRCULAR_ENTRIES); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); + result = RETURN_OK; + break; } default: sif::debug << "PlocSupervisorHandler::buildCommandFromCommand: Command not implemented" @@ -145,16 +270,50 @@ void PlocSupervisorHandler::fillCommandAndReplyMap() { this->insertInCommandMap(PLOC_SPV::SET_TIME_REF); this->insertInCommandMap(PLOC_SPV::DISABLE_PERIOIC_HK_TRANSMISSION); this->insertInCommandMap(PLOC_SPV::GET_BOOT_STATUS_REPORT); + this->insertInCommandMap(PLOC_SPV::UPDATE_AVAILABLE); + this->insertInCommandMap(PLOC_SPV::WATCHDOGS_ENABLE); + this->insertInCommandMap(PLOC_SPV::WATCHDOGS_CONFIG_TIMEOUT); + this->insertInCommandMap(PLOC_SPV::ENABLE_LATCHUP_ALERT); + this->insertInCommandMap(PLOC_SPV::DISABLE_LATCHUP_ALERT); + this->insertInCommandMap(PLOC_SPV::AUTO_CALIBRATE_ALERT); + this->insertInCommandMap(PLOC_SPV::SET_ALERT_LIMIT); + this->insertInCommandMap(PLOC_SPV::SET_ALERT_IRQ_FILTER); + this->insertInCommandMap(PLOC_SPV::SET_ADC_SWEEP_PERIOD); + this->insertInCommandMap(PLOC_SPV::SET_ADC_ENABLED_CHANNELS); + this->insertInCommandMap(PLOC_SPV::SET_ADC_WINDOW_AND_STRIDE); + this->insertInCommandMap(PLOC_SPV::SET_ADC_THRESHOLD); + this->insertInCommandMap(PLOC_SPV::GET_LATCHUP_STATUS_REPORT); + this->insertInCommandMap(PLOC_SPV::COPY_ADC_DATA_TO_MRAM); + this->insertInCommandMap(PLOC_SPV::ENABLE_NVMS); + this->insertInCommandMap(PLOC_SPV::SELECT_NVM); + this->insertInCommandMap(PLOC_SPV::RUN_AUTO_EM_TESTS); + this->insertInCommandMap(PLOC_SPV::WIPE_MRAM); + this->insertInCommandMap(PLOC_SPV::PRINT_CPU_STATS); + this->insertInCommandMap(PLOC_SPV::SET_DBG_VERBOSITY); + this->insertInCommandMap(PLOC_SPV::SET_GPIO); + this->insertInCommandMap(PLOC_SPV::READ_GPIO); + this->insertInCommandMap(PLOC_SPV::RESTART_SUPERVISOR); + this->insertInCommandMap(PLOC_SPV::FACTORY_RESET_CLEAR_ALL); + this->insertInCommandMap(PLOC_SPV::FACTORY_RESET_CLEAR_MIRROR); + this->insertInCommandMap(PLOC_SPV::FACTORY_RESET_CLEAR_CIRCULAR); + this->insertInCommandAndReplyMap(PLOC_SPV::DUMP_MRAM, 3); this->insertInReplyMap(PLOC_SPV::ACK_REPORT, 3, nullptr, PLOC_SPV::SIZE_ACK_REPORT); this->insertInReplyMap(PLOC_SPV::EXE_REPORT, 3, nullptr, PLOC_SPV::SIZE_EXE_REPORT); this->insertInReplyMap(PLOC_SPV::HK_REPORT, 3, &hkset, PLOC_SPV::SIZE_HK_REPORT); this->insertInReplyMap(PLOC_SPV::BOOT_STATUS_REPORT, 3, &bootStatusReport, PLOC_SPV::SIZE_BOOT_STATUS_REPORT); + this->insertInReplyMap(PLOC_SPV::LATCHUP_REPORT, 3, &latchupStatusReport, + PLOC_SPV::SIZE_LATCHUP_STATUS_REPORT); } ReturnValue_t PlocSupervisorHandler::scanForReply(const uint8_t *start, size_t remainingSize, DeviceCommandId_t *foundId, size_t *foundLen) { + if (nextReplyId == PLOC_SPV::DUMP_MRAM) { + *foundId = PLOC_SPV::DUMP_MRAM; + return parseMramPackets(start, remainingSize, foundLen); + } + ReturnValue_t result = RETURN_OK; uint16_t apid = (*(start) << 8 | *(start + 1)) & APID_MASK; @@ -176,6 +335,10 @@ ReturnValue_t PlocSupervisorHandler::scanForReply(const uint8_t *start, *foundLen = PLOC_SPV::SIZE_BOOT_STATUS_REPORT; *foundId = PLOC_SPV::BOOT_STATUS_REPORT; break; + case(PLOC_SPV::APID_LATCHUP_STATUS_REPORT): + *foundLen = PLOC_SPV::SIZE_LATCHUP_STATUS_REPORT; + *foundId = PLOC_SPV::LATCHUP_REPORT; + break; case(PLOC_SPV::APID_EXE_SUCCESS): *foundLen = PLOC_SPV::SIZE_EXE_REPORT; *foundId = PLOC_SPV::EXE_REPORT; @@ -212,6 +375,14 @@ ReturnValue_t PlocSupervisorHandler::interpretDeviceReply(DeviceCommandId_t id, result = handleBootStatusReport(packet); break; } + case (PLOC_SPV::LATCHUP_REPORT): { + result = handleLatchupStatusReport(packet); + break; + } + case (PLOC_SPV::DUMP_MRAM): { + result = handleMramDumpPacket(); + break; + } case (PLOC_SPV::EXE_REPORT): { result = handleExecutionReport(packet); break; @@ -258,9 +429,137 @@ ReturnValue_t PlocSupervisorHandler::initializeLocalDataPool(localpool::DataPool localDataPoolMap.emplace(PLOC_SPV::BP1_STATE, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::BP2_STATE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::LATCHUP_ID, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::CNT0, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::CNT1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::CNT2, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::CNT3, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::CNT4, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::CNT5, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::CNT6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::LATCHUP_RPT_TIME_SEC, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::LATCHUP_RPT_TIME_MIN, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::LATCHUP_RPT_TIME_HOUR, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::LATCHUP_RPT_TIME_DAY, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::LATCHUP_RPT_TIME_MON, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::LATCHUP_RPT_TIME_YEAR, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::LATCHUP_RPT_TIME_MSEC, new PoolEntry( { 0 })); + return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t PlocSupervisorHandler::enableReplyInReplyMap(DeviceCommandMap::iterator command, + uint8_t expectedReplies, bool useAlternateId, + DeviceCommandId_t alternateReplyID) { + + ReturnValue_t result = RETURN_OK; + + uint8_t enabledReplies = 0; + + switch (command->first) { + case PLOC_SPV::GET_HK_REPORT: { + enabledReplies = 3; + result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, + PLOC_SPV::HK_REPORT); + if (result != RETURN_OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " + << PLOC_SPV::HK_REPORT << " not in replyMap" << std::endl; + } + break; + } + case PLOC_SPV::GET_BOOT_STATUS_REPORT: { + enabledReplies = 3; + result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, + PLOC_SPV::BOOT_STATUS_REPORT); + if (result != RETURN_OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " + << PLOC_SPV::BOOT_STATUS_REPORT << " not in replyMap" << std::endl; + } + break; + } + case PLOC_SPV::GET_LATCHUP_STATUS_REPORT: { + enabledReplies = 3; + result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, + PLOC_SPV::LATCHUP_REPORT); + if (result != RETURN_OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " + << PLOC_SPV::LATCHUP_REPORT << " not in replyMap" << std::endl; + } + break; + } + case PLOC_SPV::DUMP_MRAM: { + enabledReplies = 2; // expected replies will be increased in handleMramDumpPacket + result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, + PLOC_SPV::DUMP_MRAM); + if (result != RETURN_OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " + << PLOC_SPV::LATCHUP_REPORT << " not in replyMap" << std::endl; + } + break; + } + case PLOC_SPV::RESTART_MPSOC: + case PLOC_SPV::START_MPSOC: + case PLOC_SPV::SHUTDOWN_MPSOC: + case PLOC_SPV::SEL_MPSOC_BOOT_IMAGE: + case PLOC_SPV::SET_BOOT_TIMEOUT: + case PLOC_SPV::SET_MAX_RESTART_TRIES: + case PLOC_SPV::RESET_MPSOC: + case PLOC_SPV::SET_TIME_REF: + case PLOC_SPV::UPDATE_AVAILABLE: + case PLOC_SPV::WATCHDOGS_ENABLE: + case PLOC_SPV::WATCHDOGS_CONFIG_TIMEOUT: + case PLOC_SPV::ENABLE_LATCHUP_ALERT: + case PLOC_SPV::DISABLE_LATCHUP_ALERT: + case PLOC_SPV::AUTO_CALIBRATE_ALERT: + case PLOC_SPV::SET_ALERT_LIMIT: + case PLOC_SPV::SET_ALERT_IRQ_FILTER: + case PLOC_SPV::SET_ADC_SWEEP_PERIOD: + case PLOC_SPV::SET_ADC_ENABLED_CHANNELS: + case PLOC_SPV::SET_ADC_WINDOW_AND_STRIDE: + case PLOC_SPV::SET_ADC_THRESHOLD: + case PLOC_SPV::COPY_ADC_DATA_TO_MRAM: + case PLOC_SPV::ENABLE_NVMS: + case PLOC_SPV::SELECT_NVM: + case PLOC_SPV::RUN_AUTO_EM_TESTS: + case PLOC_SPV::WIPE_MRAM: + case PLOC_SPV::SET_DBG_VERBOSITY: + case PLOC_SPV::CAN_LOOPBACK_TEST: + case PLOC_SPV::PRINT_CPU_STATS: + case PLOC_SPV::SET_GPIO: + case PLOC_SPV::READ_GPIO: + case PLOC_SPV::RESTART_SUPERVISOR: + case PLOC_SPV::FACTORY_RESET_CLEAR_ALL: + case PLOC_SPV::FACTORY_RESET_CLEAR_MIRROR: + case PLOC_SPV::FACTORY_RESET_CLEAR_CIRCULAR: + case PLOC_SPV::REQUEST_LOGGING_DATA: + 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, + PLOC_SPV::ACK_REPORT); + if (result != RETURN_OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " + << PLOC_SPV::ACK_REPORT << " not in replyMap" << std::endl; + } + + result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, + PLOC_SPV::EXE_REPORT); + if (result != RETURN_OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " + << PLOC_SPV::EXE_REPORT << " not in replyMap" << std::endl; + } + + return RETURN_OK; +} + ReturnValue_t PlocSupervisorHandler::verifyPacket(const uint8_t* start, size_t foundLen) { uint16_t receivedCrc = *(start + foundLen - 2) << 8 | *(start + foundLen - 1); @@ -493,69 +792,93 @@ ReturnValue_t PlocSupervisorHandler::handleBootStatusReport(const uint8_t* data) return result; } -ReturnValue_t PlocSupervisorHandler::enableReplyInReplyMap(DeviceCommandMap::iterator command, - uint8_t expectedReplies, bool useAlternateId, - DeviceCommandId_t alternateReplyID) { +ReturnValue_t PlocSupervisorHandler::handleLatchupStatusReport(const uint8_t* data) { ReturnValue_t result = RETURN_OK; - uint8_t enabledReplies = 0; + result = verifyPacket(data, PLOC_SPV::SIZE_LATCHUP_STATUS_REPORT); - switch (command->first) { - case PLOC_SPV::GET_HK_REPORT: { - enabledReplies = 3; - result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, - PLOC_SPV::HK_REPORT); - if (result != RETURN_OK) { - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " - << PLOC_SPV::HK_REPORT << " not in replyMap" << std::endl; - } - break; - } - case PLOC_SPV::GET_BOOT_STATUS_REPORT: { - enabledReplies = 3; - result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, - PLOC_SPV::BOOT_STATUS_REPORT); - if (result != RETURN_OK) { - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " - << PLOC_SPV::BOOT_STATUS_REPORT << " not in replyMap" << std::endl; - } - break; - } - case PLOC_SPV::RESTART_MPSOC: - case PLOC_SPV::START_MPSOC: - case PLOC_SPV::SHUTDOWN_MPSOC: - case PLOC_SPV::SEL_MPSOC_BOOT_IMAGE: - case PLOC_SPV::SET_BOOT_TIMEOUT: - case PLOC_SPV::SET_MAX_RESTART_TRIES: - case PLOC_SPV::RESET_MPSOC: - case PLOC_SPV::SET_TIME_REF: - enabledReplies = 2; - break; - default: - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Unknown command id" << std::endl; - break; + if(result == CRC_FAILURE) { + sif::error << "PlocSupervisorHandler::handleLatchupStatusReport: Latchup status report has " + << "invalid crc" << std::endl; + return result; } - /** - * Every command causes at least one acknowledgment and one execution report. Therefore both - * replies will be enabled here. - */ - result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, - PLOC_SPV::ACK_REPORT); - if (result != RETURN_OK) { - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " - << PLOC_SPV::ACK_REPORT << " not in replyMap" << std::endl; - } + uint16_t offset = PLOC_SPV::DATA_FIELD_OFFSET; + latchupStatusReport.id = *(data + offset); + offset += 1; + latchupStatusReport.cnt0 = *(data + offset) << 8 | *(data + offset + 1); + offset += 2; + latchupStatusReport.cnt1 = *(data + offset) << 8 | *(data + offset + 1); + offset += 2; + latchupStatusReport.cnt2 = *(data + offset) << 8 | *(data + offset + 1); + offset += 2; + latchupStatusReport.cnt3 = *(data + offset) << 8 | *(data + offset + 1); + offset += 2; + latchupStatusReport.cnt4 = *(data + offset) << 8 | *(data + offset + 1); + offset += 2; + latchupStatusReport.cnt5 = *(data + offset) << 8 | *(data + offset + 1); + offset += 2; + latchupStatusReport.cnt6 = *(data + offset) << 8 | *(data + offset + 1); + offset += 2; + latchupStatusReport.timeSec = *(data + offset) << 24 | *(data + offset + 1) << 16 | + *(data + offset + 2) << 8 | *(data + offset + 3); + offset += 4; + latchupStatusReport.timeMin = *(data + offset) << 24 | *(data + offset + 1) << 16 | + *(data + offset + 2) << 8 | *(data + offset + 3); + offset += 4; + latchupStatusReport.timeHour = *(data + offset) << 24 | *(data + offset + 1) << 16 | + *(data + offset + 2) << 8 | *(data + offset + 3); + offset += 4; + latchupStatusReport.timeDay = *(data + offset) << 24 | *(data + offset + 1) << 16 | + *(data + offset + 2) << 8 | *(data + offset + 3); + offset += 4; + latchupStatusReport.timeMon = *(data + offset) << 24 | *(data + offset + 1) << 16 | + *(data + offset + 2) << 8 | *(data + offset + 3); + offset += 4; + latchupStatusReport.timeYear = *(data + offset) << 24 | *(data + offset + 1) << 16 | + *(data + offset + 2) << 8 | *(data + offset + 3); + offset += 4; + latchupStatusReport.timeMsec = *(data + offset) << 24 | *(data + offset + 1) << 16 | + *(data + offset + 2) << 8 | *(data + offset + 3); + offset += 4; - result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, - PLOC_SPV::EXE_REPORT); - if (result != RETURN_OK) { - sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " - << PLOC_SPV::EXE_REPORT << " not in replyMap" << std::endl; - } + nextReplyId = PLOC_SPV::EXE_REPORT; - return RETURN_OK; +#if OBSW_VERBOSE_LEVEL >= 1 && PLOC_SUPERVISOR_DEBUG == 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: " + << latchupStatusReport.timeSec << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Min: " + << latchupStatusReport.timeMin << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Hour: " + << latchupStatusReport.timeHour << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Day: " + << latchupStatusReport.timeDay << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Mon: " + << latchupStatusReport.timeMon << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Year: " + << latchupStatusReport.timeYear << std::endl; + sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Msec: " + << latchupStatusReport.timeMsec << std::endl; +#endif + + return result; } void PlocSupervisorHandler::setNextReplyId() { @@ -566,12 +889,19 @@ void PlocSupervisorHandler::setNextReplyId() { case PLOC_SPV::GET_BOOT_STATUS_REPORT: nextReplyId = PLOC_SPV::BOOT_STATUS_REPORT; break; + case PLOC_SPV::GET_LATCHUP_STATUS_REPORT: + nextReplyId = PLOC_SPV::LATCHUP_REPORT; + break; + case PLOC_SPV::DUMP_MRAM: + nextReplyId = PLOC_SPV::DUMP_MRAM; + break; default: /* If no telemetry is expected the next reply is always the execution report */ nextReplyId = PLOC_SPV::EXE_REPORT; break; } } + size_t PlocSupervisorHandler::getNextReplyLength(DeviceCommandId_t commandId){ size_t replyLen = 0; @@ -580,6 +910,16 @@ size_t PlocSupervisorHandler::getNextReplyLength(DeviceCommandId_t commandId){ return replyLen; } + if (nextReplyId == PLOC_SPV::DUMP_MRAM) { + /** + * 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 = PLOC_SPV::MAX_PACKET_SIZE * 20; + return replyLen; + } + DeviceReplyIter iter = deviceReplyMap.find(nextReplyId); if (iter != deviceReplyMap.end()) { if (iter->second.delayCycles == 0) { @@ -624,19 +964,13 @@ void PlocSupervisorHandler::handleDeviceTM(const uint8_t* data, size_t dataSize, void PlocSupervisorHandler::prepareEmptyCmd(uint16_t apid) { PLOC_SPV::EmptyPacket packet(apid); - memcpy(commandBuffer, packet.getWholeData(), packet.getFullSize()); - rawPacket = commandBuffer; - rawPacketLen = packet.getFullSize(); - nextReplyId = PLOC_SPV::ACK_REPORT; + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); } void PlocSupervisorHandler::prepareSelBootImageCmd(const uint8_t * commandData) { PLOC_SPV::MPSoCBootSelect packet(*commandData, *(commandData + 1), *(commandData + 2), *(commandData + 3)); - memcpy(commandBuffer, packet.getWholeData(), packet.getFullSize()); - rawPacket = commandBuffer; - rawPacketLen = packet.getFullSize(); - nextReplyId = PLOC_SPV::ACK_REPORT; + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); } ReturnValue_t PlocSupervisorHandler::prepareSetTimeRefCmd() { @@ -648,38 +982,26 @@ ReturnValue_t PlocSupervisorHandler::prepareSetTimeRefCmd() { return GET_TIME_FAILURE; } PLOC_SPV::SetTimeRef packet(&time); - memcpy(commandBuffer, packet.getWholeData(), packet.getFullSize()); - rawPacket = commandBuffer; - rawPacketLen = packet.getFullSize(); - nextReplyId = PLOC_SPV::ACK_REPORT; + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); return RETURN_OK; } void PlocSupervisorHandler::prepareDisableHk() { PLOC_SPV::DisablePeriodicHkTransmission packet; - memcpy(commandBuffer, packet.getWholeData(), packet.getFullSize()); - rawPacket = commandBuffer; - rawPacketLen = packet.getFullSize(); - nextReplyId = PLOC_SPV::ACK_REPORT; + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); } void PlocSupervisorHandler::prepareSetBootTimeoutCmd(const uint8_t * commandData) { uint32_t timeout = *(commandData) << 24 | *(commandData + 1) << 16 | *(commandData + 2) << 8 | *(commandData + 3); PLOC_SPV::SetBootTimeout packet(timeout); - memcpy(commandBuffer, packet.getWholeData(), packet.getFullSize()); - rawPacket = commandBuffer; - rawPacketLen = packet.getFullSize(); - nextReplyId = PLOC_SPV::ACK_REPORT; + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); } void PlocSupervisorHandler::prepareRestartTriesCmd(const uint8_t * commandData) { uint8_t restartTries = *(commandData); PLOC_SPV::SetRestartTries packet(restartTries); - memcpy(commandBuffer, packet.getWholeData(), packet.getFullSize()); - rawPacket = commandBuffer; - rawPacketLen = packet.getFullSize(); - nextReplyId = PLOC_SPV::ACK_REPORT; + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); } void PlocSupervisorHandler::prepareUpdateAvailableCmd(const uint8_t * commandData) { @@ -699,9 +1021,225 @@ void PlocSupervisorHandler::prepareUpdateAvailableCmd(const uint8_t * commandDat PLOC_SPV::UpdateAvailable packet(imageSelect, imagePartition, imageSize, imageCrc, numberOfPackets); - memcpy(commandBuffer, packet.getWholeData(), packet.getFullSize()); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); +} + +void PlocSupervisorHandler::prepareWatchdogsEnableCmd(const uint8_t * commandData) { + uint8_t offset = 0; + uint8_t watchdogPs = *(commandData + offset); + offset += 1; + uint8_t watchdogPl = *(commandData + offset); + offset += 1; + uint8_t watchdogInt = *(commandData + offset); + PLOC_SPV::WatchdogsEnable packet(watchdogPs, watchdogPl, watchdogInt); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); +} + +ReturnValue_t PlocSupervisorHandler::prepareWatchdogsConfigTimeoutCmd(const uint8_t * commandData) { + uint8_t offset = 0; + uint8_t watchdog = *(commandData + offset); + offset += 1; + if (watchdog > 2) { + return INVALID_WATCHDOG; + } + uint32_t timeout = *(commandData + offset) << 24 | *(commandData + offset + 1) << 16 + | *(commandData + offset + 2) << 8 | *(commandData + offset + 3); + if (timeout < 1000 || timeout > 360000) { + return INVALID_WATCHDOG_TIMEOUT; + } + PLOC_SPV::WatchdogsConfigTimeout packet(watchdog, timeout); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); + return RETURN_OK; +} + +ReturnValue_t PlocSupervisorHandler::prepareLatchupConfigCmd(const uint8_t* commandData, + DeviceCommandId_t deviceCommand) { + ReturnValue_t result = RETURN_OK; + uint8_t latchupId = *commandData; + if (latchupId > 6) { + return INVALID_LATCHUP_ID; + } + switch (deviceCommand) { + case (PLOC_SPV::ENABLE_LATCHUP_ALERT): { + PLOC_SPV::LatchupAlert packet(true, latchupId); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); + break; + } + case (PLOC_SPV::DISABLE_LATCHUP_ALERT): { + PLOC_SPV::LatchupAlert packet(false, latchupId); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); + break; + } + default: { + sif::debug << "PlocSupervisorHandler::prepareLatchupConfigCmd: Invalid command id" + << std::endl; + result = RETURN_FAILED; + break; + } + } + return result; +} + +ReturnValue_t PlocSupervisorHandler::prepareAutoCalibrateAlertCmd(const uint8_t* commandData) { + uint8_t offset = 0; + uint8_t latchupId = *commandData; + offset += 1; + uint32_t mg = *(commandData + offset) << 24 | *(commandData + offset + 1) << 16 + | *(commandData + offset + 2) << 8 | *(commandData + offset + 3); + if (latchupId > 6) { + return INVALID_LATCHUP_ID; + } + PLOC_SPV::AutoCalibrateAlert packet(latchupId, mg); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); + return RETURN_OK; +} + +ReturnValue_t PlocSupervisorHandler::prepareSetAlertIrqFilterCmd(const uint8_t* commandData) { + uint8_t latchupId = *commandData; + uint8_t tp = *(commandData + 1); + uint8_t div = *(commandData + 2); + if (latchupId > 6) { + return INVALID_LATCHUP_ID; + } + PLOC_SPV::SetAlertIrqFilter packet(latchupId, tp, div); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); + return RETURN_OK; +} + +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 INVALID_LATCHUP_ID; + } + PLOC_SPV::SetAlertlimit packet(latchupId, dutycycle); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); + return RETURN_OK; +} + +ReturnValue_t PlocSupervisorHandler::prepareSetAdcSweetPeriodCmd(const uint8_t* commandData) { + uint32_t sweepPeriod = *(commandData) << 24 | *(commandData + 1) << 16 + | *(commandData + 2) << 8 | *(commandData + 3); + if (sweepPeriod < 21) { + return SWEEP_PERIOD_TOO_SMALL; + } + PLOC_SPV::SetAdcSweepPeriod packet(sweepPeriod); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); + return RETURN_OK; +} + +void PlocSupervisorHandler::prepareSetAdcEnabledChannelsCmd(const uint8_t* commandData) { + uint16_t ch = *(commandData) << 8 | *(commandData + 1); + PLOC_SPV::SetAdcEnabledChannels packet(ch); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); +} + +void 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); + PLOC_SPV::SetAdcWindowAndStride packet(windowSize, stridingStepSize); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); +} + +void PlocSupervisorHandler::prepareSetAdcThresholdCmd(const uint8_t* commandData) { + uint32_t threshold = *(commandData) << 24 | *(commandData + 1) << 16 | *(commandData + 2) << 8 + | *(commandData + 3); + PLOC_SPV::SetAdcThreshold packet(threshold); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); +} + +void PlocSupervisorHandler::prepareEnableNvmsCmd(const uint8_t* commandData) { + uint8_t n01 = *commandData; + uint8_t n3 = *(commandData + 1); + PLOC_SPV::EnableNvms packet(n01, n3); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); +} + +void PlocSupervisorHandler::prepareSelectNvmCmd(const uint8_t* commandData) { + uint8_t mem = *commandData; + PLOC_SPV::SelectNvm packet(mem); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); +} + +ReturnValue_t PlocSupervisorHandler::prepareRunAutoEmTest(const uint8_t* commandData) { + uint8_t test = *commandData; + if (test != 1 && test != 2) { + return INVALID_TEST_PARAM; + } + PLOC_SPV::RunAutoEmTests packet(test); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); + return RETURN_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 INVALID_MRAM_ADDRESSES; + } + PLOC_SPV::MramCmd packet(start, stop, PLOC_SPV::MramCmd::MramAction::WIPE); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); + return RETURN_OK; +} + +ReturnValue_t PlocSupervisorHandler::prepareDumpMramCmd(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); + PLOC_SPV::MramCmd packet(start, stop, PLOC_SPV::MramCmd::MramAction::DUMP); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); + if ((stop - start) <= 0) { + return INVALID_MRAM_ADDRESSES; + } + expectedMramDumpPackets = (stop - start) / PLOC_SPV::MAX_DATA_CAPACITY; + if ((stop - start) % PLOC_SPV::MAX_DATA_CAPACITY) { + expectedMramDumpPackets++; + } + receivedMramDumpPackets = 0; + return RETURN_OK; +} + +void PlocSupervisorHandler::preparePrintCpuStatsCmd(const uint8_t* commandData) { + uint8_t en = *commandData; + PLOC_SPV::PrintCpuStats packet(en); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); +} + +void PlocSupervisorHandler::prepareSetDbgVerbosityCmd(const uint8_t* commandData) { + uint8_t vb = *commandData; + PLOC_SPV::SetDbgVerbosity packet(vb); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); +} + +void PlocSupervisorHandler::prepareSetGpioCmd(const uint8_t* commandData) { + uint8_t port = *commandData; + uint8_t pin = *(commandData + 1); + uint8_t val = *(commandData + 2); + PLOC_SPV::SetGpio packet(port, pin, val); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); +} + +void PlocSupervisorHandler::prepareReadGpioCmd(const uint8_t* commandData) { + uint8_t port = *commandData; + uint8_t pin = *(commandData + 1); + PLOC_SPV::ReadGpio packet(port, pin); + packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); +} + +void PlocSupervisorHandler::packetToOutBuffer(uint8_t* packetData, size_t fullSize) { + memcpy(commandBuffer, packetData, fullSize); rawPacket = commandBuffer; - rawPacketLen = packet.getFullSize(); + rawPacketLen = fullSize; nextReplyId = PLOC_SPV::ACK_REPORT; } @@ -765,3 +1303,116 @@ void PlocSupervisorHandler::disableExeReportReply() { /* Expected replies is set to one here. The value will set to 0 in replyToReply() */ info->command->second.expectedReplies = 1; } + +ReturnValue_t PlocSupervisorHandler::parseMramPackets(const uint8_t *packet, size_t remainingSize, + size_t* foundLen) { + ReturnValue_t result = IGNORE_FULL_PACKET; + uint16_t packetLen = 0; + *foundLen = 0; + + for (size_t idx = 0; idx < remainingSize; idx++) { + std::memcpy(spacePacketBuffer + bufferTop, packet + idx, 1); + bufferTop += 1; + *foundLen += 1; + if (bufferTop >= PLOC_SPV::SPACE_PACKET_HEADER_LENGTH) { + packetLen = spacePacketBuffer[4] << 8 | spacePacketBuffer[5]; + } + + if (bufferTop == PLOC_SPV::SPACE_PACKET_HEADER_LENGTH + packetLen + 1) { + packetInBuffer = true; + bufferTop = 0; + return checkMramPacketApid(); + } + + if (bufferTop == PLOC_SPV::MAX_PACKET_SIZE) { + *foundLen = remainingSize; + disableAllReplies(); + bufferTop = 0; + return MRAM_PACKET_PARSING_FAILURE; + } + } + + return result; +} + +ReturnValue_t PlocSupervisorHandler::handleMramDumpPacket() { + + ReturnValue_t result = RETURN_FAILED; + + // Prepare packet for downlink + if (packetInBuffer) { + uint16_t packetLen = spacePacketBuffer[4] << 8 | spacePacketBuffer[5]; + result = verifyPacket(spacePacketBuffer, PLOC_SPV::SPACE_PACKET_HEADER_LENGTH + packetLen + 1); + if (result != RETURN_OK) { + sif::warning << "PlocSupervisorHandler::handleMramDumpPacket: CRC failure" << std::endl; + return result; + } + //TODO: Write MRAM dump to SD card handler + handleDeviceTM(spacePacketBuffer + PLOC_SPV::SPACE_PACKET_HEADER_LENGTH, packetLen - 1, + PLOC_SPV::DUMP_MRAM); + packetInBuffer = false; + receivedMramDumpPackets++; + if (expectedMramDumpPackets == receivedMramDumpPackets) { + nextReplyId = PLOC_SPV::EXE_REPORT; + } + increaseExpectedMramReplies(); + return RETURN_OK; + } + return result; +} + +void PlocSupervisorHandler::increaseExpectedMramReplies() { + DeviceReplyMap::iterator mramDumpIter = deviceReplyMap.find(PLOC_SPV::DUMP_MRAM); + DeviceReplyMap::iterator exeReportIter = deviceReplyMap.find(PLOC_SPV::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(PLOC_SPV::SequenceFlags::LAST_PKT)) { + // Command expects at least one MRAM packet more and the execution report + info->expectedReplies = 2; + // Wait maximum of 2 cycles for next MRAM packet + mramReplyInfo->delayCycles = 2; + // Also adapting delay cycles for execution report + exeReplyInfo->delayCycles = 3; + } + else { + // Command expects the execution report + info->expectedReplies = 1; + mramReplyInfo->delayCycles = 0; + } + return; +} + +ReturnValue_t PlocSupervisorHandler::checkMramPacketApid() { + uint16_t apid = (spacePacketBuffer[0] << 8 | spacePacketBuffer[1]) & PLOC_SPV::APID_MASK; + if (apid != PLOC_SPV::APID_MRAM_DUMP_TM) { + return NO_MRAM_PACKET; + } + return APERIODIC_REPLY; +} diff --git a/mission/devices/PlocSupervisorHandler.h b/mission/devices/PlocSupervisorHandler.h index 041989a3..df4645b2 100644 --- a/mission/devices/PlocSupervisorHandler.h +++ b/mission/devices/PlocSupervisorHandler.h @@ -63,6 +63,22 @@ private: static const ReturnValue_t GET_TIME_FAILURE = MAKE_RETURN_CODE(0xA4); //! [EXPORT] : [COMMENT] Invalid communication interface specified static const ReturnValue_t INVALID_UART_COM_IF = MAKE_RETURN_CODE(0xA5); + //! [EXPORT] : [COMMENT] Received command with invalid watchdog parameter. Valid watchdogs are 0 for PS, 1 for PL and 2 for INT + static const ReturnValue_t INVALID_WATCHDOG = MAKE_RETURN_CODE(0xA6); + //! [EXPORT] : [COMMENT] Received watchdog timeout config command with invalid timeout. Valid timeouts must be in the range between 1000 and 360000 ms. + static const ReturnValue_t INVALID_WATCHDOG_TIMEOUT = MAKE_RETURN_CODE(0xA7); + //! [EXPORT] : [COMMENT] Received latchup config command with invalid latchup ID + static const ReturnValue_t INVALID_LATCHUP_ID = MAKE_RETURN_CODE(0xA8); + //! [EXPORT] : [COMMENT] Received set adc sweep period command with invalid sweep period. Must be larger than 21. + static const ReturnValue_t SWEEP_PERIOD_TOO_SMALL = MAKE_RETURN_CODE(0xA9); + //! [EXPORT] : [COMMENT] Receive auto EM test command with invalid test param. Valid params are 1 and 2. + static const ReturnValue_t INVALID_TEST_PARAM = MAKE_RETURN_CODE(0xAA); + //! [EXPORT] : [COMMENT] Returned when scanning for MRAM dump packets failed. + static const ReturnValue_t MRAM_PACKET_PARSING_FAILURE = MAKE_RETURN_CODE(0xAB); + //! [EXPORT] : [COMMENT] Returned when the start and stop addresses of the MRAM dump or MRAM wipe commands are invalid (e.g. start address bigger than stop address) + static const ReturnValue_t INVALID_MRAM_ADDRESSES = MAKE_RETURN_CODE(0xAC); + //! [EXPORT] : [COMMENT] Expect reception of an MRAM dump packet but received space packet with other apid. + static const ReturnValue_t NO_MRAM_PACKET = MAKE_RETURN_CODE(0xAD); static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_SUPERVISOR_HANDLER; @@ -80,18 +96,6 @@ private: uint8_t commandBuffer[PLOC_SPV::MAX_COMMAND_SIZE]; - /** - * @brief This object is incremented each time a packet is sent or received. By checking the - * packet sequence count of a received packet, no packets can be lost without noticing - * it. Only the least significant 14 bits represent the packet sequence count in a - * space packet. Thus the maximum value amounts to 16383 (0x3FFF). - * @note Normally this should never happen because the PLOC replies are always sent in a - * fixed order. However, the PLOC software checks this value and will return an ACK - * failure report in case the sequence count is not incremented with each transferred - * space packet. - */ - uint16_t packetSequenceCount = 0x3FFF; - /** * 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 @@ -99,10 +103,22 @@ private: */ DeviceCommandId_t nextReplyId = PLOC_SPV::NONE; + UartComIF* uartComIf = nullptr; + PLOC_SPV::HkSet hkset; PLOC_SPV::BootStatusReport bootStatusReport; + PLOC_SPV::LatchupStatusReport latchupStatusReport; - UartComIF* uartComIf = 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; + /** Points to the next free position in the space packet buffer */ + uint16_t bufferTop = 0; + + /** This buffer is used to concatenate space packets received in two different read steps */ + uint8_t spacePacketBuffer[PLOC_SPV::MAX_PACKET_SIZE]; /** * @brief This function checks the crc of the received PLOC reply. @@ -148,6 +164,8 @@ private: */ ReturnValue_t handleBootStatusReport(const uint8_t* data); + ReturnValue_t handleLatchupStatusReport(const uint8_t* data); + /** * @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 @@ -172,7 +190,6 @@ private: */ void prepareEmptyCmd(uint16_t apid); - /** * @brief This function initializes the space packet to select the boot image of the MPSoC. */ @@ -200,6 +217,43 @@ private: */ void prepareUpdateAvailableCmd(const uint8_t * commandData); + /** + * @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 prepareAutoCalibrateAlertCmd(const uint8_t* commandData); + ReturnValue_t prepareSetAlertLimitCmd(const uint8_t* commandData); + ReturnValue_t prepareSetAlertIrqFilterCmd(const uint8_t* commandData); + ReturnValue_t prepareSetAdcSweetPeriodCmd(const uint8_t* commandData); + void prepareSetAdcEnabledChannelsCmd(const uint8_t* commandData); + void prepareSetAdcWindowAndStrideCmd(const uint8_t* commandData); + void prepareSetAdcThresholdCmd(const uint8_t* commandData); + void prepareEnableNvmsCmd(const uint8_t* commandData); + void prepareSelectNvmCmd(const uint8_t* commandData); + ReturnValue_t prepareRunAutoEmTest(const uint8_t* commandData); + ReturnValue_t prepareWipeMramCmd(const uint8_t* commandData); + ReturnValue_t prepareDumpMramCmd(const uint8_t* commandData); + void preparePrintCpuStatsCmd(const uint8_t* commandData); + void prepareSetDbgVerbosityCmd(const uint8_t* commandData); + void prepareSetGpioCmd(const uint8_t* commandData); + void prepareReadGpioCmd(const uint8_t* commandData); + + + /** + * @brief Copies the content of a space packet to the command buffer. + */ + void packetToOutBuffer(uint8_t* packetData, size_t fullSize); + /** * @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 @@ -221,6 +275,30 @@ private: * the variable expectedReplies of an active command will be set to 0. */ void disableExeReportReply(); + + /** + * @brief Function is called in scanForReply and fills the spacePacketBuffer with the read + * data until a full packet has been received. + */ + ReturnValue_t parseMramPackets(const uint8_t *packet, size_t remainingSize, size_t* foundlen); + + /** + * @brief This function generates the Service 8 packets for the MRAM dump data. + */ + ReturnValue_t handleMramDumpPacket(); + + /** + * @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(); + + /** + * @brief Function checks if the packet written to the space packet buffer is really a + * MRAM dump packet. + */ + ReturnValue_t checkMramPacketApid(); }; #endif /* MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ */ diff --git a/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h b/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h index 87153978..cc7be993 100644 --- a/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h +++ b/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h @@ -23,17 +23,48 @@ static const DeviceCommandId_t DISABLE_PERIOIC_HK_TRANSMISSION = 10; static const DeviceCommandId_t GET_BOOT_STATUS_REPORT = 11; /** Notifies the supervisor that a new update is available for the MPSoC */ static const DeviceCommandId_t UPDATE_AVAILABLE = 12; +static const DeviceCommandId_t WATCHDOGS_ENABLE = 13; +static const DeviceCommandId_t WATCHDOGS_CONFIG_TIMEOUT = 14; +static const DeviceCommandId_t ENABLE_LATCHUP_ALERT = 15; +static const DeviceCommandId_t DISABLE_LATCHUP_ALERT = 16; +static const DeviceCommandId_t AUTO_CALIBRATE_ALERT = 17; +static const DeviceCommandId_t SET_ALERT_LIMIT = 18; +static const DeviceCommandId_t SET_ALERT_IRQ_FILTER = 19; +static const DeviceCommandId_t SET_ADC_SWEEP_PERIOD = 20; +static const DeviceCommandId_t SET_ADC_ENABLED_CHANNELS = 21; +static const DeviceCommandId_t SET_ADC_WINDOW_AND_STRIDE = 22; +static const DeviceCommandId_t SET_ADC_THRESHOLD = 23; +static const DeviceCommandId_t GET_LATCHUP_STATUS_REPORT = 24; +static const DeviceCommandId_t COPY_ADC_DATA_TO_MRAM = 25; +static const DeviceCommandId_t ENABLE_NVMS = 26; +static const DeviceCommandId_t SELECT_NVM = 27; +static const DeviceCommandId_t RUN_AUTO_EM_TESTS = 28; +static const DeviceCommandId_t WIPE_MRAM = 29; +static const DeviceCommandId_t DUMP_MRAM = 30; +static const DeviceCommandId_t SET_DBG_VERBOSITY = 31; +static const DeviceCommandId_t CAN_LOOPBACK_TEST = 32; +static const DeviceCommandId_t PRINT_CPU_STATS = 33; +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 FACTORY_RESET_CLEAR_ALL = 37; +static const DeviceCommandId_t REQUEST_LOGGING_DATA = 38; +static const DeviceCommandId_t UPDATE_IMAGE_DATA = 39; +static const DeviceCommandId_t FACTORY_RESET_CLEAR_MIRROR = 40; +static const DeviceCommandId_t FACTORY_RESET_CLEAR_CIRCULAR = 41; /** Reply IDs */ static const DeviceCommandId_t ACK_REPORT = 50; static const DeviceCommandId_t EXE_REPORT = 51; static const DeviceCommandId_t HK_REPORT = 52; static const DeviceCommandId_t BOOT_STATUS_REPORT = 53; +static const DeviceCommandId_t LATCHUP_REPORT = 54; static const uint16_t SIZE_ACK_REPORT = 14; static const uint16_t SIZE_EXE_REPORT = 14; static const uint16_t SIZE_HK_REPORT = 48; static const uint16_t SIZE_BOOT_STATUS_REPORT = 22; +static const uint16_t SIZE_LATCHUP_STATUS_REPORT = 51; /** * SpacePacket apids of telemetry packets @@ -48,7 +79,7 @@ static const uint16_t APID_UPDATE_STATUS_REPORT = 0x206; static const uint16_t APID_WDG_STATUS_REPORT = 0x207; static const uint16_t APID_LATCHUP_STATUS_REPORT = 0x208; static const uint16_t APID_SOC_SYSMON = 0x209; -static const uint16_t APID_MRAM = 0x20A; +static const uint16_t APID_MRAM_DUMP_TM = 0x20A; static const uint16_t APID_SRAM = 0x20B; static const uint16_t APID_NOR_DATA = 0x20C; static const uint16_t APID_DATA_LOGGER_DATA = 0x20D; @@ -71,9 +102,35 @@ static const uint16_t APID_WTD_ENABLE = 0xC0; static const uint16_t APID_WTD_CONFIG_TIMEOUT = 0xC1; static const uint16_t APID_SET_TIME_REF = 0xC2; static const uint16_t APID_DISABLE_HK = 0xC3; +static const uint16_t APID_ENABLE_LATCHUP_ALERT = 0xD0; +static const uint16_t APID_DISABLE_LATCHUP_ALERT = 0xD1; +static const uint16_t APID_AUTO_CALIBRATE_ALERT = 0xD2; +static const uint16_t APID_SET_ALERT_LIMIT = 0xD3; +static const uint16_t APID_SET_ALERT_IRQ_FILTER = 0xD4; +static const uint16_t APID_SET_ADC_SWEEP_PERIOD = 0xD5; +static const uint16_t APID_SET_ADC_ENABLED_CHANNELS = 0xD6; +static const uint16_t APID_SET_ADC_WINDOW_AND_STRIDE = 0xD7; +static const uint16_t APID_SET_ADC_THRESHOLD = 0xD8; +static const uint16_t APID_GET_LATCHUP_STATUS_REPORT = 0xD9; +static const uint16_t APID_COPY_ADC_DATA_TO_MRAM = 0xDA; +static const uint16_t APID_ENABLE_NVMS = 0xF0; +static const uint16_t APID_SELECT_NVM = 0xF1; +static const uint16_t APID_RUN_AUTO_EM_TESTS = 0xF2; +static const uint16_t APID_WIPE_MRAM = 0xF3; +static const uint16_t APID_DUMP_MRAM = 0xF4; +static const uint16_t APID_SET_DBG_VERBOSITY = 0xF5; +static const uint16_t APID_CAN_LOOPBACK_TEST = 0xF6; +static const uint16_t APID_PRINT_CPU_STATS = 0xF8; +static const uint16_t APID_SET_GPIO = 0xF9; +static const uint16_t APID_READ_GPIO = 0xFA; +static const uint16_t APID_RESTART_SUPERVISOR = 0xFB; +static const uint16_t APID_FACTORY_RESET = 0xFC; +static const uint16_t APID_REQUEST_LOGGING_DATA = 0xFD; static const uint16_t APID_GET_HK_REPORT = 0xC6; +static const uint16_t APID_MASK = 0x3FF; + /** Offset from first byte in Space packet to first byte of data field */ static const uint8_t DATA_FIELD_OFFSET = 6; @@ -84,10 +141,14 @@ static const uint8_t DATA_FIELD_OFFSET = 6; static const uint16_t LENGTH_EMPTY_TC = 2; // Only CRC will be transported with the data field /** This is the maximum length of a space packet as defined by the TAS ICD */ -static const size_t MAX_REPLY_SIZE = 1024; static const size_t MAX_COMMAND_SIZE = 1024; +static const size_t MAX_DATA_CAPACITY = 1016; +/** This is the maximum size of a space packet for the supervisor */ +static const size_t MAX_PACKET_SIZE = 1024; -enum SequenceFlags { +static const uint8_t SPACE_PACKET_HEADER_LENGTH = 6; + +enum class SequenceFlags: uint8_t { CONTINUED_PKT = 0b00, FIRST_PKT = 0b01, LAST_PKT = 0b10, STANDALONE_PKT = 0b11 }; @@ -113,14 +174,33 @@ enum PoolIds ACTIVE_NVM, BP0_STATE, BP1_STATE, - BP2_STATE + BP2_STATE, + + LATCHUP_ID, + CNT0, + CNT1, + CNT2, + CNT3, + CNT4, + CNT5, + CNT6, + LATCHUP_RPT_TIME_SEC, + LATCHUP_RPT_TIME_MIN, + LATCHUP_RPT_TIME_HOUR, + LATCHUP_RPT_TIME_DAY, + LATCHUP_RPT_TIME_MON, + LATCHUP_RPT_TIME_YEAR, + LATCHUP_RPT_TIME_MSEC, + LATCHUP_RPT_TIME_USEC, }; static const uint8_t HK_SET_ENTRIES = 13; static const uint8_t BOOT_REPORT_SET_ENTRIES = 8; +static const uint8_t LATCHUP_RPT_SET_ENTRIES = 15; static const uint32_t HK_SET_ID = HK_REPORT; -static const uint32_t BOOT_REPORT_SET_ID = APID_BOOT_STATUS_REPORT; +static const uint32_t BOOT_REPORT_SET_ID = BOOT_STATUS_REPORT; +static const uint32_t LATCHUP_RPT_ID = LATCHUP_REPORT; /** * @brief With this class a space packet can be created which does not contain any data. @@ -342,34 +422,6 @@ private: } }; -/** - * @brief This dataset stores the boot status report of the supervisor. - */ -class BootStatusReport: public StaticLocalDataSet { -public: - - BootStatusReport(HasLocalDataPoolIF* owner) : - StaticLocalDataSet(owner, BOOT_REPORT_SET_ID) { - } - - BootStatusReport(object_id_t objectId) : - StaticLocalDataSet(sid_t(objectId, BOOT_REPORT_SET_ID)) { - } - - /** Information about boot status of MPSoC */ - lp_var_t bootSignal = lp_var_t(sid.objectId, PoolIds::BOOT_SIGNAL, this); - lp_var_t resetCounter = lp_var_t(sid.objectId, PoolIds::RESET_COUNTER, this); - /** Time the MPSoC needs for last boot */ - 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 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); - lp_var_t bp1State = lp_var_t(sid.objectId, PoolIds::BP1_STATE, this); - lp_var_t bp2State = lp_var_t(sid.objectId, PoolIds::BP2_STATE, this); -}; - /** * @brief This class packages the command to notify the supervisor that a new update for the * MPSoC is available. @@ -428,7 +480,6 @@ private: serializedSize = 0; uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); - serializedSize = 0; uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), SerializeIF::Endianness::BIG); @@ -470,6 +521,919 @@ private: } }; +/** + * @brief This class packages the command to enable the watchdogs of the PLOC. + */ +class WatchdogsEnable: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param watchdogPs Enables processing system watchdog + * @param watchdogPl Enables programmable logic wathdog + * @param watchdogInt + */ + WatchdogsEnable(uint8_t watchdogPs, uint8_t watchdogPl, uint8_t watchdogInt) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_WTD_ENABLE, DEFAULT_SEQUENCE_COUNT), + watchdogPs(watchdogPs), watchdogPl(watchdogPl), watchdogInt(watchdogInt) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 5; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t watchdogPs = 0; + uint8_t watchdogPl = 0; + uint8_t watchdogInt = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&watchdogPs, &data_field_ptr, &serializedSize, + sizeof(watchdogPs), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&watchdogPl, &data_field_ptr, &serializedSize, + sizeof(watchdogPl), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&watchdogInt, &data_field_ptr, &serializedSize, + sizeof(watchdogInt), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class packages the command to set the timeout of one of the three watchdogs (PS, + * PL, INT) + */ +class WatchdogsConfigTimeout: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param watchdogPs Selects the watchdog to configure (0 - PS, 1 - PL, 2 - INT) + * @param timeout The timeout to set + */ + WatchdogsConfigTimeout(uint8_t watchdog, uint32_t timeout) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_WTD_CONFIG_TIMEOUT, + DEFAULT_SEQUENCE_COUNT), watchdog(watchdog), timeout(timeout) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 7; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t watchdog = 0; + uint32_t timeout = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&watchdog, &data_field_ptr, &serializedSize, + sizeof(watchdog), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&timeout, &data_field_ptr, &serializedSize, + sizeof(timeout), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class packages the command to enable of disable the latchup alert. + * + * @details There are 7 different latchup alerts. + */ +class LatchupAlert: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param state true - enable, false - disable + * @param latchupId Identifies the latchup to enable/disable (0 - 0.85V, 1 - 1.8V, 2 - MISC, + * 3 - 3.3V, 4 - NVM_4XO, 5 - MISSION, 6 - SAFECOTS) + */ + LatchupAlert(bool state, uint8_t latchupId) : + SpacePacket(DATA_FIELD_LENGTH - 1, true), latchupId(latchupId) { + if (state) { + this->setAPID(APID_ENABLE_LATCHUP_ALERT); + } else { + this->setAPID(APID_DISABLE_LATCHUP_ALERT); + } + this->setPacketSequenceCount(DEFAULT_SEQUENCE_COUNT); + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 3; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t latchupId = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&latchupId, &data_field_ptr, &serializedSize, + sizeof(latchupId), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class packages the command to calibrate a certain latchup alert. + */ +class AutoCalibrateAlert: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param latchupId Identifies the latchup alert to calibrate (0 - 0.85V, 1 - 1.8V, 2 - MISC, + * 3 - 3.3V, 4 - NVM_4XO, 5 - MISSION, 6 - SAFECOTS) + * @param mg + */ + AutoCalibrateAlert(uint8_t latchupId, uint32_t mg) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_AUTO_CALIBRATE_ALERT, + DEFAULT_SEQUENCE_COUNT), latchupId(latchupId), mg(mg) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 7; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t latchupId = 0; + uint32_t mg = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&latchupId, &data_field_ptr, &serializedSize, + sizeof(latchupId), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&mg, &data_field_ptr, &serializedSize, + sizeof(mg), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + + +class SetAlertlimit: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param latchupId Identifies the latchup alert to calibrate (0 - 0.85V, 1 - 1.8V, 2 - MISC, + * 3 - 3.3V, 4 - NVM_4XO, 5 - MISSION, 6 - SAFECOTS) + * @param dutycycle + */ + SetAlertlimit(uint8_t latchupId, uint32_t dutycycle) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SET_ALERT_LIMIT, + DEFAULT_SEQUENCE_COUNT), latchupId(latchupId), dutycycle(dutycycle) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 7; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t latchupId = 0; + uint32_t dutycycle = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&latchupId, &data_field_ptr, &serializedSize, + sizeof(latchupId), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&dutycycle, &data_field_ptr, &serializedSize, + sizeof(dutycycle), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +class SetAlertIrqFilter: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param latchupId Identifies the latchup alert to calibrate (0 - 0.85V, 1 - 1.8V, 2 - MISC, + * 3 - 3.3V, 4 - NVM_4XO, 5 - MISSION, 6 - SAFECOTS) + * @param tp + * @param div + */ + SetAlertIrqFilter(uint8_t latchupId, uint8_t tp, uint8_t div) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SET_ALERT_IRQ_FILTER, + DEFAULT_SEQUENCE_COUNT), tp(tp), div(div) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 5; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t latchupId = 0; + uint8_t tp = 0; + uint8_t div = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&latchupId, &data_field_ptr, &serializedSize, + sizeof(latchupId), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&tp, &data_field_ptr, &serializedSize, + sizeof(tp), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&div, &data_field_ptr, &serializedSize, + sizeof(div), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + + +/** + * @brief This class packages the space packet to set the sweep period of the ADC. + */ +class SetAdcSweepPeriod: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param sweepPeriod Sweep period in us. minimum is 21 us + */ + SetAdcSweepPeriod(uint32_t sweepPeriod) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SET_ADC_SWEEP_PERIOD, + DEFAULT_SEQUENCE_COUNT), sweepPeriod(sweepPeriod) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 6; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint32_t sweepPeriod = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&sweepPeriod, &data_field_ptr, &serializedSize, + sizeof(sweepPeriod), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class packages the space packet to enable or disable ADC channels. + */ +class SetAdcEnabledChannels: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param ch Defines channels to be enabled or disabled. + */ + SetAdcEnabledChannels(uint16_t ch) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SET_ADC_ENABLED_CHANNELS, + DEFAULT_SEQUENCE_COUNT), ch(ch) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 4; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint16_t ch = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&ch, &data_field_ptr, &serializedSize, + sizeof(ch), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class packages the space packet to configures the window size and striding step of + * the moving average filter applied to the ADC readings. + */ +class SetAdcWindowAndStride: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param windowSize + * @param stridingStepSize + */ + SetAdcWindowAndStride(uint16_t windowSize, uint16_t stridingStepSize) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SET_ADC_WINDOW_AND_STRIDE, + DEFAULT_SEQUENCE_COUNT), windowSize(windowSize), stridingStepSize( + stridingStepSize) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 6; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint16_t windowSize = 0; + uint16_t stridingStepSize = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&windowSize, &data_field_ptr, &serializedSize, + sizeof(windowSize), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&stridingStepSize, &data_field_ptr, &serializedSize, + sizeof(stridingStepSize), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class packages the space packet to set the ADC trigger threshold. + */ +class SetAdcThreshold: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param threshold + */ + SetAdcThreshold(uint32_t threshold) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SET_ADC_THRESHOLD, + DEFAULT_SEQUENCE_COUNT), threshold(threshold) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 6; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint32_t threshold = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&threshold, &data_field_ptr, &serializedSize, + sizeof(threshold), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class packages the space packet to select between NVM 0 and NVM 1. + */ +class SelectNvm: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param mem 0 - select NVM0, 1 - select NVM1. + */ + SelectNvm(uint8_t mem) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SELECT_NVM, + DEFAULT_SEQUENCE_COUNT), mem(mem) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 3; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t mem = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&mem, &data_field_ptr, &serializedSize, + sizeof(mem), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class packages the space packet to power the NVMs on or off. + */ +class EnableNvms: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param n01 Set to one to power NVM0 and NVM1 on. 0 powers off memory. + * @param n3 Set to one to power NVM3 on. 0 powers off the memory. + */ + EnableNvms(uint8_t n01, uint8_t n3) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_ENABLE_NVMS, + DEFAULT_SEQUENCE_COUNT), n01(n01), n3(n3) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 4; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t n01 = 0; + uint8_t n3 = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&n01, &data_field_ptr, &serializedSize, + sizeof(n01), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&n3, &data_field_ptr, &serializedSize, + sizeof(n3), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class packages the space packet to run auto EM tests. + */ +class RunAutoEmTests: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param test 1 - complete EM test, 2 - Short test (only memory readback NVM0,1,3) + */ + RunAutoEmTests(uint8_t test) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_RUN_AUTO_EM_TESTS, + DEFAULT_SEQUENCE_COUNT), test(test) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 3; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t test = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&test, &data_field_ptr, &serializedSize, + sizeof(test), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class packages the space packet causing the supervisor to print the CPU load to + * the debug output. + */ +class PrintCpuStats: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param en Print is enabled if en != 0 + */ + PrintCpuStats(uint8_t en) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_PRINT_CPU_STATS, + DEFAULT_SEQUENCE_COUNT), en(en) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 3; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t en = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&en, &data_field_ptr, &serializedSize, + sizeof(en), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class packages the space packet to set the print verbosity in the supervisor + * software. + */ +class SetDbgVerbosity: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param vb 0: None, 1: Error, 2: Warn, 3: Info + */ + SetDbgVerbosity(uint8_t vb) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SET_DBG_VERBOSITY, + DEFAULT_SEQUENCE_COUNT), vb(vb) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 3; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t vb = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&vb, &data_field_ptr, &serializedSize, + sizeof(vb), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + + +/** + * @brief This class packages the space packet to wipe or dump parts of the MRAM. + */ +class MramCmd: public SpacePacket { +public: + + enum class MramAction { + WIPE, + DUMP + }; + + /** + * @brief Constructor + * + * @param start Start address of the MRAM section to wipe or dump + * @param stop End address of the MRAM section to wipe or dump + * @param action Dump or wipe MRAM + * + * @note The content at the stop address is excluded from the dump or wipe operation. + */ + MramCmd(uint32_t start, uint32_t stop, MramAction action) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_IDLE_PACKET, + DEFAULT_SEQUENCE_COUNT), start(start), stop(stop) { + if(action == MramAction::WIPE) { + this->setAPID(APID_WIPE_MRAM); + } + else if (action == MramAction::DUMP) { + this->setAPID(APID_DUMP_MRAM); + } + else { + sif::debug << "WipeMram: Invalid action specified"; + } + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 8; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint32_t start = 0; + uint32_t stop = 0; + + void initPacket() { + uint8_t concatBuffer[6]; + concatBuffer[0] = static_cast(start >> 16); + concatBuffer[1] = static_cast(start >> 8); + concatBuffer[2] = static_cast(start); + concatBuffer[3] = static_cast(stop >> 16); + concatBuffer[4] = static_cast(stop >> 8); + concatBuffer[5] = static_cast(stop); + uint8_t* data_field_ptr = this->localData.fields.buffer; + std::memcpy(data_field_ptr, concatBuffer, sizeof(concatBuffer)); + size_t serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class packages the space packet change the state of a GPIO. This command is only + * required for ground testing. + */ +class SetGpio: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param port + * @param pin + * @param val + */ + SetGpio(uint8_t port, uint8_t pin, uint8_t val) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SET_GPIO, + DEFAULT_SEQUENCE_COUNT), port(port), pin(pin), val(val) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 5; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t port = 0; + uint8_t pin = 0; + uint8_t val = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&port, &data_field_ptr, &serializedSize, + sizeof(port), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&pin, &data_field_ptr, &serializedSize, + sizeof(pin), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&val, &data_field_ptr, &serializedSize, + sizeof(val), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class packages the space packet causing the supervisor print the state of a GPIO + * to the debug output. + */ +class ReadGpio: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param port + * @param pin + */ + ReadGpio(uint8_t port, uint8_t pin) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_READ_GPIO, + DEFAULT_SEQUENCE_COUNT), port(port), pin(pin) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 4; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t port = 0; + uint8_t pin = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&port, &data_field_ptr, &serializedSize, + sizeof(port), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&pin, &data_field_ptr, &serializedSize, + sizeof(pin), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class packages the space packet to perform the factory reset. The op parameter is + * optional. + * + * @details: Without OP: All MRAM entries will be cleared. + * OP = 0x01: Only the mirror entries will be wiped. + * OP = 0x02: Only the circular entries will be wiped. + */ +class FactoryReset: public SpacePacket { +public: + + enum class Op { + CLEAR_ALL, + MIRROR_ENTRIES, + CIRCULAR_ENTRIES + }; + + /** + * @brief Constructor + * + * @param op + */ + FactoryReset(Op op) : + SpacePacket(0, true, APID_FACTORY_RESET, + DEFAULT_SEQUENCE_COUNT), op(op) { + initPacket(); + } + +private: + + uint16_t packetLen = 1; // only CRC in data field + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + uint8_t crcOffset = 0; + + Op op = Op::CLEAR_ALL; + + void initPacket() { + + uint8_t* data_field_ptr = this->localData.fields.buffer; + + switch(op) { + case Op::MIRROR_ENTRIES: + *data_field_ptr = 1; + packetLen = 2; + crcOffset = 1; + break; + case Op::CIRCULAR_ENTRIES: + *data_field_ptr = 2; + packetLen = 2; + crcOffset = 1; + break; + default: + break; + } + this->setPacketDataLength(packetLen); + size_t serializedSize = 0; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + packetLen - 1); + uint8_t* crcPos = this->localData.fields.buffer + crcOffset; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This dataset stores the boot status report of the supervisor. + */ +class BootStatusReport: public StaticLocalDataSet { +public: + + BootStatusReport(HasLocalDataPoolIF* owner) : + StaticLocalDataSet(owner, BOOT_REPORT_SET_ID) { + } + + BootStatusReport(object_id_t objectId) : + StaticLocalDataSet(sid_t(objectId, BOOT_REPORT_SET_ID)) { + } + + /** Information about boot status of MPSoC */ + lp_var_t bootSignal = lp_var_t(sid.objectId, PoolIds::BOOT_SIGNAL, this); + lp_var_t resetCounter = lp_var_t(sid.objectId, PoolIds::RESET_COUNTER, this); + /** Time the MPSoC needs for last boot */ + 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 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); + lp_var_t bp1State = lp_var_t(sid.objectId, PoolIds::BP1_STATE, this); + lp_var_t bp2State = lp_var_t(sid.objectId, PoolIds::BP2_STATE, this); +}; + /** * @brief This dataset stores the housekeeping data of the supervisor. */ @@ -500,6 +1464,37 @@ public: this); lp_var_t fmcState = lp_var_t(sid.objectId, PoolIds::FMC_STATE, this); }; + +/** + * @brief This dataset stores the last requested latchup status report. + */ +class LatchupStatusReport: public StaticLocalDataSet { +public: + + LatchupStatusReport(HasLocalDataPoolIF* owner) : + StaticLocalDataSet(owner, LATCHUP_RPT_ID) { + } + + LatchupStatusReport(object_id_t objectId) : + StaticLocalDataSet(sid_t(objectId, LATCHUP_RPT_ID)) { + } + + lp_var_t id = lp_var_t(sid.objectId, PoolIds::LATCHUP_ID, this); + lp_var_t cnt0 = lp_var_t(sid.objectId, PoolIds::CNT0, this); + lp_var_t cnt1 = lp_var_t(sid.objectId, PoolIds::CNT1, this); + lp_var_t cnt2 = lp_var_t(sid.objectId, PoolIds::CNT2, this); + lp_var_t cnt3 = lp_var_t(sid.objectId, PoolIds::CNT3, this); + lp_var_t cnt4 = lp_var_t(sid.objectId, PoolIds::CNT4, this); + lp_var_t cnt5 = lp_var_t(sid.objectId, PoolIds::CNT5, this); + lp_var_t cnt6 = lp_var_t(sid.objectId, PoolIds::CNT6, this); + lp_var_t timeSec = lp_var_t(sid.objectId, PoolIds::LATCHUP_RPT_TIME_SEC, this); + lp_var_t timeMin = lp_var_t(sid.objectId, PoolIds::LATCHUP_RPT_TIME_MIN, this); + lp_var_t timeHour = lp_var_t(sid.objectId, PoolIds::LATCHUP_RPT_TIME_HOUR, this); + lp_var_t timeDay = lp_var_t(sid.objectId, PoolIds::LATCHUP_RPT_TIME_DAY, this); + lp_var_t timeMon = lp_var_t(sid.objectId, PoolIds::LATCHUP_RPT_TIME_MON, this); + lp_var_t timeYear = lp_var_t(sid.objectId, PoolIds::LATCHUP_RPT_TIME_YEAR, this); + lp_var_t timeMsec = lp_var_t(sid.objectId, PoolIds::LATCHUP_RPT_TIME_MSEC, this); +}; } #endif /* MISSION_DEVICES_DEVICEDEFINITIONS_PLOCSVPDEFINITIONS_H_ */