diff --git a/mission/devices/PlocSupervisorHandler.cpp b/mission/devices/PlocSupervisorHandler.cpp index 4dcb2a16..367cc642 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; } @@ -136,6 +138,38 @@ ReturnValue_t PlocSupervisorHandler::buildCommandFromCommand( 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; } default: sif::debug << "PlocSupervisorHandler::buildCommandFromCommand: Command not implemented" @@ -171,12 +205,21 @@ void PlocSupervisorHandler::fillCommandAndReplyMap() { 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::APID_AUTO_CALIBRATE_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->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, @@ -285,9 +328,126 @@ 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::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::DUMP_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: + 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); @@ -520,75 +680,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_BOOT_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: - 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: - 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() { @@ -599,12 +777,16 @@ 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; 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; @@ -787,6 +969,65 @@ ReturnValue_t PlocSupervisorHandler::prepareAutoCalibrateAlertCmd(const uint8_t* 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::packetToOutBuffer(uint8_t* packetData, size_t fullSize) { memcpy(commandBuffer, packetData, fullSize); rawPacket = commandBuffer; diff --git a/mission/devices/PlocSupervisorHandler.h b/mission/devices/PlocSupervisorHandler.h index bbbbf25e..59c51a13 100644 --- a/mission/devices/PlocSupervisorHandler.h +++ b/mission/devices/PlocSupervisorHandler.h @@ -66,9 +66,11 @@ private: //! [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(0xA6); + 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(0xA7); + 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(0x9); static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_SUPERVISOR_HANDLER; @@ -105,10 +107,11 @@ private: */ DeviceCommandId_t nextReplyId = PLOC_SPV::NONE; + UartComIF* uartComIf = nullptr; + PLOC_SPV::HkSet hkset; PLOC_SPV::BootStatusReport bootStatusReport; - - UartComIF* uartComIf = nullptr; + PLOC_SPV::LatchupStatusReport latchupStatusReport; /** * @brief This function checks the crc of the received PLOC reply. @@ -154,6 +157,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 @@ -220,6 +225,12 @@ private: 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); /** diff --git a/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h b/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h index 28349dab..7eb7c163 100644 --- a/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h +++ b/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h @@ -28,17 +28,40 @@ 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 = 37; +static const DeviceCommandId_t REQUEST_LOGGING_DATA = 38; /** 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 = 55; /** * SpacePacket apids of telemetry packets @@ -142,14 +165,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. @@ -661,6 +703,266 @@ private: } }; + +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 dataset stores the boot status report of the supervisor. */ @@ -719,6 +1021,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_ */