#include #include #include #include #include "PlocSupervisorHandler.h" #include "OBSWConfig.h" #include #include #include 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; } } PlocSupervisorHandler::~PlocSupervisorHandler() { } ReturnValue_t PlocSupervisorHandler::initialize() { ReturnValue_t result = RETURN_OK; result = DeviceHandlerBase::initialize(); if (result != RETURN_OK) { return result; } uartComIf = dynamic_cast(communicationInterface); if (uartComIf == nullptr) { sif::warning << "PlocSupervisorHandler::initialize: Invalid uart com if" << std::endl; return INVALID_UART_COM_IF; } sdcMan = SdCardManager::instance(); return result; } void PlocSupervisorHandler::doStartUp(){ #if OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP == 1 setMode(MODE_NORMAL); #else setMode(_MODE_TO_ON); #endif } void PlocSupervisorHandler::doShutDown(){ setMode(_MODE_POWER_DOWN); } ReturnValue_t PlocSupervisorHandler::buildNormalDeviceCommand( DeviceCommandId_t * id) { return NOTHING_TO_SEND; } ReturnValue_t PlocSupervisorHandler::buildTransitionDeviceCommand( DeviceCommandId_t * id){ return NOTHING_TO_SEND; } ReturnValue_t PlocSupervisorHandler::buildCommandFromCommand( DeviceCommandId_t deviceCommand, const uint8_t * commandData, size_t commandDataLen) { ReturnValue_t result = RETURN_FAILED; switch(deviceCommand) { case(PLOC_SPV::GET_HK_REPORT): { prepareEmptyCmd(PLOC_SPV::APID_GET_HK_REPORT); result = RETURN_OK; break; } case(PLOC_SPV::RESTART_MPSOC): { prepareEmptyCmd(PLOC_SPV::APID_RESTART_MPSOC); result = RETURN_OK; break; } case(PLOC_SPV::START_MPSOC): { prepareEmptyCmd(PLOC_SPV::APID_START_MPSOC); result = RETURN_OK; break; } case(PLOC_SPV::SHUTDOWN_MPSOC): { prepareEmptyCmd(PLOC_SPV::APID_SHUTWOWN_MPSOC); result = RETURN_OK; break; } case(PLOC_SPV::SEL_MPSOC_BOOT_IMAGE): { prepareSelBootImageCmd(commandData); result = RETURN_OK; break; } case(PLOC_SPV::RESET_MPSOC): { prepareEmptyCmd(PLOC_SPV::APID_RESET_MPSOC); result = RETURN_OK; break; } case(PLOC_SPV::SET_TIME_REF): { result = prepareSetTimeRefCmd(); break; } case(PLOC_SPV::SET_BOOT_TIMEOUT): { prepareSetBootTimeoutCmd(commandData); result = RETURN_OK; break; } case(PLOC_SPV::SET_MAX_RESTART_TRIES): { prepareRestartTriesCmd(commandData); result = RETURN_OK; break; } case(PLOC_SPV::DISABLE_PERIOIC_HK_TRANSMISSION): { prepareDisableHk(); result = RETURN_OK; break; } case(PLOC_SPV::GET_BOOT_STATUS_REPORT): { prepareEmptyCmd(PLOC_SPV::APID_GET_BOOT_STATUS_RPT); 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::CAN_LOOPBACK_TEST): { prepareEmptyCmd(PLOC_SPV::APID_CAN_LOOPBACK_TEST); 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; } case(PLOC_SPV::UPDATE_AVAILABLE): case(PLOC_SPV::UPDATE_IMAGE_DATA): case(PLOC_SPV::UPDATE_VERIFY): // Simply forward data from PLOC Updater to supervisor std::memcpy(commandBuffer, commandData, commandDataLen); rawPacket = commandBuffer; rawPacketLen = commandDataLen; nextReplyId = PLOC_SPV::ACK_REPORT; result = RETURN_OK; break; default: sif::debug << "PlocSupervisorHandler::buildCommandFromCommand: Command not implemented" << std::endl; result = DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; break; } if (result == RETURN_OK) { /** * Flushing the receive buffer to make sure there are no data left from a faulty reply. */ uartComIf->flushUartRxBuffer(comCookie); } return result; } void PlocSupervisorHandler::fillCommandAndReplyMap() { this->insertInCommandMap(PLOC_SPV::GET_HK_REPORT); this->insertInCommandMap(PLOC_SPV::RESTART_MPSOC); this->insertInCommandMap(PLOC_SPV::START_MPSOC); this->insertInCommandMap(PLOC_SPV::SHUTDOWN_MPSOC); this->insertInCommandMap(PLOC_SPV::SEL_MPSOC_BOOT_IMAGE); this->insertInCommandMap(PLOC_SPV::SET_BOOT_TIMEOUT); this->insertInCommandMap(PLOC_SPV::SET_MAX_RESTART_TRIES); this->insertInCommandMap(PLOC_SPV::RESET_MPSOC); 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::UPDATE_VERIFY); this->insertInCommandMap(PLOC_SPV::UPDATE_IMAGE_DATA); 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->insertInCommandMap(PLOC_SPV::CAN_LOOPBACK_TEST); 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; switch(apid) { case(PLOC_SPV::APID_ACK_SUCCESS): *foundLen = PLOC_SPV::SIZE_ACK_REPORT; *foundId = PLOC_SPV::ACK_REPORT; break; case(PLOC_SPV::APID_ACK_FAILURE): *foundLen = PLOC_SPV::SIZE_ACK_REPORT; *foundId = PLOC_SPV::ACK_REPORT; break; case(PLOC_SPV::APID_HK_REPORT): *foundLen = PLOC_SPV::SIZE_HK_REPORT; *foundId = PLOC_SPV::HK_REPORT; break; case(PLOC_SPV::APID_BOOT_STATUS_REPORT): *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; break; case(PLOC_SPV::APID_EXE_FAILURE): *foundLen = PLOC_SPV::SIZE_EXE_REPORT; *foundId = PLOC_SPV::EXE_REPORT; break; default: { sif::debug << "PlocSupervisorHandler::scanForReply: Reply has invalid apid" << std::endl; *foundLen = remainingSize; return INVALID_APID; } } return result; } ReturnValue_t PlocSupervisorHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { ReturnValue_t result = RETURN_OK; switch (id) { case PLOC_SPV::ACK_REPORT: { result = handleAckReport(packet); break; } case (PLOC_SPV::HK_REPORT): { result = handleHkReport(packet); break; } case (PLOC_SPV::BOOT_STATUS_REPORT): { 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; } default: { sif::debug << "PlocSupervisorHandler::interpretDeviceReply: Unknown device reply id" << std::endl; return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY; } } return result; } void PlocSupervisorHandler::setNormalDatapoolEntriesInvalid(){ } uint32_t PlocSupervisorHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo){ return 500; } ReturnValue_t PlocSupervisorHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { localDataPoolMap.emplace(PLOC_SPV::NUM_TMS, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::TEMP_PS, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::TEMP_PL, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::SOC_STATE, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::NVM0_1_STATE, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::NVM3_STATE, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::MISSION_IO_STATE, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::FMC_STATE, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::NUM_TCS, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::UPTIME, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::CPULOAD, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::AVAILABLEHEAP, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::BOOT_SIGNAL, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::RESET_COUNTER, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::BOOT_AFTER_MS, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::BOOT_TIMEOUT_MS, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::ACTIVE_NVM, new PoolEntry( { 0 })); localDataPoolMap.emplace(PLOC_SPV::BP0_STATE, new PoolEntry( { 0 })); 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::UPDATE_IMAGE_DATA: case PLOC_SPV::UPDATE_VERIFY: 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); uint16_t recalculatedCrc = CRC::crc16ccitt(start, foundLen - 2); if (receivedCrc != recalculatedCrc) { return CRC_FAILURE; } return RETURN_OK; } ReturnValue_t PlocSupervisorHandler::handleAckReport(const uint8_t* data) { ReturnValue_t result = RETURN_OK; result = verifyPacket(data, PLOC_SPV::SIZE_ACK_REPORT); if(result == CRC_FAILURE) { sif::error << "PlocSupervisorHandler::handleAckReport: CRC failure" << std::endl; nextReplyId = PLOC_SPV::NONE; replyRawReplyIfnotWiretapped(data, PLOC_SPV::SIZE_ACK_REPORT); triggerEvent(SUPV_CRC_FAILURE_EVENT); sendFailureReport(PLOC_SPV::ACK_REPORT, CRC_FAILURE); disableAllReplies(); return RETURN_OK; } uint16_t apid = (*(data) << 8 | *(data + 1)) & APID_MASK; switch(apid) { case PLOC_SPV::APID_ACK_FAILURE: { //TODO: Interpretation of status field in acknowledgment report sif::debug << "PlocSupervisorHandler::handleAckReport: Received Ack failure report" << std::endl; DeviceCommandId_t commandId = getPendingCommand(); if (commandId != DeviceHandlerIF::NO_COMMAND_ID) { triggerEvent(SUPV_ACK_FAILURE, commandId); } sendFailureReport(PLOC_SPV::ACK_REPORT, RECEIVED_ACK_FAILURE); disableAllReplies(); nextReplyId = PLOC_SPV::NONE; result = IGNORE_REPLY_DATA; break; } case PLOC_SPV::APID_ACK_SUCCESS: { setNextReplyId(); break; } default: { sif::debug << "PlocSupervisorHandler::handleAckReport: Invalid APID in Ack report" << std::endl; result = RETURN_FAILED; break; } } return result; } ReturnValue_t PlocSupervisorHandler::handleExecutionReport(const uint8_t* data) { ReturnValue_t result = RETURN_OK; result = verifyPacket(data, PLOC_SPV::SIZE_EXE_REPORT); if(result == CRC_FAILURE) { sif::error << "PlocSupervisorHandler::handleExecutionReport: CRC failure" << std::endl; nextReplyId = PLOC_SPV::NONE; return result; } uint16_t apid = (*(data) << 8 | *(data + 1)) & APID_MASK; switch (apid) { case (PLOC_SPV::APID_EXE_SUCCESS): { break; } case (PLOC_SPV::APID_EXE_FAILURE): { //TODO: Interpretation of status field in execution report sif::error << "PlocSupervisorHandler::handleExecutionReport: Received execution failure report" << std::endl; DeviceCommandId_t commandId = getPendingCommand(); if (commandId != DeviceHandlerIF::NO_COMMAND_ID) { triggerEvent(SUPV_EXE_FAILURE, commandId); } else { sif::debug << "PlocSupervisorHandler::handleExecutionReport: Unknown command id" << std::endl; } sendFailureReport(PLOC_SPV::EXE_REPORT, RECEIVED_EXE_FAILURE); disableExeReportReply(); result = IGNORE_REPLY_DATA; break; } default: { sif::error << "PlocSupervisorHandler::handleExecutionReport: Unknown APID" << std::endl; result = RETURN_FAILED; break; } } nextReplyId = PLOC_SPV::NONE; return result; } ReturnValue_t PlocSupervisorHandler::handleHkReport(const uint8_t* data) { ReturnValue_t result = RETURN_OK; result = verifyPacket(data, PLOC_SPV::SIZE_HK_REPORT); if(result == CRC_FAILURE) { sif::error << "PlocSupervisorHandler::handleHkReport: Hk report has invalid crc" << std::endl; } uint16_t offset = PLOC_SPV::DATA_FIELD_OFFSET; hkset.tempPs = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | *(data + offset + 3); offset += 4; hkset.tempPl = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | *(data + offset + 3); offset += 4; hkset.tempSup = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | *(data + offset + 3); offset += 4; hkset.uptime = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | *(data + offset + 3); offset += 4; hkset.cpuLoad = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | *(data + offset + 3); offset += 4; hkset.availableHeap = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | *(data + offset + 3); offset += 4; hkset.numTcs = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | *(data + offset + 3); offset += 4; hkset.numTms = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | *(data + offset + 3); offset += 4; hkset.socState = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | *(data + offset + 3); offset += 4; hkset.nvm0_1_state = *(data + offset); offset += 1; hkset.nvm3_state = *(data + offset); offset += 1; hkset.missionIoState = *(data + offset); offset += 1; hkset.fmcState = *(data + offset); offset += 1; nextReplyId = PLOC_SPV::EXE_REPORT; #if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_PLOC_SUPERVISOR == 1 sif::info << "PlocSupervisorHandler::handleHkReport: temp_ps: " << hkset.tempPs << std::endl; sif::info << "PlocSupervisorHandler::handleHkReport: temp_pl: " << hkset.tempPl << std::endl; sif::info << "PlocSupervisorHandler::handleHkReport: temp_sup: " << hkset.tempSup << std::endl; sif::info << "PlocSupervisorHandler::handleHkReport: uptime: " << hkset.uptime << std::endl; sif::info << "PlocSupervisorHandler::handleHkReport: cpu_load: " << hkset.cpuLoad << std::endl; sif::info << "PlocSupervisorHandler::handleHkReport: available_heap: " << hkset.availableHeap << std::endl; sif::info << "PlocSupervisorHandler::handleHkReport: num_tcs: " << hkset.numTcs << std::endl; sif::info << "PlocSupervisorHandler::handleHkReport: num_tms: " << hkset.numTms << std::endl; sif::info << "PlocSupervisorHandler::handleHkReport: soc_state: " << hkset.socState << std::endl; sif::info << "PlocSupervisorHandler::handleHkReport: nvm0_1_state: " << static_cast(hkset.nvm0_1_state.value) << std::endl; sif::info << "PlocSupervisorHandler::handleHkReport: nvm3_state: " << static_cast(hkset.nvm3_state.value) << std::endl; sif::info << "PlocSupervisorHandler::handleHkReport: missoin_io_state: " << static_cast(hkset.missionIoState.value) << std::endl; sif::info << "PlocSupervisorHandler::handleHkReport: fmc_state: " << static_cast(hkset.fmcState.value) << std::endl; #endif return result; } ReturnValue_t PlocSupervisorHandler::handleBootStatusReport(const uint8_t* data) { ReturnValue_t result = RETURN_OK; result = verifyPacket(data, PLOC_SPV::SIZE_BOOT_STATUS_REPORT); if(result == CRC_FAILURE) { sif::error << "PlocSupervisorHandler::handleBootStatusReport: Boot status report has invalid" " crc" << std::endl; return result; } uint16_t offset = PLOC_SPV::DATA_FIELD_OFFSET; bootStatusReport.bootSignal = *(data + offset); offset += 1; bootStatusReport.resetCounter = *(data + offset); offset += 1; bootStatusReport.bootAfterMs = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | *(data + offset + 3); offset += 4; bootStatusReport.bootTimeoutMs = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 | *(data + offset + 3); offset += 4; bootStatusReport.activeNvm = *(data + offset); offset += 1; bootStatusReport.bp0State = *(data + offset); offset += 1; bootStatusReport.bp1State = *(data + offset); offset += 1; bootStatusReport.bp2State = *(data + offset); nextReplyId = PLOC_SPV::EXE_REPORT; #if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_PLOC_SUPERVISOR == 1 sif::info << "PlocSupervisorHandler::handleBootStatusReport: Boot signal: " << static_cast(bootStatusReport.bootSignal.value) << std::endl; sif::info << "PlocSupervisorHandler::handleBootStatusReport: Reset counter: " << static_cast(bootStatusReport.resetCounter.value) << std::endl; sif::info << "PlocSupervisorHandler::handleBootStatusReport: BootAfterMs: " << bootStatusReport.bootAfterMs << " ms" << std::endl; sif::info << "PlocSupervisorHandler::handleBootStatusReport: BootTimeoutMs: " << bootStatusReport.bootTimeoutMs << " ms" << std::endl; sif::info << "PlocSupervisorHandler::handleBootStatusReport: Active NVM: " << static_cast(bootStatusReport.activeNvm.value) << std::endl; sif::info << "PlocSupervisorHandler::handleBootStatusReport: BP0: " << static_cast(bootStatusReport.bp0State.value) << std::endl; sif::info << "PlocSupervisorHandler::handleBootStatusReport: BP1: " << static_cast(bootStatusReport.bp1State.value) << std::endl; sif::info << "PlocSupervisorHandler::handleBootStatusReport: BP2: " << static_cast(bootStatusReport.bp2State.value) << std::endl; #endif return result; } ReturnValue_t PlocSupervisorHandler::handleLatchupStatusReport(const uint8_t* data) { ReturnValue_t result = RETURN_OK; result = verifyPacket(data, PLOC_SPV::SIZE_LATCHUP_STATUS_REPORT); if(result == CRC_FAILURE) { sif::error << "PlocSupervisorHandler::handleLatchupStatusReport: Latchup status report has " << "invalid crc" << std::endl; return result; } 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; nextReplyId = PLOC_SPV::EXE_REPORT; #if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_PLOC_SUPERVISOR == 1 sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Latchup ID: " << static_cast(latchupStatusReport.id.value) << std::endl; sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: CNT0: " << latchupStatusReport.cnt0 << std::endl; sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: CNT1: " << latchupStatusReport.cnt1 << std::endl; sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: CNT2: " << latchupStatusReport.cnt2 << std::endl; sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: CNT3: " << latchupStatusReport.cnt3 << std::endl; sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: CNT4: " << latchupStatusReport.cnt4 << std::endl; sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: CNT5: " << latchupStatusReport.cnt5 << std::endl; sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: CNT6: " << latchupStatusReport.cnt6 << std::endl; sif::info << "PlocSupervisorHandler::handleLatchupStatusReport: Sec: " << 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() { switch(getPendingCommand()) { case PLOC_SPV::GET_HK_REPORT: nextReplyId = PLOC_SPV::HK_REPORT; break; 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; if (nextReplyId == PLOC_SPV::NONE) { 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) { /* Reply inactive */ return replyLen; } replyLen = iter->second.replyLen; } else { sif::debug << "PlocSupervisorHandler::getNextReplyLength: No entry for reply with reply id " << std::hex << nextReplyId << " in deviceReplyMap" << std::endl; } return replyLen; } void PlocSupervisorHandler::handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId) { ReturnValue_t result = RETURN_OK; if (wiretappingMode == RAW) { /* Data already sent in doGetRead() */ return; } DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId); if (iter == deviceReplyMap.end()) { sif::debug << "PlocSupervisorHandler::handleDeviceTM: Unknown reply id" << std::endl; return; } MessageQueueId_t queueId = iter->second.command->second.sendReplyTo; if (queueId == NO_COMMANDER) { return; } result = actionHelper.reportData(queueId, replyId, data, dataSize); if (result != RETURN_OK) { sif::debug << "PlocSupervisorHandler::handleDeviceTM: Failed to report data" << std::endl; } } void PlocSupervisorHandler::prepareEmptyCmd(uint16_t apid) { PLOC_SPV::EmptyPacket packet(apid); packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); } void PlocSupervisorHandler::prepareSelBootImageCmd(const uint8_t * commandData) { PLOC_SPV::MPSoCBootSelect packet(*commandData, *(commandData + 1), *(commandData + 2), *(commandData + 3)); packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); } ReturnValue_t PlocSupervisorHandler::prepareSetTimeRefCmd() { Clock::TimeOfDay_t time; ReturnValue_t result = Clock::getDateAndTime(&time); if (result != RETURN_OK) { sif::warning << "PlocSupervisorHandler::prepareSetTimeRefCmd: Failed to get current time" << std::endl; return GET_TIME_FAILURE; } PLOC_SPV::SetTimeRef packet(&time); packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); return RETURN_OK; } void PlocSupervisorHandler::prepareDisableHk() { PLOC_SPV::DisablePeriodicHkTransmission packet; 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); packetToOutBuffer(packet.getWholeData(), packet.getFullSize()); } void PlocSupervisorHandler::prepareRestartTriesCmd(const uint8_t * commandData) { uint8_t restartTries = *(commandData); PLOC_SPV::SetRestartTries packet(restartTries); 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 = fullSize; nextReplyId = PLOC_SPV::ACK_REPORT; } void PlocSupervisorHandler::disableAllReplies() { DeviceReplyMap::iterator iter; /* Disable ack reply */ iter = deviceReplyMap.find(PLOC_SPV::ACK_REPORT); DeviceReplyInfo *info = &(iter->second); info->delayCycles = 0; info->command = deviceCommandMap.end(); DeviceCommandId_t commandId = getPendingCommand(); /* If the command expects a telemetry packet the appropriate tm reply will be disabled here */ switch (commandId) { case PLOC_SPV::GET_HK_REPORT: { iter = deviceReplyMap.find(PLOC_SPV::GET_HK_REPORT); info = &(iter->second); info->delayCycles = 0; info->command = deviceCommandMap.end(); break; } default: { break; } } /* We must always disable the execution report reply here */ disableExeReportReply(); } void PlocSupervisorHandler::sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status) { DeviceReplyIter iter = deviceReplyMap.find(replyId); if (iter == deviceReplyMap.end()) { sif::debug << "PlocSupervisorHandler::sendFailureReport: Reply not in reply map" << std::endl; return; } DeviceCommandInfo* info = &(iter->second.command->second); if (info == nullptr) { sif::debug << "PlocSupervisorHandler::sendFailureReport: Reply has no active command" << std::endl; return; } if (info->sendReplyTo != NO_COMMANDER) { actionHelper.finish(false, info->sendReplyTo, iter->first, status); } info->isExecuting = false; } void PlocSupervisorHandler::disableExeReportReply() { DeviceReplyIter iter = deviceReplyMap.find(PLOC_SPV::EXE_REPORT); DeviceReplyInfo *info = &(iter->second); info->delayCycles = 0; info->command = deviceCommandMap.end(); /* 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 = readSpacePacketLength(spacePacketBuffer); } 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 = readSpacePacketLength(spacePacketBuffer); 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; } handleMramDumpFile(); if (downlinkMramDump == true) { 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; } ReturnValue_t PlocSupervisorHandler::handleMramDumpFile() { ReturnValue_t result = RETURN_OK; uint16_t packetLen = readSpacePacketLength(spacePacketBuffer); uint8_t sequenceFlags = readSequenceFlags(spacePacketBuffer); if (sequenceFlags == static_cast(PLOC_SPV::SequenceFlags::FIRST_PKT)) { result = createMramDumpFile(); if (result != RETURN_OK) { return result; } } if (not std::filesystem::exists(activeMramFile)) { sif::warning << "PlocSupervisorHandler::handleMramDumpFile: MRAM file does not exist" << std::endl; return MRAM_FILE_NOT_EXISTS; } std::ofstream file(activeMramFile, std::ios_base::app | std::ios_base::out); file.write( reinterpret_cast(spacePacketBuffer + PLOC_SPV::SPACE_PACKET_HEADER_LENGTH), packetLen - 1); file.close(); return RETURN_OK; } uint16_t PlocSupervisorHandler::readSpacePacketLength(uint8_t* spacePacket) { return spacePacket[4] << 8 | spacePacket[5]; } uint8_t PlocSupervisorHandler::readSequenceFlags(uint8_t* spacePacket) { return spacePacketBuffer[2] >> 6; } ReturnValue_t PlocSupervisorHandler::createMramDumpFile() { ReturnValue_t result = RETURN_OK; std::string timeStamp; result = getTimeStampString(timeStamp); if (result != RETURN_OK) { return result; } std::string filename = "mram-dump--" + timeStamp + ".bin"; std::string currentMountPrefix = sdcMan->getCurrentMountPrefix(); // Check if path to PLOC directory exists if (not std::filesystem::exists(std::string(currentMountPrefix + "/" + plocFilePath))) { sif::warning << "PlocSupervisorHandler::createMramDumpFile: Ploc path does not exist" << std::endl; return PATH_DOES_NOT_EXIST; } activeMramFile = currentMountPrefix + "/" + plocFilePath + "/" + filename; // Create new file std::ofstream file(activeMramFile, std::ios_base::out); file.close(); return RETURN_OK; } ReturnValue_t PlocSupervisorHandler::getTimeStampString(std::string& timeStamp) { Clock::TimeOfDay_t time; ReturnValue_t result = Clock::getDateAndTime(&time); if (result != RETURN_OK) { sif::warning << "PlocSupervisorHandler::createMramDumpFile: Failed to get current time" << std::endl; return GET_TIME_FAILURE; } timeStamp = std::to_string(time.year) + "-" + std::to_string(time.month) + "-" + std::to_string(time.day) + "--" + std::to_string(time.hour) + "-" + std::to_string(time.minute) + "-" + std::to_string(time.second); return RETURN_OK; }