diff --git a/common/config/commonClassIds.h b/common/config/commonClassIds.h index 94d59602..827c316c 100644 --- a/common/config/commonClassIds.h +++ b/common/config/commonClassIds.h @@ -15,6 +15,7 @@ enum commonClassIds: uint8_t { STR_HANDLER, //STRH PLOC_MPSOC_HANDLER, //PLMP MPSOC_CMD, //MPCMD + DWLPWRON_CMD, //DWLPWRON MPSOC_TM, //MPTM PLOC_SUPERVISOR_HANDLER, //PLSV SUS_HANDLER, //SUSS diff --git a/fsfw b/fsfw index 1b7e0371..bac8b408 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 1b7e0371c337f9edae70f7bf1845a8a4854a6b8f +Subproject commit bac8b4088009a71afbb0225e634dabcbff0d9ec1 diff --git a/linux/devices/devicedefinitions/PlocMPSoCDefinitions.h b/linux/devices/devicedefinitions/PlocMPSoCDefinitions.h index ea51c0aa..45dff261 100644 --- a/linux/devices/devicedefinitions/PlocMPSoCDefinitions.h +++ b/linux/devices/devicedefinitions/PlocMPSoCDefinitions.h @@ -41,7 +41,7 @@ namespace apid { static const uint16_t TC_FLASHFOPEN = 0x119; static const uint16_t TC_FLASHFCLOSE = 0x11A; static const uint16_t TC_FLASHDELETE = 0x11C; - static const uint16_t TC_DOWLINK_PWR_OFF = 0x124; + static const uint16_t TC_DOWNLINK_PWR_OFF = 0x124; static const uint16_t TM_MEMORY_READ_REPORT = 0x404; static const uint16_t ACK_SUCCESS = 0x400; static const uint16_t ACK_FAILURE = 0x401; @@ -73,7 +73,13 @@ static const size_t MAX_COMMAND_SIZE = SpacePacket::PACKET_MAX_SIZE; static const size_t MAX_DATA_SIZE = 1016; /** - * @breif Abstract base class for TC space packet of MPSoC. + * The replay write sequence command has a maximum delay for the execution report which amounts to + * 30 seconds (60 cycles * 0.5 seconds). + */ +static const uint16_t TC_WRITE_SEQ_EXECUTION_DELAY = 60; + +/** + * @brief Abstract base class for TC space packet of MPSoC. */ class TcBase : public SpacePacket, public HasReturnvaluesIF { public: @@ -327,6 +333,28 @@ public: } }; +/** + * @brief Class to build flash write space packet. + */ +class TcFlashWrite : public TcBase { +public: + + TcFlashWrite(uint16_t sequenceCount) : + TcBase(apid::TC_FLASHWRITE, sequenceCount) { + } + + ReturnValue_t createPacket(uint8_t* writeData, uint32_t writeLen) { + if (writeLen > MAX_DATA_SIZE) { + sif::debug << "FlashWrite::createPacket: Command data too big" << std::endl; + return RETURN_FAILED; + } + std::memcpy(this->getPacketData(), writeData, writeLen); + addCrc(); + this->setPacketDataLength(static_cast(writeLen + CRC_SIZE - 1)); + return RETURN_OK; + } +}; + /** * @brief Class to help creation of flash delete command. */ @@ -341,33 +369,32 @@ public: ReturnValue_t result = RETURN_OK; size_t nameSize = filename.size(); std::memcpy(this->getPacketData(), filename.c_str(), nameSize); + this->setPacketDataLength(nameSize + CRC_SIZE - 1); result = addCrc(); if (result != RETURN_OK) { return result; } - this->setPacketDataLength(nameSize + CRC_SIZE - 1); return result; } }; /** - * @brief Class to build flash write space packet. + * @brief Class to build replay stop space packet. */ -class FlashWrite : public TcBase { +class TcReplayStop : public TcBase { public: - FlashWrite(uint16_t sequenceCount) : - TcBase(apid::TC_FLASHWRITE, sequenceCount) { + TcReplayStop(uint16_t sequenceCount) : + TcBase(apid::TC_REPLAY_STOP, sequenceCount) { } - ReturnValue_t createPacket(uint8_t* writeData, uint32_t writeLen) { - if (writeLen > MAX_DATA_SIZE) { - sif::debug << "FlashWrite::createPacket: Command data too big" << std::endl; - return RETURN_FAILED; + ReturnValue_t createPacket() { + ReturnValue_t result = RETURN_OK; + result = addCrc(); + if (result != RETURN_OK) { + return result; } - std::memcpy(this->getPacketData(), writeData, writeLen); - addCrc(); - this->setPacketDataLength(static_cast(writeLen + CRC_SIZE - 1)); + this->setPacketDataLength(static_cast(CRC_SIZE - 1)); return RETURN_OK; } }; @@ -391,7 +418,7 @@ protected: if (result != RETURN_OK) { return result; } - result = lengthData(commandData); + result = checkData(*commandData); if (result != RETURN_OK) { return result; } @@ -424,14 +451,14 @@ private: }; /** - * @brief This class helps to build the replay stop command. + * @brief This class helps to build downlink power on command. */ -class TcReplayStart: public TcBase { +class TcDownlinkPwrOn: public TcBase { public: /** * @brief Constructor */ - TcReplayStart(uint16_t sequenceCount) : TcBase(apid::TC_REPLAY_START, sequenceCount) { + TcDownlinkPwrOn(uint16_t sequenceCount) : TcBase(apid::TC_DOWNLINK_PWR_ON, sequenceCount) { } protected: @@ -442,7 +469,97 @@ protected: if (result != RETURN_OK) { return result; } - result = lengthData(commandData); + result = modeCheck(*commandData); + if (result != RETURN_OK) { + return result; + } + result = laneRateCheck(*(commandData + 1)); + if (result != RETURN_OK) { + return result; + } + std::memcpy(this->localData.fields.buffer, commandData, commandDataLen); + std::memcpy(this->localData.fields.buffer + commandDataLen, &MAX_AMPLITUDE, + sizeof(MAX_AMPLITUDE)); + this->setPacketDataLength(commandDataLen + sizeof(MAX_AMPLITUDE) + CRC_SIZE - 1); + return result; + } + +private: + + static const uint8_t INTERFACE_ID = CLASS_ID::DWLPWRON_CMD; + + //! [EXPORT] : [COMMENT] Received command has invalid JESD mode (valid modes are 0 - 5) + static const ReturnValue_t INVALID_MODE = MAKE_RETURN_CODE(0xE0); + //! [EXPORT] : [COMMENT] Received command has invalid lane rate (valid lane rate are 0 - 9) + static const ReturnValue_t INVALID_LANE_RATE = MAKE_RETURN_CODE(0xE1); + + static const size_t COMMAND_DATA_LENGTH = 2; + static const uint8_t MAX_MODE = 5; + static const uint8_t MAX_LANE_RATE = 9; + static const uint16_t MAX_AMPLITUDE = 0; + + ReturnValue_t lengthCheck(size_t commandDataLen) { + if (commandDataLen != COMMAND_DATA_LENGTH) { + sif::warning << "TcDownlinkPwrOn: Command has invalid length " << commandDataLen << std::endl; + return INVALID_LENGTH; + } + return RETURN_OK; + } + + ReturnValue_t modeCheck(uint8_t mode) { + if (mode > MAX_MODE) { + sif::warning << "TcDwonlinkPwrOn::modeCheck: Invalid JESD mode" << std::endl; + return INVALID_MODE; + } + return RETURN_OK; + } + + ReturnValue_t laneRateCheck(uint8_t laneRate) { + if (laneRate > MAX_LANE_RATE) { + sif::warning << "TcReplayStart::laneRateCheck: Invalid lane rate" << std::endl; + return INVALID_LANE_RATE; + } + return RETURN_OK; + } +}; + +/** + * @brief Class to build replay stop space packet. + */ +class TcDownlinkPwrOff : public TcBase { +public: + + TcDownlinkPwrOff(uint16_t sequenceCount) : + TcBase(apid::TC_DOWNLINK_PWR_OFF, sequenceCount) { + } + + ReturnValue_t createPacket() { + ReturnValue_t result = RETURN_OK; + result = addCrc(); + if (result != RETURN_OK) { + return result; + } + this->setPacketDataLength(static_cast(CRC_SIZE - 1)); + return RETURN_OK; + } +}; + + +/** + * @brief This class helps to build the replay start command. + */ +class TcReplayWriteSeq: public TcBase { +public: + /** + * @brief Constructor + */ + TcReplayWriteSeq(uint16_t sequenceCount) : TcBase(apid::TC_REPLAY_WRITE_SEQUENCE, sequenceCount) {} + +protected: + + ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) { + ReturnValue_t result = RETURN_OK; + result = lengthCheck(commandDataLen); if (result != RETURN_OK) { return result; } @@ -451,6 +568,17 @@ protected: return result; } +private: + + static const size_t USE_DECODING_LENGTH = 1; + + ReturnValue_t lengthCheck(size_t commandDataLen) { + if (commandDataLen > USE_DECODING_LENGTH + MAX_FILENAME_SIZE) { + sif::warning << "TcReplayWriteSeq: Command has invalid length " << commandDataLen << std::endl; + return INVALID_LENGTH; + } + return RETURN_OK; + } }; } diff --git a/linux/devices/ploc/PlocMPSoCHandler.cpp b/linux/devices/ploc/PlocMPSoCHandler.cpp index de808a0e..55822c31 100644 --- a/linux/devices/ploc/PlocMPSoCHandler.cpp +++ b/linux/devices/ploc/PlocMPSoCHandler.cpp @@ -142,6 +142,26 @@ ReturnValue_t PlocMPSoCHandler::buildCommandFromCommand( result = prepareTcFlashDelete(commandData, commandDataLen); break; } + case(mpsoc::TC_REPLAY_START): { + result = prepareTcReplayStart(commandData, commandDataLen); + break; + } + case(mpsoc::TC_REPLAY_STOP): { + result = prepareTcReplayStop(); + break; + } + case(mpsoc::TC_DOWNLINK_PWR_ON): { + result = prepareTcDownlinkPwrOn(commandData, commandDataLen); + break; + } + case(mpsoc::TC_DOWNLINK_PWR_OFF): { + result = prepareTcDownlinkPwrOff(); + break; + } + case(mpsoc::TC_REPLAY_WRITE_SEQUENCE): { + result = prepareTcReplayWriteSequence(commandData, commandDataLen); + break; + } default: sif::debug << "PlocMPSoCHandler::buildCommandFromCommand: Command not implemented" << std::endl; result = DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; @@ -161,6 +181,12 @@ ReturnValue_t PlocMPSoCHandler::buildCommandFromCommand( void PlocMPSoCHandler::fillCommandAndReplyMap() { this->insertInCommandMap(mpsoc::TC_MEM_WRITE); this->insertInCommandMap(mpsoc::TC_MEM_READ); + this->insertInCommandMap(mpsoc::TC_FLASHDELETE); + this->insertInCommandMap(mpsoc::TC_REPLAY_START); + this->insertInCommandMap(mpsoc::TC_REPLAY_STOP); + this->insertInCommandMap(mpsoc::TC_DOWNLINK_PWR_ON); + this->insertInCommandMap(mpsoc::TC_DOWNLINK_PWR_OFF); + this->insertInCommandMap(mpsoc::TC_REPLAY_WRITE_SEQUENCE); this->insertInReplyMap(mpsoc::ACK_REPORT, 1, nullptr, mpsoc::SIZE_ACK_REPORT); this->insertInReplyMap(mpsoc::EXE_REPORT, 3, nullptr, mpsoc::SIZE_EXE_REPORT); this->insertInReplyMap(mpsoc::TM_MEMORY_READ_REPORT, 2, nullptr, mpsoc::SIZE_TM_MEM_READ_REPORT); @@ -321,10 +347,64 @@ ReturnValue_t PlocMPSoCHandler::prepareTcReplayStart( sequenceCount--; return result; } - copyToCommandBuffer (&tcFlashDelete); + copyToCommandBuffer(&tcReplayStart); return RETURN_OK; } +ReturnValue_t PlocMPSoCHandler::prepareTcReplayStop() { + ReturnValue_t result = RETURN_OK; + sequenceCount++; + mpsoc::TcReplayStop tcReplayStop(sequenceCount); + result = tcReplayStop.createPacket(); + if (result != RETURN_OK) { + sequenceCount--; + return result; + } + copyToCommandBuffer(&tcReplayStop); + return RETURN_OK; +} + +ReturnValue_t PlocMPSoCHandler::prepareTcDownlinkPwrOn( + const uint8_t * commandData, size_t commandDataLen) { + ReturnValue_t result = RETURN_OK; + sequenceCount++; + mpsoc::TcDownlinkPwrOn tcDownlinkPwrOn(sequenceCount); + result = tcDownlinkPwrOn.createPacket(commandData, commandDataLen); + if (result != RETURN_OK) { + sequenceCount--; + return result; + } + copyToCommandBuffer(&tcDownlinkPwrOn); + return RETURN_OK; +} + +ReturnValue_t PlocMPSoCHandler::prepareTcDownlinkPwrOff() { + ReturnValue_t result = RETURN_OK; + sequenceCount++; + mpsoc::TcDownlinkPwrOff tcDownlinkPwrOff(sequenceCount); + result = tcDownlinkPwrOff.createPacket(); + if (result != RETURN_OK) { + sequenceCount--; + return result; + } + copyToCommandBuffer(&tcDownlinkPwrOff); + return RETURN_OK; +} + +ReturnValue_t PlocMPSoCHandler::prepareTcReplayWriteSequence(const uint8_t* commandData, + size_t commandDataLen) { + ReturnValue_t result = RETURN_OK; + sequenceCount++; + mpsoc::TcReplayWriteSeq tcReplayWriteSeq(sequenceCount); + result = tcReplayWriteSeq.createPacket(commandData, commandDataLen); + if (result != RETURN_OK) { + sequenceCount--; + return result; + } + copyToCommandBuffer(&tcReplayWriteSeq); + return RETURN_OK; +} + void PlocMPSoCHandler::copyToCommandBuffer(mpsoc::TcBase* tc) { if (tc == nullptr) { sif::debug << "PlocMPSoCHandler::copyToCommandBuffer: Invalid TC" << std::endl; @@ -458,6 +538,11 @@ ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator switch (command->first) { case mpsoc::TC_MEM_WRITE: case mpsoc::TC_FLASHDELETE: + case mpsoc::TC_REPLAY_START: + case mpsoc::TC_REPLAY_STOP: + case mpsoc::TC_DOWNLINK_PWR_ON: + case mpsoc::TC_DOWNLINK_PWR_OFF: + case mpsoc::TC_REPLAY_WRITE_SEQUENCE: enabledReplies = 2; break; case mpsoc::TC_MEM_READ: { @@ -493,6 +578,23 @@ ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator << " not in replyMap" << std::endl; } + switch(command->first) { + case mpsoc::TC_REPLAY_WRITE_SEQUENCE: { + DeviceReplyIter iter = deviceReplyMap.find(mpsoc::EXE_REPORT); + if (iter != deviceReplyMap.end()) { + // Overwrite delay cycles because replay write sequence command can required up to + // 30 seconds for execution + iter->second.delayCycles = mpsoc::TC_WRITE_SEQ_EXECUTION_DELAY; + } + else { + sif::debug << "PlocMPSoCHandler::enableReplyInReplyMap: Unknown reply id" << std::endl; + } + break; + } + default: + break; + } + return RETURN_OK; } diff --git a/linux/devices/ploc/PlocMPSoCHandler.h b/linux/devices/ploc/PlocMPSoCHandler.h index b6cc8914..5aa84dd7 100644 --- a/linux/devices/ploc/PlocMPSoCHandler.h +++ b/linux/devices/ploc/PlocMPSoCHandler.h @@ -131,9 +131,10 @@ private: ReturnValue_t prepareTcMemRead(const uint8_t * commandData, size_t commandDataLen); ReturnValue_t prepareTcFlashDelete(const uint8_t * commandData, size_t commandDataLen); ReturnValue_t prepareTcReplayStart(const uint8_t * commandData, size_t commandDataLen); -// ReturnValue_t prepareTcReplayStop(const uint8_t * commandData, size_t commandDataLen); -// ReturnValue_t prepareTcDownlinkPwrOff(const uint8_t * commandData, size_t commandDataLen); -// ReturnValue_t prepareTcDownlinkPwrOn(const uint8_t * commandData, size_t commandDataLen); + ReturnValue_t prepareTcReplayStop(); + ReturnValue_t prepareTcDownlinkPwrOn(const uint8_t * commandData, size_t commandDataLen); + ReturnValue_t prepareTcDownlinkPwrOff(); + ReturnValue_t prepareTcReplayWriteSequence(const uint8_t * commandData, size_t commandDataLen); /** * @brief Copies space packet into command buffer diff --git a/linux/devices/ploc/PlocMPSoCHelper.cpp b/linux/devices/ploc/PlocMPSoCHelper.cpp index 66f320b2..b1a65773 100644 --- a/linux/devices/ploc/PlocMPSoCHelper.cpp +++ b/linux/devices/ploc/PlocMPSoCHelper.cpp @@ -109,7 +109,7 @@ ReturnValue_t PlocMPSoCHelper::performFlashWrite() { } file.read(reinterpret_cast(tempData), dataLength); (*sequenceCount)++; - mpsoc::FlashWrite tc(*sequenceCount); + mpsoc::TcFlashWrite tc(*sequenceCount); tc.createPacket(tempData, dataLength); result = sendCommand(&tc); if (result != RETURN_OK) { diff --git a/tmtc b/tmtc index 9005ccab..1af59ea7 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 9005ccab3a07f569c45369f591c12b7613ffcac3 +Subproject commit 1af59ea7a53cd0cbbaf433710d99c6c27369a3d1