#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_PLOCSVPDEFINITIONS_H_ #define MISSION_DEVICES_DEVICEDEFINITIONS_PLOCSVPDEFINITIONS_H_ #include #include #include #include #include #include #include #include #include "mission/devices/devicedefinitions/SpBase.h" namespace supv { namespace result { static const uint8_t INTERFACE_ID = CLASS_ID::SUPV_RETURN_VALUES_IF; //! [EXPORT] : [COMMENT] Space Packet received from PLOC supervisor has invalid CRC static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA0); static constexpr ReturnValue_t INVALID_SERVICE_ID = MAKE_RETURN_CODE(0xA1); //! [EXPORT] : [COMMENT] Received ACK failure reply from PLOC supervisor static const ReturnValue_t RECEIVED_ACK_FAILURE = MAKE_RETURN_CODE(0xA2); //! [EXPORT] : [COMMENT] Received execution failure reply from PLOC supervisor static const ReturnValue_t RECEIVED_EXE_FAILURE = MAKE_RETURN_CODE(0xA3); //! [EXPORT] : [COMMENT] Received space packet with invalid APID from PLOC supervisor static const ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(0xA4); //! [EXPORT] : [COMMENT] Failed to read current system time static const ReturnValue_t GET_TIME_FAILURE = MAKE_RETURN_CODE(0xA5); //! [EXPORT] : [COMMENT] Received command with invalid watchdog parameter. Valid watchdogs are 0 //! for PS, 1 for PL and 2 for INT static const ReturnValue_t INVALID_WATCHDOG = MAKE_RETURN_CODE(0xA6); //! [EXPORT] : [COMMENT] Received watchdog timeout config command with invalid timeout. Valid //! timeouts must be in the range between 1000 and 360000 ms. static const ReturnValue_t INVALID_WATCHDOG_TIMEOUT = MAKE_RETURN_CODE(0xA7); //! [EXPORT] : [COMMENT] Received latchup config command with invalid latchup ID static const ReturnValue_t INVALID_LATCHUP_ID = MAKE_RETURN_CODE(0xA8); //! [EXPORT] : [COMMENT] Received set adc sweep period command with invalid sweep period. Must be //! larger than 21. static const ReturnValue_t SWEEP_PERIOD_TOO_SMALL = MAKE_RETURN_CODE(0xA9); //! [EXPORT] : [COMMENT] Receive auto EM test command with invalid test param. Valid params are 1 //! and 2. static const ReturnValue_t INVALID_TEST_PARAM = MAKE_RETURN_CODE(0xAA); //! [EXPORT] : [COMMENT] Returned when scanning for MRAM dump packets failed. static const ReturnValue_t MRAM_PACKET_PARSING_FAILURE = MAKE_RETURN_CODE(0xAB); //! [EXPORT] : [COMMENT] Returned when the start and stop addresses of the MRAM dump or MRAM wipe //! commands are invalid (e.g. start address bigger than stop address) static const ReturnValue_t INVALID_MRAM_ADDRESSES = MAKE_RETURN_CODE(0xAC); //! [EXPORT] : [COMMENT] Expect reception of an MRAM dump packet but received space packet with //! other apid. static const ReturnValue_t NO_MRAM_PACKET = MAKE_RETURN_CODE(0xAD); //! [EXPORT] : [COMMENT] Path to PLOC directory on SD card does not exist static const ReturnValue_t PATH_DOES_NOT_EXIST = MAKE_RETURN_CODE(0xAE); //! [EXPORT] : [COMMENT] MRAM dump file does not exists. The file should actually already have //! been created with the reception of the first dump packet. static const ReturnValue_t MRAM_FILE_NOT_EXISTS = MAKE_RETURN_CODE(0xAF); static constexpr ReturnValue_t INVALID_REPLY_LENGTH = MAKE_RETURN_CODE(0xB0); //! [EXPORT] : [COMMENT] Received action command has invalid length static const ReturnValue_t INVALID_LENGTH = MAKE_RETURN_CODE(0xB1); //! [EXPORT] : [COMMENT] Filename too long static const ReturnValue_t FILENAME_TOO_LONG = MAKE_RETURN_CODE(0xB2); //! [EXPORT] : [COMMENT] Received update status report with invalid packet length field static const ReturnValue_t UPDATE_STATUS_REPORT_INVALID_LENGTH = MAKE_RETURN_CODE(0xB3); //! [EXPORT] : [COMMENT] Update status report does not contain expected CRC. There might be a bit //! flip in the update memory region. static const ReturnValue_t UPDATE_CRC_FAILURE = MAKE_RETURN_CODE(0xB4); //! [EXPORT] : [COMMENT] Supervisor helper task ist currently executing a command (wait until //! helper tas has finished or interrupt by sending the terminate command) static const ReturnValue_t SUPV_HELPER_EXECUTING = MAKE_RETURN_CODE(0xB5); static constexpr ReturnValue_t BUF_TOO_SMALL = MAKE_RETURN_CODE(0xC0); static constexpr ReturnValue_t NO_REPLY_TIMEOUT = MAKE_RETURN_CODE(0xC1); }; // namespace result static constexpr uint16_t DEFAULT_SEQ_COUNT = 0; /** Command IDs */ static const DeviceCommandId_t NONE = 0; static const DeviceCommandId_t GET_HK_REPORT = 1; 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; static const DeviceCommandId_t ENABLE_LATCHUP_ALERT = 15; static const DeviceCommandId_t DISABLE_LATCHUP_ALERT = 16; static const DeviceCommandId_t SET_ALERT_LIMIT = 18; 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 RUN_AUTO_EM_TESTS = 28; static const DeviceCommandId_t WIPE_MRAM = 29; static const DeviceCommandId_t FIRST_MRAM_DUMP = 30; 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 LOGGING_REQUEST_COUNTERS = 38; static constexpr DeviceCommandId_t FACTORY_RESET = 39; static const DeviceCommandId_t CONSECUTIVE_MRAM_DUMP = 43; static const DeviceCommandId_t START_MPSOC_QUIET = 45; static const DeviceCommandId_t SET_SHUTDOWN_TIMEOUT = 46; static const DeviceCommandId_t FACTORY_FLASH = 47; static const DeviceCommandId_t PERFORM_UPDATE = 48; static const DeviceCommandId_t TERMINATE_SUPV_HELPER = 49; static const DeviceCommandId_t ENABLE_AUTO_TM = 50; static const DeviceCommandId_t DISABLE_AUTO_TM = 51; static const DeviceCommandId_t LOGGING_REQUEST_EVENT_BUFFERS = 54; static const DeviceCommandId_t LOGGING_CLEAR_COUNTERS = 55; static const DeviceCommandId_t LOGGING_SET_TOPIC = 56; static const DeviceCommandId_t REQUEST_ADC_REPORT = 57; static const DeviceCommandId_t RESET_PL = 58; static const DeviceCommandId_t ENABLE_NVMS = 59; static const DeviceCommandId_t CONTINUE_UPDATE = 60; static const DeviceCommandId_t MEMORY_CHECK_WITH_FILE = 61; /** Reply IDs */ enum ReplyId : DeviceCommandId_t { ACK_REPORT = 100, EXE_REPORT = 101, HK_REPORT = 102, BOOT_STATUS_REPORT = 103, LATCHUP_REPORT = 104, LOGGING_REPORT = 105, ADC_REPORT = 106, UPDATE_STATUS_REPORT = 107, }; // Size of complete space packet (6 byte header + size of data + 2 byte CRC) static const uint16_t SIZE_ACK_REPORT = 14; static const uint16_t SIZE_EXE_REPORT = 14; static const uint16_t SIZE_HK_REPORT = 52; static const uint16_t SIZE_BOOT_STATUS_REPORT = 24; static const uint16_t SIZE_LATCHUP_STATUS_REPORT = 31; static const uint16_t SIZE_LOGGING_REPORT = 73; static const uint16_t SIZE_ADC_REPORT = 72; // 2 bits APID SRC, 00 for OBC, 2 bits APID DEST, 01 for SUPV, 7 bits CMD ID -> Mask 0x080 static constexpr uint16_t APID_TC_SUPV_MASK = 0x080; enum Apid { TMTC_MAN = 0x00, HK = 0x01, BOOT_MAN = 0x02, LATCHUP_MON = 0x03, ADC_MON = 0x04, MEM_MAN = 0x05, DATA_LOGGER = 0x06, WDOG_MAN = 0x07 }; namespace tc { enum class HkId : uint8_t { ENABLE = 0x01, SET_PERIOD = 0x02, GET_REPORT = 0x03, GET_HARDFAULTS_REPORT = 0x04, }; enum class TmtcId : uint8_t { TIME_REF = 0x03, GET_SUPV_VERSION = 0x05, RUN_AUTO_EM_TEST = 0x08, SET_GPIO = 0x0E, READ_GPIO = 0x0F, GET_MPSOC_POWER_INFO = 0x10 }; enum class BootManId : uint8_t { START_MPSOC = 0x01, SHUTDOWN_MPSOC = 0x02, SELECT_IMAGE = 0x03, SET_BOOT_TIMEOUT = 0x04, SET_MAX_REBOOT_TRIES = 0x05, RESET_MPSOC = 0x06, RESET_PL = 0x07, GET_BOOT_STATUS_REPORT = 0x08, PREPARE_UPDATE = 0x09, SHUTDOWN_TIMEOUT = 0x0B, FACTORY_FLASH = 0x0C }; enum class LatchupMonId : uint8_t { ENABLE = 0x01, DISABLE = 0x02, SET_ALERT_LIMIT = 0x04, GET_STATUS_REPORT = 0x06 }; // Right now, none of the commands seem to be implemented, but still // keep the enum here in case some are added enum class AdcMonId : uint8_t { SET_SWEEP_PERIOD = 0x01, SET_ENABLED_CHANNELS = 0x02, SET_WINDOW_STRIDE = 0x03, SET_ADC_THRESHOLD = 0x04, COPY_ADC_DATA_TO_MRAM = 0x05 }; enum class MemManId : uint8_t { ERASE = 0x01, WRITE = 0x02, CHECK = 0x03 }; enum class DataLoggerServiceId : uint8_t { WIPE_MRAM = 0x05, DUMP_MRAM = 0x06, FACTORY_RESET = 0x07 }; // Right now, none of the commands seem to be implemented, but still // keep the enum here in case some are added enum class WdogManServiceId : uint8_t {}; } // namespace tc namespace tm { enum class TmtcId : uint8_t { ACK = 0x01, NAK = 0x02, EXEC_ACK = 0x03, EXEC_NAK = 0x04 }; enum class HkId : uint8_t { REPORT = 0x01, HARDFAULTS = 0x02 }; enum class BootManId : uint8_t { BOOT_STATUS_REPORT = 0x01 }; enum class MemManId : uint8_t { UPDATE_STATUS_REPORT = 0x01 }; enum class LatchupMonId : uint8_t { LATCHUP_STATUS_REPORT = 0x01 }; } // namespace tm static const uint16_t APID_MASK = 0x3FF; static const uint16_t SEQUENCE_COUNT_MASK = 0xFFF; static const uint8_t HK_SET_ENTRIES = 13; static const uint8_t BOOT_REPORT_SET_ENTRIES = 10; static const uint8_t LATCHUP_RPT_SET_ENTRIES = 16; static const uint8_t LOGGING_RPT_SET_ENTRIES = 16; static const uint8_t ADC_RPT_SET_ENTRIES = 32; static const uint32_t HK_SET_ID = HK_REPORT; static const uint32_t BOOT_REPORT_SET_ID = BOOT_STATUS_REPORT; static const uint32_t LATCHUP_RPT_ID = LATCHUP_REPORT; static const uint32_t LOGGING_RPT_ID = LOGGING_REPORT; static const uint32_t ADC_REPORT_SET_ID = ADC_REPORT; namespace timeout { // Erase memory can require up to 60 seconds for execution static const uint32_t ERASE_MEMORY = 60000; static const uint32_t UPDATE_STATUS_REPORT = 70000; static const uint32_t CRC_EXECUTION_TIMEOUT = 60000; } // namespace timeout static constexpr size_t TIMESTAMP_LEN = 7; static constexpr size_t SECONDARY_HEADER_LEN = TIMESTAMP_LEN + 1; static constexpr size_t CRC_LEN = 2; /** This is the maximum length of a space packet as defined by the TAS ICD */ static const size_t MAX_COMMAND_SIZE = 1024; static const size_t MAX_DATA_CAPACITY = 1016; /** This is the maximum size of a space packet for the supervisor */ static const size_t MAX_PACKET_SIZE = 1024; static constexpr size_t MIN_PAYLOAD_LEN = SECONDARY_HEADER_LEN + CRC_LEN; static constexpr size_t MIN_TMTC_LEN = ccsds::HEADER_LEN + MIN_PAYLOAD_LEN; static constexpr size_t PAYLOAD_OFFSET = ccsds::HEADER_LEN + SECONDARY_HEADER_LEN; enum class FactoryResetSelect : uint8_t { EVENT_BUF = 0x00, ADC_BUF = 0x01, SYS_CFG = 0x02, DEBUG_CFG = 0x03, BOOT_MAN_CFG = 0x04, DATA_LOGGER_CFG = 0x05, DATA_LOGGER_OP_DATA = 0x06, LATCHUP_MON_CFG = 0x07, ADC_MON_CFG = 0x08, WDOG_MAN_CFG = 0x09, HK_CFG = 0x0A, MEM_MAN_CFG = 0xB9 }; struct UpdateParams { std::string file; uint8_t memId; uint32_t startAddr; uint32_t bytesWritten; uint16_t seqCount; bool deleteMemory; }; enum PoolIds : lp_id_t { NUM_TMS, TEMP_PS, TEMP_PL, HK_SOC_STATE, NVM0_1_STATE, NVM3_STATE, MISSION_IO_STATE, FMC_STATE, NUM_TCS, TEMP_SUP, UPTIME, CPULOAD, AVAILABLEHEAP, BR_SOC_STATE, POWER_CYCLES, BOOT_AFTER_MS, BOOT_TIMEOUT_MS, ACTIVE_NVM, BP0_STATE, BP1_STATE, BP2_STATE, BOOT_STATE, BOOT_CYCLES, 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_IS_SET, LATCHUP_HAPPENED_CNT_0, LATCHUP_HAPPENED_CNT_1, LATCHUP_HAPPENED_CNT_2, LATCHUP_HAPPENED_CNT_3, LATCHUP_HAPPENED_CNT_4, LATCHUP_HAPPENED_CNT_5, LATCHUP_HAPPENED_CNT_6, ADC_DEVIATION_TRIGGERS_CNT, TC_RECEIVED_CNT, TM_AVAILABLE_CNT, SUPERVISOR_BOOTS, MPSOC_BOOTS, MPSOC_BOOT_FAILED_ATTEMPTS, MPSOC_POWER_UP, MPSOC_UPDATES, LAST_RECVD_TC, ADC_RAW_0, ADC_RAW_1, ADC_RAW_2, ADC_RAW_3, ADC_RAW_4, ADC_RAW_5, ADC_RAW_6, ADC_RAW_7, ADC_RAW_8, ADC_RAW_9, ADC_RAW_10, ADC_RAW_11, ADC_RAW_12, ADC_RAW_13, ADC_RAW_14, ADC_RAW_15, ADC_ENG_0, ADC_ENG_1, ADC_ENG_2, ADC_ENG_3, ADC_ENG_4, ADC_ENG_5, ADC_ENG_6, ADC_ENG_7, ADC_ENG_8, ADC_ENG_9, ADC_ENG_10, ADC_ENG_11, ADC_ENG_12, ADC_ENG_13, ADC_ENG_14, ADC_ENG_15 }; struct TcParams : public ploc::SpTcParams { public: TcParams(SpacePacketCreator& creator) : ploc::SpTcParams(creator) {} TcParams(SpacePacketCreator& creator, uint8_t* buf, size_t maxSize) : ploc::SpTcParams(creator, buf, maxSize) {} void setLenFromPayloadLen(size_t payloadLen) { setFullPayloadLen(ccsds::HEADER_LEN + SECONDARY_HEADER_LEN + payloadLen + CRC_LEN); } }; class TcBase : public ploc::SpTcBase { public: TcBase(TcParams params) : TcBase(params, 0x00, 0x00, MIN_PAYLOAD_LEN) {} TcBase(TcParams params, uint16_t apid) : TcBase(params, apid, 0x00, MIN_PAYLOAD_LEN) {} TcBase(TcParams params, uint16_t apid, uint8_t service, size_t payloadLen) : TcBase(params, apid, service, payloadLen, DEFAULT_SEQ_COUNT) {} TcBase(TcParams params, uint16_t apid, uint8_t serviceId, size_t payloadLen, uint16_t seqCount) : ploc::SpTcBase(params, apid, fullSpDataLenFromPayloadLen(payloadLen), seqCount) { setup(serviceId); } void setServiceId(uint8_t id) { if (spParams.maxSize < MIN_PAYLOAD_LEN) { return; } payloadStart[supv::PAYLOAD_OFFSET] = id; } uint8_t getServiceId() const { return payloadStart[supv::PAYLOAD_OFFSET]; } static size_t fullSpDataLenFromPayloadLen(size_t payloadLen) { return SECONDARY_HEADER_LEN + payloadLen + CRC_LEN; } void setLenFromPayloadLen(size_t payloadLen) { spParams.setFullPayloadLen(fullSpDataLenFromPayloadLen(payloadLen)); updateLenFromParams(); } private: ReturnValue_t setup(uint8_t serviceId) { if (spParams.maxSize < MIN_PAYLOAD_LEN) { sif::error << "SupvTcBase::SupvTcBase: Passed buffer is too small" << std::endl; return returnvalue::FAILED; } std::memset(spParams.buf + ccsds::HEADER_LEN, 0, TIMESTAMP_LEN); payloadStart = spParams.buf + ccsds::HEADER_LEN + SECONDARY_HEADER_LEN; payloadStart[supv::PAYLOAD_OFFSET] = serviceId; return returnvalue::OK; } }; class TmBase : public ploc::SpTmReader { public: TmBase() = default; TmBase(const uint8_t* data, size_t maxSize) : ploc::SpTmReader(data, maxSize) { if (maxSize < MIN_TMTC_LEN) { sif::error << "SupvTcBase::SupvTcBase: Passed buffer is too small" << std::endl; } } bool verifyCrc() { if (checkCrc() == returnvalue::OK) { crcOk = true; } return crcOk; } bool crcIsOk() const { return crcOk; } uint8_t getServiceId() const { return getPacketData()[TIMESTAMP_LEN]; } const uint8_t* getPayloadStart() const { return getPacketData() + SECONDARY_HEADER_LEN; } size_t getPayloadLen() const { if (getFullPacketLen() > SECONDARY_HEADER_LEN + ccsds::HEADER_LEN) { return getFullPacketLen() - SECONDARY_HEADER_LEN - ccsds::HEADER_LEN; } return 0; } private: bool crcOk = false; }; class NoPayloadPacket : public TcBase { public: NoPayloadPacket(TcParams params, uint16_t apid, uint8_t serviceId) : NoPayloadPacket(params, apid, serviceId, 0) {} NoPayloadPacket(TcParams params, uint16_t apid, uint8_t serviceId, uint16_t seqId) : TcBase(params, apid, serviceId, MIN_PAYLOAD_LEN, seqId) {} ReturnValue_t buildPacket() { ReturnValue_t result = checkSizeAndSerializeHeader(); if (result != returnvalue::OK) { return result; } return calcAndSetCrc(); } private: }; /** * @brief This class can be used to generate the space packet selecting the boot image of * of the MPSoC. */ class MPSoCBootSelect : public TcBase { public: static const uint8_t NVM0 = 0; static const uint8_t NVM1 = 1; /** * @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 * * @note Selection of partitions is currently not supported. */ MPSoCBootSelect(TcParams params) : TcBase(params, Apid::BOOT_MAN, static_cast(tc::BootManId::SELECT_IMAGE), 4) {} ReturnValue_t buildPacket(uint8_t mem = 0, uint8_t bp0 = 0, uint8_t bp1 = 0, uint8_t bp2 = 0) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(mem, bp0, bp1, bp2); return calcAndSetCrc(); } private: void initPacket(uint8_t mem = 0, uint8_t bp0 = 0, uint8_t bp1 = 0, uint8_t bp2 = 0) { payloadStart[0] = mem; payloadStart[1] = bp0; payloadStart[2] = bp1; payloadStart[3] = bp2; } }; /** * @brief This class generates the space packet to update the time of the PLOC supervisor. */ class SetTimeRef : public TcBase { public: static constexpr size_t PAYLOAD_LEN = 8; SetTimeRef(TcParams params) : TcBase(params, Apid::TMTC_MAN, static_cast(tc::TmtcId::TIME_REF), 8) {} ReturnValue_t buildPacket(Clock::TimeOfDay_t* time) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } res = initPacket(time); if (res != returnvalue::OK) { return res; } return calcAndSetCrc(); } private: static const uint16_t SYNC = 0x8000; ReturnValue_t initPacket(Clock::TimeOfDay_t* time) { size_t serializedSize = 6; uint8_t* dataFieldPtr = payloadStart; uint16_t milliseconds = static_cast(time->usecond / 1000) | SYNC; ReturnValue_t result = SerializeAdapter::serialize(&milliseconds, &dataFieldPtr, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { return result; } uint8_t second = static_cast(time->second); result = SerializeAdapter::serialize(&second, &dataFieldPtr, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { return result; } uint8_t minute = static_cast(time->minute); result = SerializeAdapter::serialize(&minute, &dataFieldPtr, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { return result; } uint8_t hour = static_cast(time->hour); result = SerializeAdapter::serialize(&hour, &dataFieldPtr, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { return result; } uint8_t day = static_cast(time->day); result = SerializeAdapter::serialize(&day, &dataFieldPtr, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { return result; } uint8_t month = static_cast(time->month); result = SerializeAdapter::serialize(&month, &dataFieldPtr, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { return result; } uint8_t year = static_cast(time->year - 1900); return SerializeAdapter::serialize(&year, &dataFieldPtr, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); } }; /** * @brief This class can be used to generate the set boot timout command. */ class SetBootTimeout : public TcBase { public: static constexpr size_t PAYLOAD_LEN = 4; /** * @brief Constructor * * @param timeout The boot timeout in milliseconds. */ SetBootTimeout(TcParams params) : TcBase(params, Apid::BOOT_MAN, static_cast(tc::BootManId::SET_BOOT_TIMEOUT), PAYLOAD_LEN) {} ReturnValue_t buildPacket(uint32_t timeout) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(timeout); return calcAndSetCrc(); } private: void initPacket(uint32_t timeout) { size_t serializedSize = 0; uint8_t* dataFieldPtr = payloadStart; SerializeAdapter::serialize(&timeout, &dataFieldPtr, &serializedSize, sizeof(timeout), SerializeIF::Endianness::BIG); } }; class FactoryReset : public TcBase { public: FactoryReset(TcParams params) : TcBase(params, Apid::DATA_LOGGER, static_cast(tc::DataLoggerServiceId::FACTORY_RESET), 0) {} ReturnValue_t buildPacket(std::optional op) { if (op) { setLenFromPayloadLen(1); } auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } if (op) { payloadStart[0] = op.value(); } return calcAndSetCrc(); } private: }; /** * @brief This class can be used to generate the space packet to set the maximum boot tries. */ class SetRestartTries : public TcBase { public: /** * @brief Constructor * * @param restartTries Maximum restart tries to set. */ SetRestartTries(TcParams params) : TcBase(params, Apid::BOOT_MAN, static_cast(tc::BootManId::SET_MAX_REBOOT_TRIES), 1) {} ReturnValue_t buildPacket(uint8_t restartTries) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(restartTries); return calcAndSetCrc(); } private: uint8_t restartTries = 0; void initPacket(uint8_t restartTries) { payloadStart[0] = restartTries; } }; /** * @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 TcBase { public: /** * @brief Constructor */ DisablePeriodicHkTransmission(TcParams params) : TcBase(params, Apid::HK, static_cast(tc::HkId::ENABLE), 1) {} ReturnValue_t buildPacket() { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(); return calcAndSetCrc(); } private: void initPacket() { payloadStart[0] = false; } }; /** * @brief This class packages the command to enable of disable the latchup alert. * * @details There are 7 different latchup alerts. */ class LatchupAlert : public TcBase { public: /** * @brief Constructor * * @param state true - enable, false - disable * @param latchupId Identifies the latchup to enable/disable (0 - 0.85V, 1 - 1.8V, 2 - MISC, * 3 - 3.3V, 4 - NVM_4XO, 5 - MISSION, 6 - SAFECOTS) */ LatchupAlert(TcParams params) : TcBase(params, Apid::LATCHUP_MON) { setLenFromPayloadLen(1); } ReturnValue_t buildPacket(bool state, uint8_t latchupId) { if (state) { setServiceId(static_cast(tc::LatchupMonId::ENABLE)); } else { setServiceId(static_cast(tc::LatchupMonId::DISABLE)); } auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(latchupId); return calcAndSetCrc(); } private: uint8_t latchupId = 0; void initPacket(uint8_t latchupId) { payloadStart[0] = latchupId; } }; class SetAlertlimit : public TcBase { 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(TcParams params) : TcBase(params, Apid::LATCHUP_MON, static_cast(tc::LatchupMonId::SET_ALERT_LIMIT), 5) {} ReturnValue_t buildPacket(uint8_t latchupId, uint32_t dutycycle) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } res = initPacket(latchupId, dutycycle); if (res != returnvalue::OK) { return res; } return calcAndSetCrc(); } private: uint8_t latchupId = 0; uint32_t dutycycle = 0; ReturnValue_t initPacket(uint8_t latchupId, uint32_t dutycycle) { payloadStart[0] = latchupId; size_t serLen = 0; return SerializeAdapter::serialize(&dutycycle, payloadStart + 1, &serLen, sizeof(dutycycle), 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 TcBase { public: /** * @brief Constructor * * @param windowSize * @param stridingStepSize */ SetAdcWindowAndStride(TcParams params) : TcBase(params, Apid::ADC_MON, static_cast(tc::AdcMonId::SET_WINDOW_STRIDE), 4) {} ReturnValue_t buildPacket(uint16_t windowSize, uint16_t stridingStepSize) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(windowSize, stridingStepSize); return calcAndSetCrc(); } private: void initPacket(uint16_t windowSize, uint16_t stridingStepSize) { size_t serializedSize = 6; uint8_t* data = payloadStart; SerializeAdapter::serialize(&windowSize, &data, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); SerializeAdapter::serialize(&stridingStepSize, &data, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); } }; /** * @brief This class packages the space packet to set the ADC trigger threshold. */ class SetAdcThreshold : public TcBase { public: /** * @brief Constructor * * @param threshold */ SetAdcThreshold(TcParams params) : TcBase(params, Apid::ADC_MON, static_cast(tc::AdcMonId::SET_ADC_THRESHOLD), 4) {} ReturnValue_t buildPacket(uint32_t threshold) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(threshold); return calcAndSetCrc(); } private: void initPacket(uint32_t threshold) { size_t serializedSize = 0; SerializeAdapter::serialize(&threshold, payloadStart, &serializedSize, sizeof(threshold), SerializeIF::Endianness::BIG); } }; /** * @brief This class packages the space packet to run auto EM tests. */ class RunAutoEmTests : public TcBase { public: /** * @brief Constructor * * @param test 1 - complete EM test, 2 - Short test (only memory readback NVM0,1,3) */ RunAutoEmTests(TcParams params) : TcBase(params, Apid::TMTC_MAN, static_cast(tc::TmtcId::RUN_AUTO_EM_TEST), 1) {} ReturnValue_t buildPacket(uint8_t test) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(test); return calcAndSetCrc(); } private: uint8_t test = 0; void initPacket(uint8_t test) { payloadStart[0] = test; } }; /** * @brief This class packages the space packet to enable or disable ADC channels. */ class SetAdcEnabledChannels : public TcBase { public: /** * @brief Constructor * * @param ch Defines channels to be enabled or disabled. */ SetAdcEnabledChannels(TcParams params) : TcBase(params, Apid::ADC_MON, static_cast(tc::AdcMonId::SET_ENABLED_CHANNELS), 2) { } ReturnValue_t buildPacket(uint16_t ch) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(ch); return calcAndSetCrc(); } private: void initPacket(uint16_t ch) { size_t serializedSize = 0; SerializeAdapter::serialize(&ch, &payloadStart, &serializedSize, sizeof(ch), SerializeIF::Endianness::BIG); } }; /** * @brief This class packages the space packet change the state of a GPIO. This command is only * required for ground testing. */ class SetGpio : public TcBase { public: /** * @brief Constructor * * @param port * @param pin * @param val */ SetGpio(TcParams params) : TcBase(params, Apid::TMTC_MAN, static_cast(tc::TmtcId::SET_GPIO), 3) {} ReturnValue_t buildPacket(uint8_t port, uint8_t pin, uint8_t val) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(port, pin, val); return calcAndSetCrc(); } private: uint8_t port = 0; uint8_t pin = 0; uint8_t val = 0; void initPacket(uint8_t port, uint8_t pin, uint8_t val) { payloadStart[0] = port; payloadStart[1] = pin; payloadStart[2] = val; } }; /** * @brief This class packages the space packet causing the supervisor print the state of a GPIO * to the debug output. */ class ReadGpio : public TcBase { public: /** * @brief Constructor * * @param port * @param pin */ ReadGpio(TcParams params) : TcBase(params, Apid::TMTC_MAN, static_cast(tc::TmtcId::READ_GPIO), 2) {} ReturnValue_t buildPacket(uint8_t port, uint8_t pin) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(port, pin); return calcAndSetCrc(); } private: uint8_t port = 0; uint8_t pin = 0; void initPacket(uint8_t port, uint8_t pin) { payloadStart[0] = port; payloadStart[1] = pin; } }; class SetShutdownTimeout : public TcBase { public: SetShutdownTimeout(TcParams params) : TcBase(params, Apid::BOOT_MAN, static_cast(tc::BootManId::SHUTDOWN_TIMEOUT), 4) {} ReturnValue_t buildPacket(uint32_t timeout) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(timeout); return calcAndSetCrc(); } private: void initPacket(uint32_t timeout) { size_t serLen = 0; SerializeAdapter::serialize(&timeout, payloadStart, &serLen, sizeof(timeout), SerializeIF::Endianness::BIG); } }; /** * @brief Command to request CRC over memory region of the supervisor. */ class CheckMemory : public TcBase { public: /** * @brief Constructor * * @param memoryId * @param startAddress Start address of CRC calculation * @param length Length in bytes of memory region */ CheckMemory(TcParams params) : TcBase(params, Apid::MEM_MAN, static_cast(tc::MemManId::CHECK), 10) {} ReturnValue_t buildPacket(uint8_t memoryId, uint32_t startAddress, uint32_t length) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(memoryId, startAddress, length); return calcAndSetCrc(); } private: uint8_t n = 1; void initPacket(uint8_t memoryId, uint32_t startAddress, uint32_t length) { uint8_t* data = payloadStart; size_t serLen = 6; SerializeAdapter::serialize(&memoryId, &data, &serLen, spParams.maxSize, SerializeIF::Endianness::BIG); SerializeAdapter::serialize(&n, &data, &serLen, spParams.maxSize, SerializeIF::Endianness::BIG); SerializeAdapter::serialize(&startAddress, &data, &serLen, spParams.maxSize, SerializeIF::Endianness::BIG); SerializeAdapter::serialize(&length, &data, &serLen, spParams.maxSize, SerializeIF::Endianness::BIG); } }; /** * @brief This class packages the space packet transporting a part of an MPSoC update. */ class WriteMemory : public TcBase { public: /** * @brief Constructor * * @param seqFlags Sequence flags * @param sequenceCount Sequence count (first update packet expects 1 as sequence count) * @param updateData Pointer to buffer containing update data */ WriteMemory(TcParams params) : TcBase(params, Apid::MEM_MAN, static_cast(tc::MemManId::WRITE), 1) {} ReturnValue_t buildPacket(ccsds::SequenceFlags seqFlags, uint16_t sequenceCount, uint8_t memoryId, uint32_t startAddress, uint16_t length, uint8_t* updateData) { if (length > CHUNK_MAX) { sif::error << "WriteMemory::WriteMemory: Invalid length" << std::endl; return SerializeIF::BUFFER_TOO_SHORT; } spParams.creator.setSeqFlags(seqFlags); spParams.creator.setSeqCount(sequenceCount); initPacket(memoryId, startAddress, length, updateData); auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } return calcAndSetCrc(); } // Although the space packet has space left for 1010 bytes of data to supervisor can only process // update packets with a maximum of 512 bytes. static const uint16_t CHUNK_MAX = 512; private: static const uint16_t META_DATA_LENGTH = 8; uint8_t n = 1; ReturnValue_t initPacket(uint8_t memoryId, uint32_t startAddr, uint16_t updateDataLen, uint8_t* updateData) { uint8_t* data = payloadStart; if (updateDataLen % 2 != 0) { setLenFromPayloadLen(META_DATA_LENGTH + updateDataLen + 1); } else { setLenFromPayloadLen(META_DATA_LENGTH + updateDataLen); } // To avoid crashes in this unexpected case ReturnValue_t result = checkPayloadLen(); if (result != returnvalue::OK) { return result; } size_t serializedSize = 6; SerializeAdapter::serialize(&memoryId, &data, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); SerializeAdapter::serialize(&n, &data, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); SerializeAdapter::serialize(&startAddr, &data, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); SerializeAdapter::serialize(&updateDataLen, &data, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); std::memcpy(data, updateData, updateDataLen); if (updateDataLen % 2 != 0) { // The data field must be two bytes aligned. Thus, in case the number of bytes to write is odd // a value of zero is added here data[updateDataLen + 1] = 0; } return returnvalue::OK; } }; /** * @brief This class can be used to package erase memory command */ class EraseMemory : public TcBase { public: EraseMemory(TcParams params) : TcBase(params, Apid::MEM_MAN, static_cast(tc::MemManId::ERASE), PAYLOAD_LENGTH) {} ReturnValue_t buildPacket(uint8_t memoryId, uint32_t startAddress, uint32_t length) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(memoryId, startAddress, length); return calcAndSetCrc(); } private: static const uint16_t PAYLOAD_LENGTH = 10; // length without CRC field uint8_t n = 1; void initPacket(uint8_t memoryId, uint32_t startAddress, uint32_t length) { uint8_t* data = payloadStart; size_t serializedSize = 6; SerializeAdapter::serialize(&memoryId, &data, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); SerializeAdapter::serialize(&n, &data, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); SerializeAdapter::serialize(&startAddress, &data, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); SerializeAdapter::serialize(&length, &data, &serializedSize, spParams.maxSize, SerializeIF::Endianness::BIG); } }; class VerificationReport { public: VerificationReport(TmBase& readerBase) : readerBase(readerBase) {} virtual ~VerificationReport() = default; virtual ReturnValue_t parse() { if (not readerBase.crcIsOk()) { return result::CRC_FAILURE; } if (readerBase.getApid() != Apid::TMTC_MAN) { return result::INVALID_APID; } if (readerBase.getBufSize() < MIN_TMTC_LEN + PAYLOAD_LEN or readerBase.getPayloadLen() < PAYLOAD_LEN) { sif::error << "VerificationReport: Invalid verification report, payload too small" << std::endl; return result::BUF_TOO_SMALL; } const uint8_t* payloadStart = readerBase.getPayloadStart(); size_t remLen = PAYLOAD_LEN; ReturnValue_t result = SerializeAdapter::deSerialize(&refApid, &payloadStart, &remLen, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { sif::debug << "VerificationReport: Failed to deserialize reference APID field" << std::endl; return result; } result = SerializeAdapter::deSerialize(&refServiceId, &payloadStart, &remLen, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { sif::debug << "VerificationReport: Failed to deserialize reference Service ID field" << std::endl; return result; } result = SerializeAdapter::deSerialize(&refSeqCount, &payloadStart, &remLen, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { sif::debug << "VerificationReport: Failed to deserialize reference sequence count field" << std::endl; return result; } result = SerializeAdapter::deSerialize(&statusCode, &payloadStart, &remLen, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { sif::debug << "VerificationReport: Failed to deserialize status code field" << std::endl; return result; } return returnvalue::OK; } /** * @brief Gets the APID of command which caused the transmission of this verification report. */ uint8_t getRefApid() const { return refApid; } uint8_t getRefServiceId() const { return refServiceId; } uint16_t getRefSequenceCount() const { return refSeqCount; } uint32_t getStatusCode() const { return statusCode; } protected: TmBase& readerBase; uint8_t refApid = 0; uint8_t refServiceId = 0; uint16_t refSeqCount = 0; uint32_t statusCode = 0; static const size_t PAYLOAD_LEN = 8; }; class AcknowledgmentReport : public VerificationReport { public: AcknowledgmentReport(TmBase& readerBase) : VerificationReport(readerBase) {} virtual ReturnValue_t parse() override { if (readerBase.getServiceId() != static_cast(tm::TmtcId::ACK) and readerBase.getServiceId() != static_cast(tm::TmtcId::NAK)) { return result::INVALID_SERVICE_ID; } return VerificationReport::parse(); } void printStatusInformation() { StatusCode statusCode = static_cast(getStatusCode()); const char* prefix = "Supervisor acknowledgment report status: "; switch (statusCode) { case StatusCode::OK: { sif::warning << prefix << "Ok" << std::endl; break; } case StatusCode::BAD_PARAM: { sif::warning << prefix << "Bad param" << std::endl; break; } case StatusCode::TIMEOUT: { sif::warning << prefix << "Timeout" << std::endl; break; } case StatusCode::RX_ERROR: { sif::warning << prefix << "RX error" << std::endl; break; } case StatusCode::TX_ERROR: { sif::warning << prefix << "TX error" << std::endl; break; } case StatusCode::HEADER_EMPTY: { sif::warning << prefix << "Header empty" << std::endl; break; } case StatusCode::DEFAULT_NAK: { sif::warning << prefix << "Default code for NAK" << std::endl; break; } case StatusCode::ROUTE_PACKET: { sif::warning << prefix << "Route packet error" << std::endl; break; } default: sif::warning << "AcknowledgmentReport::printStatusInformation: Invalid status code: 0x" << std::hex << static_cast(statusCode) << std::endl; break; } } private: enum class StatusCode : uint16_t { OK = 0x0, BAD_PARAM = 0x1, TIMEOUT = 0x2, RX_ERROR = 0x3, TX_ERROR = 0x4, HEADER_EMPTY = 0x5, DEFAULT_NAK = 0x6, ROUTE_PACKET = 0x7 }; }; class ExecutionReport : public VerificationReport { public: ExecutionReport(TmBase& readerBase) : VerificationReport(readerBase) {} TmBase& getReader() { return readerBase; } ReturnValue_t parse() override { if (readerBase.getServiceId() != static_cast(tm::TmtcId::EXEC_ACK) and readerBase.getServiceId() != static_cast(tm::TmtcId::EXEC_NAK)) { return returnvalue::FAILED; } return VerificationReport::parse(); } void printStatusInformation() { StatusCode statusCode = static_cast(getStatusCode()); switch (statusCode) { case StatusCode::OK: { sif::warning << STATUS_PRINTOUT_PREFIX << "Ok" << std::endl; break; } case StatusCode::INIT_ERROR: { sif::warning << STATUS_PRINTOUT_PREFIX << "Init error" << std::endl; break; } case StatusCode::BAD_PARAM: { sif::warning << STATUS_PRINTOUT_PREFIX << "Bad param" << std::endl; break; } case StatusCode::NOT_INITIALIZED: { sif::warning << STATUS_PRINTOUT_PREFIX << "Not initialized" << std::endl; break; } case StatusCode::BAD_PERIPH_ID: { sif::warning << STATUS_PRINTOUT_PREFIX << "Bad periph ID" << std::endl; break; } case StatusCode::TIMEOUT: { sif::warning << STATUS_PRINTOUT_PREFIX << "Timeout" << std::endl; break; } case StatusCode::RX_ERROR: { sif::warning << STATUS_PRINTOUT_PREFIX << "RX error" << std::endl; break; } case StatusCode::TX_ERROR: { sif::warning << STATUS_PRINTOUT_PREFIX << "TX error" << std::endl; break; } case StatusCode::BUF_EMPTY: { sif::warning << STATUS_PRINTOUT_PREFIX << "Buf empty" << std::endl; break; } case StatusCode::BUF_FULL: { sif::warning << STATUS_PRINTOUT_PREFIX << "Buf full" << std::endl; break; } case StatusCode::NAK: { sif::warning << STATUS_PRINTOUT_PREFIX << "Nak, default error code" << std::endl; break; } case StatusCode::ARB_LOST: { sif::warning << STATUS_PRINTOUT_PREFIX << "Arb lost" << std::endl; break; } case StatusCode::BUSY: { sif::warning << STATUS_PRINTOUT_PREFIX << "Busy" << std::endl; break; } case StatusCode::NOT_IMPLEMENTED: { sif::warning << STATUS_PRINTOUT_PREFIX << "Not implemented" << std::endl; break; } case StatusCode::ALIGNEMENT_ERROR: { sif::warning << STATUS_PRINTOUT_PREFIX << "Alignment error" << std::endl; break; } case StatusCode::PERIPH_ERR: { sif::warning << STATUS_PRINTOUT_PREFIX << "Periph error" << std::endl; break; } case StatusCode::FAILED_LATCH: { sif::warning << STATUS_PRINTOUT_PREFIX << "Failed latch" << std::endl; break; } case StatusCode::GPIO_HIGH: { sif::warning << STATUS_PRINTOUT_PREFIX << "GPIO high" << std::endl; break; } case StatusCode::GPIO_LOW: { sif::warning << STATUS_PRINTOUT_PREFIX << "GPIO low" << std::endl; break; } case StatusCode::TEST_PASSED: { sif::warning << STATUS_PRINTOUT_PREFIX << "Test passed" << std::endl; break; } case StatusCode::TEST_FAILED: { sif::warning << STATUS_PRINTOUT_PREFIX << "Test failed" << std::endl; break; } case StatusCode::NOTHING_TODO: { sif::warning << STATUS_PRINTOUT_PREFIX << "Nothing todo, not an error but a warning" << std::endl; break; } case StatusCode::POWER_FAULT: { sif::warning << STATUS_PRINTOUT_PREFIX << "Power fault" << std::endl; break; } case StatusCode::INVALID_LENGTH: { sif::warning << STATUS_PRINTOUT_PREFIX << "Invalid length" << std::endl; break; } case StatusCode::OUT_OF_RANGE: { sif::warning << STATUS_PRINTOUT_PREFIX << "Out of range, lenght check of parameter failed" << std::endl; break; } case StatusCode::OUT_OF_HEAP_MEMORY: { sif::warning << STATUS_PRINTOUT_PREFIX << "Out of heap memory" << std::endl; break; } case StatusCode::INVALID_STATE_TRANSITION: { sif::warning << STATUS_PRINTOUT_PREFIX << "Invalid state transition" << std::endl; break; } case StatusCode::MPSOC_ALREADY_BOOTING: { sif::warning << STATUS_PRINTOUT_PREFIX << "MPSoC already booting" << std::endl; break; } case StatusCode::MPSOC_ALREADY_OPERATIONAL: { sif::warning << STATUS_PRINTOUT_PREFIX << "MPSoC already operational" << std::endl; break; } case StatusCode::MPSOC_BOOT_FAILED: { sif::warning << STATUS_PRINTOUT_PREFIX << "MPSoC boot failed" << std::endl; break; } case StatusCode::SP_NOT_AVAILABLE: { sif::warning << STATUS_PRINTOUT_PREFIX << "SP not available" << std::endl; break; } case StatusCode::SP_DATA_INSUFFICIENT: { sif::warning << STATUS_PRINTOUT_PREFIX << "SP data insufficient" << std::endl; break; } case StatusCode::SP_MEMORY_ID_INVALID: { sif::warning << STATUS_PRINTOUT_PREFIX << "SP data insufficient" << std::endl; break; } case StatusCode::MPSOC_NOT_IN_RESET: { sif::warning << STATUS_PRINTOUT_PREFIX << "MPSoC not in reset" << std::endl; break; } case StatusCode::FLASH_INIT_FAILED: { sif::warning << STATUS_PRINTOUT_PREFIX << "Flash init failed" << std::endl; break; } case StatusCode::FLASH_ERASE_FAILED: { sif::warning << STATUS_PRINTOUT_PREFIX << "Flash erase failed" << std::endl; break; } case StatusCode::FLASH_WRITE_FAILED: { sif::warning << STATUS_PRINTOUT_PREFIX << "Flash write failed" << std::endl; break; } case StatusCode::FLASH_VERIFY_FAILED: { sif::warning << STATUS_PRINTOUT_PREFIX << "Flash verify failed" << std::endl; break; } case StatusCode::CANNOT_ACCESS_TM: { sif::warning << STATUS_PRINTOUT_PREFIX << "Can not access tm" << std::endl; break; } case StatusCode::CANNOT_SEND_TM: { sif::warning << STATUS_PRINTOUT_PREFIX << "Can not access tm" << std::endl; break; } case StatusCode::PG_LOW: { sif::warning << STATUS_PRINTOUT_PREFIX << "PG low" << std::endl; break; } case StatusCode::PG_5V_LOW: { sif::warning << STATUS_PRINTOUT_PREFIX << "PG 5V low" << std::endl; break; } case StatusCode::PG_0V85_LOW: { sif::warning << STATUS_PRINTOUT_PREFIX << "PG 0V85 low" << std::endl; break; } case StatusCode::PG_1V8_LOW: { sif::warning << STATUS_PRINTOUT_PREFIX << "PG 1V8 low" << std::endl; break; } case StatusCode::PG_MISC_LOW: { sif::warning << STATUS_PRINTOUT_PREFIX << "PG misc low" << std::endl; break; } case StatusCode::PG_3V3_LOW: { sif::warning << STATUS_PRINTOUT_PREFIX << "PG 3V3 low" << std::endl; break; } case StatusCode::PG_MB_VAIO_LOW: { sif::warning << STATUS_PRINTOUT_PREFIX << "PG mb vaio low" << std::endl; break; } case StatusCode::PG_MB_MPSOCIO_LOW: { sif::warning << STATUS_PRINTOUT_PREFIX << "PG mb mpsocio low" << std::endl; break; } default: sif::warning << "ExecutionReport::printStatusInformation: Invalid status code: 0x" << std::hex << std::setfill('0') << std::setw(4) << static_cast(statusCode) << std::dec << std::endl; break; } } private: static constexpr char STATUS_PRINTOUT_PREFIX[] = "Supervisor execution failure report status: "; enum class StatusCode : uint16_t { OK = 0x0, INIT_ERROR = 0x1, BAD_PARAM = 0x2, NOT_INITIALIZED = 0x3, BAD_PERIPH_ID = 0x4, TIMEOUT = 0x5, RX_ERROR = 0x6, TX_ERROR = 0x7, BUF_EMPTY = 0x8, BUF_FULL = 0x9, NAK = 0xA, ARB_LOST = 0xB, BUSY = 0xC, NOT_IMPLEMENTED = 0xD, ALIGNEMENT_ERROR = 0xE, PERIPH_ERR = 0xF, FAILED_LATCH = 0x10, GPIO_HIGH = 0x11, GPIO_LOW = 0x12, TEST_PASSED = 0x13, TEST_FAILED = 0x14, NOTHING_TODO = 0x100, POWER_FAULT = 0x101, INVALID_LENGTH = 0x102, OUT_OF_RANGE = 0x103, OUT_OF_HEAP_MEMORY = 0x104, INVALID_STATE_TRANSITION = 0x105, MPSOC_ALREADY_BOOTING = 0x106, MPSOC_ALREADY_OPERATIONAL = 0x107, MPSOC_BOOT_FAILED = 0x108, SP_NOT_AVAILABLE = 0x200, SP_DATA_INSUFFICIENT = 0x201, SP_MEMORY_ID_INVALID = 0x202, MPSOC_NOT_IN_RESET = 0x203, FLASH_INIT_FAILED = 0x204, FLASH_ERASE_FAILED = 0x205, FLASH_WRITE_FAILED = 0x206, FLASH_VERIFY_FAILED = 0x207, CANNOT_ACCESS_TM = 0x208, CANNOT_SEND_TM = 0x209, PG_LOW = 0x300, PG_5V_LOW = 0x301, PG_0V85_LOW = 0x302, PG_1V8_LOW = 0x303, PG_MISC_LOW = 0x304, PG_3V3_LOW = 0x305, PG_MB_VAIO_LOW = 0x306, PG_MB_MPSOCIO_LOW = 0x307 }; }; class UpdateStatusReport { public: UpdateStatusReport(TmBase& tmReader) : tmReader(tmReader) {} ReturnValue_t parse() { if (not tmReader.crcIsOk()) { return result::CRC_FAILURE; } if (tmReader.getApid() != Apid::MEM_MAN) { return result::INVALID_APID; } if (tmReader.getBufSize() < MIN_TMTC_LEN + PAYLOAD_LEN or tmReader.getPayloadLen() < PAYLOAD_LEN) { sif::error << "VerificationReport: Invalid verification report, payload too small" << std::endl; return result::BUF_TOO_SMALL; } size_t remLen = PAYLOAD_LEN; if (remLen < PAYLOAD_LEN) { return result::INVALID_REPLY_LENGTH; } const uint8_t* dataFieldPtr = tmReader.getPayloadStart(); SerializeAdapter::deSerialize(&memoryId, &dataFieldPtr, &remLen, SerializeIF::Endianness::BIG); SerializeAdapter::deSerialize(&n, &dataFieldPtr, &remLen, SerializeIF::Endianness::BIG); SerializeAdapter::deSerialize(&startAddress, &dataFieldPtr, &remLen, SerializeIF::Endianness::BIG); SerializeAdapter::deSerialize(&length, &dataFieldPtr, &remLen, SerializeIF::Endianness::BIG); SerializeAdapter::deSerialize(&crc, &dataFieldPtr, &remLen, SerializeIF::Endianness::BIG); return returnvalue::OK; } ReturnValue_t verifyCrc(uint16_t goodCrc) const { if (crc != goodCrc) { return result::UPDATE_CRC_FAILURE; } return returnvalue::OK; } uint16_t getCrc() const { return crc; } private: TmBase& tmReader; // Nominal size of the space packet static const uint16_t PAYLOAD_LEN = 12; // header, data field and crc uint8_t memoryId = 0; uint8_t n = 0; uint32_t startAddress = 0; uint32_t length = 0; uint16_t crc = 0; }; /** * @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 socState = lp_var_t(sid.objectId, PoolIds::BR_SOC_STATE, this); lp_var_t powerCycles = lp_var_t(sid.objectId, PoolIds::POWER_CYCLES, 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); lp_var_t bootState = lp_var_t(sid.objectId, PoolIds::BOOT_STATE, this); lp_var_t bootCycles = lp_var_t(sid.objectId, PoolIds::BOOT_CYCLES, this); }; /** * @brief This dataset stores the housekeeping data of the supervisor. */ class HkSet : public StaticLocalDataSet { public: enum class SocState { OFF = 0, BOOTING = 1, OPERATIONAL = 3, SHUTDOWN = 4 }; 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::HK_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); }; /** * @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 timeMsec = lp_var_t(sid.objectId, PoolIds::LATCHUP_RPT_TIME_MSEC, 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 isSet = lp_var_t(sid.objectId, PoolIds::LATCHUP_RPT_IS_SET, this); static const uint8_t IS_SET_BIT_POS = 15; }; /** * @brief This dataset stores the logging report. */ class LoggingReport : public StaticLocalDataSet { public: LoggingReport(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, LOGGING_RPT_ID) {} LoggingReport(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, LOGGING_RPT_ID)) {} lp_var_t latchupHappenCnt0 = lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNT_0, this); lp_var_t latchupHappenCnt1 = lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNT_1, this); lp_var_t latchupHappenCnt2 = lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNT_2, this); lp_var_t latchupHappenCnt3 = lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNT_3, this); lp_var_t latchupHappenCnt4 = lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNT_4, this); lp_var_t latchupHappenCnt5 = lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNT_5, this); lp_var_t latchupHappenCnt6 = lp_var_t(sid.objectId, PoolIds::LATCHUP_HAPPENED_CNT_6, this); lp_var_t adcDeviationTriggersCnt = lp_var_t(sid.objectId, PoolIds::ADC_DEVIATION_TRIGGERS_CNT, this); lp_var_t tcReceivedCnt = lp_var_t(sid.objectId, PoolIds::TC_RECEIVED_CNT, this); lp_var_t tmAvailableCnt = lp_var_t(sid.objectId, PoolIds::TM_AVAILABLE_CNT, this); lp_var_t supervisorBoots = lp_var_t(sid.objectId, PoolIds::SUPERVISOR_BOOTS, this); lp_var_t mpsocBoots = lp_var_t(sid.objectId, PoolIds::MPSOC_BOOTS, this); lp_var_t mpsocBootFailedAttempts = lp_var_t(sid.objectId, PoolIds::MPSOC_BOOT_FAILED_ATTEMPTS, this); lp_var_t mpsocPowerup = lp_var_t(sid.objectId, PoolIds::MPSOC_POWER_UP, this); lp_var_t mpsocUpdates = lp_var_t(sid.objectId, PoolIds::MPSOC_UPDATES, this); lp_var_t lastRecvdTc = lp_var_t(sid.objectId, PoolIds::LAST_RECVD_TC, this); void printSet() { sif::info << "LoggingReport: Latchup happened count 0: " << this->latchupHappenCnt0 << std::endl; sif::info << "LoggingReport: Latchup happened count 1: " << this->latchupHappenCnt1 << std::endl; sif::info << "LoggingReport: Latchup happened count 2: " << this->latchupHappenCnt2 << std::endl; sif::info << "LoggingReport: Latchup happened count 3: " << this->latchupHappenCnt3 << std::endl; sif::info << "LoggingReport: Latchup happened count 4: " << this->latchupHappenCnt4 << std::endl; sif::info << "LoggingReport: Latchup happened count 5: " << this->latchupHappenCnt5 << std::endl; sif::info << "LoggingReport: Latchup happened count 6: " << this->latchupHappenCnt6 << std::endl; sif::info << "LoggingReport: ADC deviation triggers count: " << this->adcDeviationTriggersCnt << std::endl; sif::info << "LoggingReport: TC received count: " << this->tcReceivedCnt << std::endl; sif::info << "LoggingReport: TM available count: " << this->tmAvailableCnt << std::endl; sif::info << "LoggingReport: Supervisor boots: " << this->supervisorBoots << std::endl; sif::info << "LoggingReport: MPSoC boots: " << this->mpsocBoots << std::endl; sif::info << "LoggingReport: MPSoC boot failed attempts: " << this->mpsocBootFailedAttempts << std::endl; sif::info << "LoggingReport: MPSoC power up: " << this->mpsocPowerup << std::endl; sif::info << "LoggingReport: MPSoC updates: " << this->mpsocUpdates << std::endl; sif::info << "LoggingReport: APID of last received TC: 0x" << std::hex << this->lastRecvdTc << std::endl; } }; /** * @brief This dataset stores the ADC report. */ class AdcReport : public StaticLocalDataSet { public: AdcReport(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, ADC_REPORT_SET_ID) {} AdcReport(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, ADC_REPORT_SET_ID)) {} lp_var_t adcRaw0 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_0, this); lp_var_t adcRaw1 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_1, this); lp_var_t adcRaw2 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_2, this); lp_var_t adcRaw3 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_3, this); lp_var_t adcRaw4 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_4, this); lp_var_t adcRaw5 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_5, this); lp_var_t adcRaw6 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_6, this); lp_var_t adcRaw7 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_7, this); lp_var_t adcRaw8 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_8, this); lp_var_t adcRaw9 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_9, this); lp_var_t adcRaw10 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_10, this); lp_var_t adcRaw11 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_11, this); lp_var_t adcRaw12 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_12, this); lp_var_t adcRaw13 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_13, this); lp_var_t adcRaw14 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_14, this); lp_var_t adcRaw15 = lp_var_t(sid.objectId, PoolIds::ADC_RAW_15, this); lp_var_t adcEng0 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_0, this); lp_var_t adcEng1 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_1, this); lp_var_t adcEng2 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_2, this); lp_var_t adcEng3 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_3, this); lp_var_t adcEng4 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_4, this); lp_var_t adcEng5 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_5, this); lp_var_t adcEng6 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_6, this); lp_var_t adcEng7 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_7, this); lp_var_t adcEng8 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_8, this); lp_var_t adcEng9 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_9, this); lp_var_t adcEng10 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_10, this); lp_var_t adcEng11 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_11, this); lp_var_t adcEng12 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_12, this); lp_var_t adcEng13 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_13, this); lp_var_t adcEng14 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_14, this); lp_var_t adcEng15 = lp_var_t(sid.objectId, PoolIds::ADC_ENG_15, this); void printSet() { sif::info << "---- Adc Report: Raw values ----" << std::endl; sif::info << "AdcReport: ADC raw 0: " << std::dec << this->adcRaw0 << std::endl; sif::info << "AdcReport: ADC raw 1: " << this->adcRaw1 << std::endl; sif::info << "AdcReport: ADC raw 2: " << this->adcRaw2 << std::endl; sif::info << "AdcReport: ADC raw 3: " << this->adcRaw3 << std::endl; sif::info << "AdcReport: ADC raw 4: " << this->adcRaw4 << std::endl; sif::info << "AdcReport: ADC raw 5: " << this->adcRaw5 << std::endl; sif::info << "AdcReport: ADC raw 6: " << this->adcRaw6 << std::endl; sif::info << "AdcReport: ADC raw 7: " << this->adcRaw7 << std::endl; sif::info << "AdcReport: ADC raw 8: " << this->adcRaw8 << std::endl; sif::info << "AdcReport: ADC raw 9: " << this->adcRaw9 << std::endl; sif::info << "AdcReport: ADC raw 10: " << this->adcRaw10 << std::endl; sif::info << "AdcReport: ADC raw 11: " << this->adcRaw11 << std::endl; sif::info << "AdcReport: ADC raw 12: " << this->adcRaw12 << std::endl; sif::info << "AdcReport: ADC raw 13: " << this->adcRaw13 << std::endl; sif::info << "AdcReport: ADC raw 14: " << this->adcRaw14 << std::endl; sif::info << "AdcReport: ADC raw 15: " << this->adcRaw15 << std::endl; sif::info << "---- Adc Report: Engineering values ----" << std::endl; sif::info << "AdcReport: ADC eng 0: " << this->adcEng0 << std::endl; sif::info << "AdcReport: ADC eng 1: " << this->adcEng1 << std::endl; sif::info << "AdcReport: ADC eng 2: " << this->adcEng2 << std::endl; sif::info << "AdcReport: ADC eng 3: " << this->adcEng3 << std::endl; sif::info << "AdcReport: ADC eng 4: " << this->adcEng4 << std::endl; sif::info << "AdcReport: ADC eng 5: " << this->adcEng5 << std::endl; sif::info << "AdcReport: ADC eng 6: " << this->adcEng6 << std::endl; sif::info << "AdcReport: ADC eng 7: " << this->adcEng7 << std::endl; sif::info << "AdcReport: ADC eng 8: " << this->adcEng8 << std::endl; sif::info << "AdcReport: ADC eng 9: " << this->adcEng9 << std::endl; sif::info << "AdcReport: ADC eng 10: " << this->adcEng10 << std::endl; sif::info << "AdcReport: ADC eng 11: " << this->adcEng11 << std::endl; sif::info << "AdcReport: ADC eng 12: " << this->adcEng12 << std::endl; sif::info << "AdcReport: ADC eng 13: " << this->adcEng13 << std::endl; sif::info << "AdcReport: ADC eng 14: " << this->adcEng14 << std::endl; sif::info << "AdcReport: ADC eng 15: " << this->adcEng15 << std::endl; } }; namespace notimpl { /** * @brief This class packages the space packet to perform the factory reset. The op parameter is * optional. * * @details: Without OP: All MRAM entries will be cleared. * OP = 0x01: Only the mirror entries will be wiped. * OP = 0x02: Only the circular entries will be wiped. */ class FactoryReset : public TcBase { public: enum class Op { CLEAR_ALL, MIRROR_ENTRIES, CIRCULAR_ENTRIES }; /** * @brief Constructor * * @param op */ FactoryReset(TcParams params) : TcBase(params, Apid::TMTC_MAN, 0x11, 1) {} ReturnValue_t buildPacket(Op op) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(op); return calcAndSetCrc(); } private: void initPacket(Op op) { size_t packetDataLen = 2; switch (op) { case Op::MIRROR_ENTRIES: payloadStart[0] = 1; packetDataLen = 3; break; case Op::CIRCULAR_ENTRIES: payloadStart[0] = 2; packetDataLen = 3; break; default: break; } spParams.setFullPayloadLen(packetDataLen); } }; /** * @brief This class creates the command to enable or disable the NVMs connected to the * supervisor. */ class EnableNvms : public TcBase { 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 */ EnableNvms(TcParams params) : TcBase(params, Apid::TMTC_MAN, 0x06, 2) {} ReturnValue_t buildPacket(uint8_t nvm01, uint8_t nvm3) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(nvm01, nvm3); return calcAndSetCrc(); } private: void initPacket(uint8_t nvm01, uint8_t nvm3) { payloadStart[0] = nvm01; payloadStart[1] = nvm3; } }; /** * @brief This class packages the space packet to wipe or dump parts of the MRAM. */ class MramCmd : public TcBase { public: enum class MramAction { WIPE, DUMP }; /** * @brief Constructor * * @param start Start address of the MRAM section to wipe or dump * @param stop End address of the MRAM section to wipe or dump * @param action Dump or wipe MRAM * * @note The content at the stop address is excluded from the dump or wipe operation. */ MramCmd(TcParams params) : TcBase(params, Apid::DATA_LOGGER) { setLenFromPayloadLen(6); } ReturnValue_t buildPacket(uint32_t start, uint32_t stop, MramAction action) { if (action == MramAction::WIPE) { setServiceId(static_cast(tc::DataLoggerServiceId::WIPE_MRAM)); } else if (action == MramAction::DUMP) { setServiceId(static_cast(tc::DataLoggerServiceId::DUMP_MRAM)); } else { sif::debug << "WipeMram: Invalid action specified"; } auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } initPacket(start, stop); return calcAndSetCrc(); } private: uint32_t start = 0; uint32_t stop = 0; void initPacket(uint32_t start, uint32_t stop) { uint8_t concatBuffer[6]; concatBuffer[0] = static_cast(start >> 16); concatBuffer[1] = static_cast(start >> 8); concatBuffer[2] = static_cast(start); concatBuffer[3] = static_cast(stop >> 16); concatBuffer[4] = static_cast(stop >> 8); concatBuffer[5] = static_cast(stop); std::memcpy(payloadStart, concatBuffer, sizeof(concatBuffer)); } }; /** * @brief This class creates the space packet to enable the auto TM generation */ class EnableAutoTm : public TcBase { public: EnableAutoTm(TcParams params) : TcBase(params) { spParams.setFullPayloadLen(PAYLOAD_LENGTH + 2); // spParams.creator.setApid(APID_AUTO_TM); // spParams.creator.setSeqCount(DEFAULT_SEQUENCE_COUNT); } ReturnValue_t buildPacket() { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } payloadStart[0] = ENABLE; return calcAndSetCrc(); } private: static const uint16_t PAYLOAD_LENGTH = 1; // length without CRC field static const uint8_t ENABLE = 1; }; /** * @brief This class creates the space packet to disable the auto TM generation */ class DisableAutoTm : public TcBase { public: DisableAutoTm(TcParams params) : TcBase(params) { spParams.setFullPayloadLen(PAYLOAD_LENGTH + 2); // spParams.creator.setApid(APID_AUTO_TM); // spParams.creator.setSeqCount(DEFAULT_SEQUENCE_COUNT); } ReturnValue_t buildPacket() { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } payloadStart[0] = DISABLE; return calcAndSetCrc(); } private: static const uint16_t PAYLOAD_LENGTH = 1; // length without CRC field static const uint8_t DISABLE = 0; }; /** * @brief This class creates the space packet to request the logging data from the supervisor */ class RequestLoggingData : public TcBase { public: /** * Subapid */ enum class Sa : uint8_t { REQUEST_COUNTERS = 1, /**< REQUEST_COUNTERS */ REQUEST_EVENT_BUFFERS = 2, /**< REQUEST_EVENT_BUFFERS */ CLEAR_COUNTERS = 3, /**< CLEAR_COUNTERS */ SET_LOGGING_TOPIC = 4 /**< SET_LOGGING_TOPIC */ }; RequestLoggingData(TcParams params) : TcBase(params) { spParams.setFullPayloadLen(PAYLOAD_LENGTH + 2); // spParams.creator.setApid(APID_REQUEST_LOGGING_DATA); // spParams.creator.setSeqCount(DEFAULT_SEQUENCE_COUNT); } /** * @param sa * @param tpc Topic * @return */ ReturnValue_t buildPacket(Sa sa, uint8_t tpc = 0) { auto res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } payloadStart[0] = static_cast(sa); payloadStart[1] = tpc; return calcAndSetCrc(); } private: static const uint16_t PAYLOAD_LENGTH = 2; // length without CRC field static const uint8_t TPC_OFFSET = 1; }; typedef struct { // The most significant bit of msec value is set to 0x80 to indicate that full // time and data information is transmitted, when the time has been synced with // the reference. If the time has not been synced with reference, then the most // significant bit is set to 0x00. Only the most significant bit is used for // this purpose (bit 15 of the field tm_msec) uint16_t tm_msec; // miliseconds 0-999; uint8_t tm_sec; // seconds after the minute, 0 to 60 // (0 - 60 allows for the occasional leap second) uint8_t tm_min; // minutes after the hour, 0 to 59 uint8_t tm_hour; // hours since midnight, 0 to 23 uint8_t tm_mday; // day of the month, 1 to 31 uint8_t tm_mon; // months 1 to 12 uint8_t tm_year; // years since 1900 } tas_time_t; } // namespace notimpl } // namespace supv #endif /* MISSION_DEVICES_DEVICEDEFINITIONS_PLOCSVPDEFINITIONS_H_ */