#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_PLOCSVPDEFINITIONS_H_ #define MISSION_DEVICES_DEVICEDEFINITIONS_PLOCSVPDEFINITIONS_H_ #include #include #include #include namespace PLOC_SPV { /** Command IDs */ static const DeviceCommandId_t NONE = 0; static const DeviceCommandId_t GET_HK_REPORT = 1; static const DeviceCommandId_t RESTART_MPSOC = 2; static const DeviceCommandId_t START_MPSOC = 3; static const DeviceCommandId_t SHUTDOWN_MPSOC = 4; static const DeviceCommandId_t SEL_MPSOC_BOOT_IMAGE = 5; static const DeviceCommandId_t SET_BOOT_TIMEOUT = 6; 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 */ static const uint16_t APID_ACK_SUCCESS = 0x200; static const uint16_t APID_ACK_FAILURE = 0x201; static const uint16_t APID_EXE_SUCCESS = 0x202; static const uint16_t APID_EXE_FAILURE = 0x203; static const uint16_t APID_HK_REPORT = 0x204; static const uint16_t APID_BOOT_STATUS_REPORT = 0x205; static const uint16_t APID_UPDATE_STATUS_REPORT = 0x206; static const uint16_t APID_WDG_STATUS_REPORT = 0x207; static const uint16_t APID_LATCHUP_STATUS_REPORT = 0x208; static const uint16_t APID_SOC_SYSMON = 0x209; static const uint16_t APID_MRAM = 0x20A; static const uint16_t APID_SRAM = 0x20B; static const uint16_t APID_NOR_DATA = 0x20C; static const uint16_t APID_DATA_LOGGER_DATA = 0x20D; /** * APIDs of telecommand packets */ static const uint16_t APID_RESTART_MPSOC = 0xA0; static const uint16_t APID_START_MPSOC = 0xA1; static const uint16_t APID_SHUTWOWN_MPSOC = 0xA2; static const uint16_t APID_SEL_MPSOC_BOOT_IMAGE = 0xA3; static const uint16_t APID_SET_BOOT_TIMEOUT = 0xA4; static const uint16_t APID_SET_MAX_RESTART_TRIES = 0xA5; static const uint16_t APID_RESET_MPSOC = 0xA6; static const uint16_t APID_GET_BOOT_STATUS_RPT = 0xA8; static const uint16_t APID_UPDATE_AVAILABLE = 0xB0; static const uint16_t APID_UPDATE_IMAGE_DATA = 0xB1; static const uint16_t APID_UPDATE_VERIFY = 0xB2; static const uint16_t APID_WTD_ENABLE = 0xC0; static const uint16_t APID_WTD_CONFIG_TIMEOUT = 0xC1; static const uint16_t APID_SET_TIME_REF = 0xC2; static const uint16_t APID_DISABLE_HK = 0xC3; static const uint16_t APID_GET_HK_REPORT = 0xC6; /** Offset from first byte in Space packet to first byte of data field */ static const uint8_t DATA_FIELD_OFFSET = 6; /** * Space packet length for fixed size packets. This is the size of the whole packet data * field. For the length field in the space packet this size will be substracted by one. */ static const uint16_t LENGTH_EMPTY_TC = 2; // Only CRC will be transported with the data field /** This is the maximum length of a space packet as defined by the TAS ICD */ static const size_t MAX_REPLY_SIZE = 1024; static const size_t MAX_COMMAND_SIZE = 1024; enum SequenceFlags { CONTINUED_PKT = 0b00, FIRST_PKT = 0b01, LAST_PKT = 0b10, STANDALONE_PKT = 0b11 }; enum PoolIds : lp_id_t { NUM_TMS, TEMP_PS, TEMP_PL, SOC_STATE, NVM0_1_STATE, NVM3_STATE, MISSION_IO_STATE, FMC_STATE, NUM_TCS, TEMP_SUP, UPTIME, CPULOAD, 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. */ class EmptyPacket: public SpacePacket { public: /** * @brief Constructor * * @param apid The APID to set in the space packet. * * @note Sequence count of empty packet is always 1. */ EmptyPacket(uint16_t apid) : SpacePacket(LENGTH_EMPTY_TC - 1, true, apid, 1) { calcCrc(); } private: /** * @brief CRC calculation which involves only the header in an empty packet */ void calcCrc() { /* Calculate crc */ uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, sizeof(CCSDSPrimaryHeader)); /* Add crc to packet data field of space packet */ size_t serializedSize = 0; uint8_t* crcPos = this->localData.fields.buffer; SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), SerializeIF::Endianness::BIG); } }; /** * @brief This class can be used to generate the space packet selecting the boot image of * of the MPSoC. */ class MPSoCBootSelect: public SpacePacket { public: /** * @brief Constructor * * @param mem The memory to boot from: NVM0 (0), NVM1 (1) * @param bp0 Partition pin 0 * @param bp1 Partition pin 1 * @param bp2 Partition pin 2 */ MPSoCBootSelect(uint8_t mem, uint8_t bp0, uint8_t bp1, uint8_t bp2) : SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SEL_MPSOC_BOOT_IMAGE, DEFAULT_SEQUENCE_COUNT), mem(mem), bp0(bp0), bp1(bp1), bp2(bp2) { initPacket(); } private: static const uint16_t DATA_FIELD_LENGTH = 6; static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; static const uint8_t MEM_OFFSET = 0; static const uint8_t BP0_OFFSET = 1; static const uint8_t BP1_OFFSET = 2; static const uint8_t BP2_OFFSET = 3; static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; uint8_t mem = 0; uint8_t bp0 = 0; uint8_t bp1 = 0; uint8_t bp2 = 0; void initPacket() { uint8_t* data_field_start = this->localData.fields.buffer; std::memcpy(data_field_start + MEM_OFFSET, &mem, sizeof(mem)); std::memcpy(data_field_start + BP0_OFFSET, &bp0, sizeof(bp0)); std::memcpy(data_field_start + BP1_OFFSET, &bp1, sizeof(bp1)); std::memcpy(data_field_start + BP2_OFFSET, &bp2, sizeof(bp2)); /* Calculate crc */ uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); /* Add crc to packet data field of space packet */ size_t serializedSize = 0; uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), SerializeIF::Endianness::BIG); } }; /** * @brief This class generates the space packet to update the time of the PLOC supervisor. */ class SetTimeRef: public SpacePacket { public: SetTimeRef(Clock::TimeOfDay_t* time) : SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SET_TIME_REF, DEFAULT_SEQUENCE_COUNT) { initPacket(time); } private: static const uint16_t DATA_FIELD_LENGTH = 34; static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; void initPacket(Clock::TimeOfDay_t* time) { size_t serializedSize = 0; uint8_t* data_field_ptr = this->localData.fields.buffer; SerializeAdapter::serialize(&time->second, &data_field_ptr, &serializedSize, sizeof(time->second), SerializeIF::Endianness::BIG); serializedSize = 0; SerializeAdapter::serialize(&time->minute, &data_field_ptr, &serializedSize, sizeof(time->minute), SerializeIF::Endianness::BIG); serializedSize = 0; SerializeAdapter::serialize(&time->hour, &data_field_ptr, &serializedSize, sizeof(time->hour), SerializeIF::Endianness::BIG); serializedSize = 0; SerializeAdapter::serialize(&time->day, &data_field_ptr, &serializedSize, sizeof(time->day), SerializeIF::Endianness::BIG); serializedSize = 0; SerializeAdapter::serialize(&time->month, &data_field_ptr, &serializedSize, sizeof(time->month), SerializeIF::Endianness::BIG); serializedSize = 0; SerializeAdapter::serialize(&time->year, &data_field_ptr, &serializedSize, sizeof(time->year), SerializeIF::Endianness::BIG); serializedSize = 0; uint32_t milliseconds = time->usecond / 1000; SerializeAdapter::serialize(&milliseconds, &data_field_ptr, &serializedSize, sizeof(milliseconds), SerializeIF::Endianness::BIG); serializedSize = 0; uint32_t isSet = 0xFFFFFFFF; SerializeAdapter::serialize(&isSet, &data_field_ptr, &serializedSize, sizeof(isSet), SerializeIF::Endianness::BIG); serializedSize = 0; /* Calculate crc */ uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); SerializeAdapter::serialize(&crc, &data_field_ptr, &serializedSize, sizeof(crc), SerializeIF::Endianness::BIG); } }; /** * @brief This class can be used to generate the set boot timout command. */ class SetBootTimeout: public SpacePacket { public: /** * @brief Constructor * * @param timeout The boot timeout in milliseconds. */ SetBootTimeout(uint32_t timeout) : SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SET_BOOT_TIMEOUT, 1), timeout(timeout) { initPacket(); } private: uint32_t timeout = 0; /** boot timeout value (uint32_t) and crc (uint16_t) */ static const uint16_t DATA_FIELD_LENGTH = 6; void initPacket() { size_t serializedSize = 0; uint8_t* data_field_ptr = this->localData.fields.buffer; SerializeAdapter::serialize(&timeout, &data_field_ptr, &serializedSize, sizeof(timeout), SerializeIF::Endianness::BIG); /* Calculate crc */ uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); /* Add crc to packet data field of space packet */ serializedSize = 0; SerializeAdapter::serialize(&crc, &data_field_ptr, &serializedSize, sizeof(crc), SerializeIF::Endianness::BIG); } }; /** * @brief This class can be used to generate the space packet to set the maximum boot tries. */ class SetRestartTries: public SpacePacket { public: /** * @brief Constructor * * @param restartTries Maximum restart tries to set. */ SetRestartTries(uint8_t restartTries) : SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SET_MAX_RESTART_TRIES, 1), restartTries( restartTries) { initPacket(); } private: uint8_t restartTries = 0; /** Restart tries value (uint8_t) and crc (uint16_t) */ static const uint16_t DATA_FIELD_LENGTH = 3; void initPacket() { uint8_t* data_field_ptr = this->localData.fields.buffer; *data_field_ptr = restartTries; uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); size_t serializedSize = 0; uint8_t* crcPtr = data_field_ptr + 1; SerializeAdapter::serialize(&crc, &crcPtr, &serializedSize, sizeof(crc), SerializeIF::Endianness::BIG); } }; /** * @brief This dataset stores the boot status report of the supervisor. */ class BootStatusReport: public StaticLocalDataSet { public: BootStatusReport(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, BOOT_REPORT_SET_ID) { } BootStatusReport(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, BOOT_REPORT_SET_ID)) { } /** Information about boot status of MPSoC */ lp_var_t bootSignal = lp_var_t(sid.objectId, PoolIds::BOOT_SIGNAL, this); lp_var_t resetCounter = lp_var_t(sid.objectId, PoolIds::RESET_COUNTER, this); /** Time the MPSoC needs for last boot */ lp_var_t bootAfterMs = lp_var_t(sid.objectId, PoolIds::BOOT_AFTER_MS, this); /** The currently set boot timeout */ lp_var_t bootTimeoutMs = lp_var_t(sid.objectId, PoolIds::BOOT_TIMEOUT_MS, this); lp_var_t activeNvm = lp_var_t(sid.objectId, PoolIds::ACTIVE_NVM, this); /** States of the boot partition pins */ lp_var_t bp0State = lp_var_t(sid.objectId, PoolIds::BP0_STATE, this); lp_var_t bp1State = lp_var_t(sid.objectId, PoolIds::BP1_STATE, this); lp_var_t bp2State = lp_var_t(sid.objectId, PoolIds::BP2_STATE, this); }; /** * @brief This 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 * command can be useful for debugging. */ class DisablePeriodicHkTransmission: public SpacePacket { public: /** * @brief Constructor */ DisablePeriodicHkTransmission() : SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_DISABLE_HK, 1) { initPacket(); } private: uint8_t disableHk = 0; /** Restart tries value (uint8_t) and crc (uint16_t) */ static const uint16_t DATA_FIELD_LENGTH = 3; void initPacket() { uint8_t* data_field_ptr = this->localData.fields.buffer; *data_field_ptr = disableHk; uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); size_t serializedSize = 0; uint8_t* crcPtr = data_field_ptr + 1; SerializeAdapter::serialize(&crc, &crcPtr, &serializedSize, sizeof(crc), SerializeIF::Endianness::BIG); } }; /** * @brief This dataset stores the housekeeping data of the supervisor. */ class HkSet: public StaticLocalDataSet { public: HkSet(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, HK_SET_ID) { } HkSet(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, HK_SET_ID)) { } 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); }; } #endif /* MISSION_DEVICES_DEVICEDEFINITIONS_PLOCSVPDEFINITIONS_H_ */