diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index b72bbf62..1285a56b 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -360,7 +360,7 @@ void CoreController::initPrint() { #if OBSW_VERBOSE_LEVEL >= 1 #if OBSW_USE_TMTC_TCP_BRIDGE == 0 sif::info << "Created UDP server for TMTC commanding with listener port " << - TcpTmTcBridge::DEFAULT_UDP_SERVER_PORT << std::endl; + UdpTmTcBridge::DEFAULT_UDP_SERVER_PORT << std::endl; #else sif::info << "Created TCP server for TMTC commanding with listener port " << TcpTmTcBridge::DEFAULT_TCP_SERVER_PORT << std::endl; diff --git a/mission/devices/PlocSupervisorHandler.cpp b/mission/devices/PlocSupervisorHandler.cpp index 21310248..5af3693b 100644 --- a/mission/devices/PlocSupervisorHandler.cpp +++ b/mission/devices/PlocSupervisorHandler.cpp @@ -6,7 +6,7 @@ #include PlocSupervisorHandler::PlocSupervisorHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF * comCookie) : - DeviceHandlerBase(objectId, uartComIFid, comCookie), hkset(this) { + DeviceHandlerBase(objectId, uartComIFid, comCookie), hkset(this), bootStatusReport(this) { if (comCookie == NULL) { sif::error << "PlocSupervisorHandler: Invalid com cookie" << std::endl; } @@ -105,6 +105,16 @@ ReturnValue_t PlocSupervisorHandler::buildCommandFromCommand( 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::UPDATE_AVAILABLE): { + prepareUpdateAvailableCmd(commandData); + result = RETURN_OK; + break; } default: sif::debug << "PlocSupervisorHandler::buildCommandFromCommand: Command not implemented" @@ -134,9 +144,12 @@ void PlocSupervisorHandler::fillCommandAndReplyMap() { 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->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, nullptr, PLOC_SPV::SIZE_HK_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); } ReturnValue_t PlocSupervisorHandler::scanForReply(const uint8_t *start, @@ -159,6 +172,10 @@ ReturnValue_t PlocSupervisorHandler::scanForReply(const uint8_t *start, *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_EXE_SUCCESS): *foundLen = PLOC_SPV::SIZE_EXE_REPORT; *foundId = PLOC_SPV::EXE_REPORT; @@ -191,6 +208,10 @@ ReturnValue_t PlocSupervisorHandler::interpretDeviceReply(DeviceCommandId_t id, result = handleHkReport(packet); break; } + case (PLOC_SPV::BOOT_STATUS_REPORT): { + result = handleBootStatusReport(packet); + break; + } case (PLOC_SPV::EXE_REPORT): { result = handleExecutionReport(packet); break; @@ -228,6 +249,15 @@ ReturnValue_t PlocSupervisorHandler::initializeLocalDataPool(localpool::DataPool 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 })); + return HasReturnvaluesIF::RETURN_OK; } @@ -408,6 +438,61 @@ ReturnValue_t PlocSupervisorHandler::handleHkReport(const uint8_t* data) { 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 && PLOC_SUPERVISOR_DEBUG == 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::enableReplyInReplyMap(DeviceCommandMap::iterator command, uint8_t expectedReplies, bool useAlternateId, DeviceCommandId_t alternateReplyID) { @@ -427,6 +512,16 @@ ReturnValue_t PlocSupervisorHandler::enableReplyInReplyMap(DeviceCommandMap::ite } 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: @@ -468,6 +563,9 @@ void PlocSupervisorHandler::setNextReplyId() { 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; default: /* If no telemetry is expected the next reply is always the execution report */ nextReplyId = PLOC_SPV::EXE_REPORT; @@ -584,6 +682,29 @@ void PlocSupervisorHandler::prepareRestartTriesCmd(const uint8_t * commandData) nextReplyId = PLOC_SPV::ACK_REPORT; } +void PlocSupervisorHandler::prepareUpdateAvailableCmd(const uint8_t * commandData) { + uint8_t offset = 0; + uint8_t imageSelect = *(commandData + offset); + offset += 1; + uint8_t imagePartition = *(commandData + offset); + offset += 1; + uint32_t imageSize = *(commandData + offset) << 24 | *(commandData + offset + 1) << 16 + | *(commandData + offset + 2) << 8 | *(commandData + offset + 3); + offset += 4; + uint32_t imageCrc = *(commandData + offset) << 24 | *(commandData + offset + 1) << 16 + | *(commandData + offset + 2) << 8 | *(commandData + offset + 3); + offset += 4; + uint32_t numberOfPackets = *(commandData + offset) << 24 | *(commandData + offset + 1) << 16 + | *(commandData + offset + 2) << 8 | *(commandData + offset + 3); + + PLOC_SPV::UpdateAvailable packet(imageSelect, imagePartition, imageSize, imageCrc, + numberOfPackets); + memcpy(commandBuffer, packet.getWholeData(), packet.getFullSize()); + rawPacket = commandBuffer; + rawPacketLen = packet.getFullSize(); + nextReplyId = PLOC_SPV::ACK_REPORT; +} + void PlocSupervisorHandler::disableAllReplies() { DeviceReplyMap::iterator iter; diff --git a/mission/devices/PlocSupervisorHandler.h b/mission/devices/PlocSupervisorHandler.h index e91fb1e4..d4ad811c 100644 --- a/mission/devices/PlocSupervisorHandler.h +++ b/mission/devices/PlocSupervisorHandler.h @@ -100,6 +100,7 @@ private: DeviceCommandId_t nextReplyId = PLOC_SPV::NONE; PLOC_SPV::HkSet hkset; + PLOC_SPV::BootStatusReport bootStatusReport; UartComIF* uartComIf = nullptr; @@ -141,6 +142,12 @@ private: */ ReturnValue_t handleHkReport(const uint8_t* data); + /** + * @brief This function calls the function to check the CRC of the received boot status report + * and fills the associated dataset with the boot status information. + */ + ReturnValue_t handleBootStatusReport(const uint8_t* data); + /** * @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 @@ -187,6 +194,12 @@ private: void prepareRestartTriesCmd(const uint8_t * commandData); + /** + * @brief This function fills the command buffer with the packet to notify the supervisor + * about the availability of an update for the MPSoC + */ + void prepareUpdateAvailableCmd(const uint8_t * commandData); + /** * @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 diff --git a/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h b/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h index dd4f875b..87153978 100644 --- a/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h +++ b/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h @@ -20,15 +20,20 @@ static const DeviceCommandId_t SET_MAX_RESTART_TRIES = 7; static const DeviceCommandId_t RESET_MPSOC = 8; static const DeviceCommandId_t SET_TIME_REF = 9; 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; /** 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 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; /** * SpacePacket apids of telemetry packets @@ -100,12 +105,22 @@ enum PoolIds TEMP_SUP, UPTIME, CPULOAD, - AVAILABLEHEAP + AVAILABLEHEAP, + BOOT_SIGNAL, + RESET_COUNTER, + BOOT_AFTER_MS, + BOOT_TIMEOUT_MS, + ACTIVE_NVM, + BP0_STATE, + BP1_STATE, + BP2_STATE }; static const uint8_t HK_SET_ENTRIES = 13; +static const uint8_t BOOT_REPORT_SET_ENTRIES = 8; static const uint32_t HK_SET_ID = HK_REPORT; +static const uint32_t BOOT_REPORT_SET_ID = APID_BOOT_STATUS_REPORT; /** * @brief With this class a space packet can be created which does not contain any data. @@ -327,6 +342,99 @@ 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. + */ +class UpdateAvailable: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param imageSelect + * @param imagePartition + * @param imageSize + * @param imageCrc + * @param numberOfPackets + */ + UpdateAvailable(uint8_t imageSelect, uint8_t imagePartition, uint32_t imageSize, + uint32_t imageCrc, uint32_t numberOfPackets) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_UPDATE_AVAILABLE, + DEFAULT_SEQUENCE_COUNT), imageSelect(imageSelect), imagePartition( + imagePartition), imageSize(imageSize), imageCrc(imageCrc), numberOfPackets( + numberOfPackets) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 16; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t imageSelect = 0; + uint8_t imagePartition = 0; + uint32_t imageSize = 0; + uint32_t imageCrc = 0; + uint32_t numberOfPackets = 0; + + void initPacket() { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&imageSelect, &data_field_ptr, &serializedSize, + sizeof(imageSelect), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&imagePartition, &data_field_ptr, &serializedSize, + sizeof(imagePartition), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&imageSize, &data_field_ptr, &serializedSize, + sizeof(imageSize), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&imageCrc, &data_field_ptr, &serializedSize, + sizeof(imageCrc), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&numberOfPackets, &data_field_ptr, &serializedSize, + sizeof(numberOfPackets), SerializeIF::Endianness::BIG); + 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); + } +}; + /** * @brief With this class the space packet can be generated to disable to periodic transmission * of housekeeping data. Normally, this will be disabled by default. However, adding this @@ -363,7 +471,7 @@ private: }; /** - * @brief This dataset to store the housekeeping data of the supervisor. + * @brief This dataset stores the housekeeping data of the supervisor. */ class HkSet: public StaticLocalDataSet { public: @@ -376,21 +484,21 @@ public: StaticLocalDataSet(sid_t(objectId, HK_SET_ID)) { } - lp_var_t numTms = lp_var_t(sid.objectId, PoolIds::NUM_TMS, this); lp_var_t tempPs = lp_var_t(sid.objectId, PoolIds::TEMP_PS, this); lp_var_t tempPl = lp_var_t(sid.objectId, PoolIds::TEMP_PS, this); + lp_var_t tempSup = lp_var_t(sid.objectId, PoolIds::TEMP_SUP, this); + lp_var_t uptime = lp_var_t(sid.objectId, PoolIds::UPTIME, this); + lp_var_t cpuLoad = lp_var_t(sid.objectId, PoolIds::CPULOAD, this); + lp_var_t availableHeap = lp_var_t(sid.objectId, PoolIds::AVAILABLEHEAP, + this); + lp_var_t numTcs = lp_var_t(sid.objectId, PoolIds::NUM_TCS, this); + lp_var_t numTms = lp_var_t(sid.objectId, PoolIds::NUM_TMS, this); lp_var_t socState = lp_var_t(sid.objectId, PoolIds::SOC_STATE, this); lp_var_t nvm0_1_state = lp_var_t(sid.objectId, PoolIds::NVM0_1_STATE, this); lp_var_t nvm3_state = lp_var_t(sid.objectId, PoolIds::NVM3_STATE, this); lp_var_t missionIoState = lp_var_t(sid.objectId, PoolIds::MISSION_IO_STATE, this); lp_var_t fmcState = lp_var_t(sid.objectId, PoolIds::FMC_STATE, this); - lp_var_t numTcs = lp_var_t(sid.objectId, PoolIds::NUM_TCS, this); - lp_var_t tempSup = lp_var_t(sid.objectId, PoolIds::TEMP_SUP, this); - lp_var_t uptime = lp_var_t(sid.objectId, PoolIds::UPTIME, this); - lp_var_t cpuLoad = lp_var_t(sid.objectId, PoolIds::CPULOAD, this); - lp_var_t availableHeap = lp_var_t(sid.objectId, PoolIds::AVAILABLEHEAP, - this); }; } diff --git a/tmtc b/tmtc index 2e942ec2..6352a6f2 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 2e942ec21e47485b9ab6416a0341b9ab8ec30543 +Subproject commit 6352a6f272b3138257831fcd1f5d9ffcd4902681