From aa2bfb7d0e6bec9cf7a2a1437923ab8f33c252a3 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 30 Apr 2024 15:14:22 +0200 Subject: [PATCH 1/9] Re-work MPSoC handler module --- CHANGELOG.md | 14 + CMakeLists.txt | 6 +- .../payload => archive}/PlocMpsocHandler.cpp | 40 +- {linux/payload => archive}/PlocMpsocHandler.h | 14 +- archive/PlocMpsocSpecialComHelperLegacy.cpp | 545 +++++++ archive/PlocMpsocSpecialComHelperLegacy.h | 200 +++ bsp_hosted/OBSWConfig.h.in | 1 + .../fsfwconfig/events/translateEvents.cpp | 2 +- .../fsfwconfig/objects/translateObjects.cpp | 7 +- bsp_hosted/objectFactory.cpp | 8 +- bsp_q7s/objectFactory.cpp | 26 +- common/config/eive/objects.h | 1 + common/config/eive/resultClassIds.h | 1 + fsfw | 2 +- generators/bsp_hosted_events.csv | 16 +- generators/bsp_hosted_objects.csv | 1 + generators/bsp_q7s_events.csv | 16 +- generators/bsp_q7s_objects.csv | 1 + generators/bsp_q7s_returnvalues.csv | 26 +- generators/events/translateEvents.cpp | 2 +- generators/objects/translateObjects.cpp | 7 +- linux/fsfwconfig/events/translateEvents.cpp | 2 +- linux/fsfwconfig/objects/translateObjects.cpp | 7 +- linux/payload/CMakeLists.txt | 4 +- linux/payload/FreshMpsocHandler.cpp | 1260 +++++++++++++++++ linux/payload/FreshMpsocHandler.h | 205 +++ linux/payload/FreshSupvHandler.cpp | 2 +- linux/payload/MpsocCommunication.cpp | 75 + linux/payload/MpsocCommunication.h | 44 + linux/payload/PlocMpsocSpecialComHelper.cpp | 145 +- linux/payload/PlocMpsocSpecialComHelper.h | 29 +- linux/payload/PlocSupvUartMan.cpp | 2 + linux/payload/SerialCommunicationHelper.cpp | 126 ++ linux/payload/SerialCommunicationHelper.h | 69 + linux/payload/SerialConfig.h | 70 + linux/payload/mpsocRetvals.h | 33 - linux/payload/plocMpsocHelpers.cpp | 63 +- linux/payload/plocMpsocHelpers.h | 451 ++++-- mission/pollingSeqTables.cpp | 13 +- scripts/q7s-cp.py | 7 +- tmtc | 2 +- unittest/CMakeLists.txt | 3 +- unittest/mpsocTests.cpp | 14 + 43 files changed, 3211 insertions(+), 351 deletions(-) rename {linux/payload => archive}/PlocMpsocHandler.cpp (97%) rename {linux/payload => archive}/PlocMpsocHandler.h (97%) create mode 100644 archive/PlocMpsocSpecialComHelperLegacy.cpp create mode 100644 archive/PlocMpsocSpecialComHelperLegacy.h create mode 100644 linux/payload/FreshMpsocHandler.cpp create mode 100644 linux/payload/FreshMpsocHandler.h create mode 100644 linux/payload/MpsocCommunication.cpp create mode 100644 linux/payload/MpsocCommunication.h create mode 100644 linux/payload/SerialCommunicationHelper.cpp create mode 100644 linux/payload/SerialCommunicationHelper.h create mode 100644 linux/payload/SerialConfig.h delete mode 100644 linux/payload/mpsocRetvals.h create mode 100644 unittest/mpsocTests.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index d58be5b2..b71b353b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,20 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +## Changed + +- Reworked MPSoC handler to be compatible to new MPSoC software image and use + new device handler base class. This should increase the reliability of the communication + significantly. +- MPSoC device modes IDLE, SNAPSHOT and REPLAY are now modelled using submodes. +- Commanding a submode the device is already in will not result in a completion failure + anymore. + +## Added + +- Added `VERIFY_BOOT` command for MPSoC. +- New command for MPSoC to store camera image in chunks. + # [v7.8.1] 2024-04-11 - Reverted fix for wrong order in quaternion multiplication for computation of the error quaternion. diff --git a/CMakeLists.txt b/CMakeLists.txt index 3132f5ed..ba7dd618 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,9 +9,9 @@ # ############################################################################## cmake_minimum_required(VERSION 3.13) -set(OBSW_VERSION_MAJOR 7) -set(OBSW_VERSION_MINOR 8) -set(OBSW_VERSION_REVISION 1) +set(OBSW_VERSION_MAJOR 8) +set(OBSW_VERSION_MINOR 0) +set(OBSW_VERSION_REVISION 0) # set(CMAKE_VERBOSE TRUE) diff --git a/linux/payload/PlocMpsocHandler.cpp b/archive/PlocMpsocHandler.cpp similarity index 97% rename from linux/payload/PlocMpsocHandler.cpp rename to archive/PlocMpsocHandler.cpp index 6df5a59b..ecb0bed8 100644 --- a/linux/payload/PlocMpsocHandler.cpp +++ b/archive/PlocMpsocHandler.cpp @@ -2,15 +2,15 @@ #include #include -#include - #include "OBSWConfig.h" #include "fsfw/datapool/PoolReadGuard.h" #include "fsfw/globalfunctions/CRC.h" +#include "fsfw/ipc/QueueFactory.h" #include "fsfw/parameters/HasParametersIF.h" PlocMpsocHandler::PlocMpsocHandler(object_id_t objectId, object_id_t uartComIFid, - CookieIF* comCookie, PlocMpsocSpecialComHelper* plocMPSoCHelper, + CookieIF* comCookie, + PlocMpsocSpecialComHelperLegacy* plocMPSoCHelper, Gpio uartIsolatorSwitch, object_id_t supervisorHandler) : DeviceHandlerBase(objectId, uartComIFid, comCookie), hkReport(this), @@ -54,24 +54,26 @@ ReturnValue_t PlocMpsocHandler::initialize() { return result; } result = manager->subscribeToEvent( - eventQueue->getId(), event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_WRITE_FAILED)); + eventQueue->getId(), + event::getEventId(PlocMpsocSpecialComHelperLegacy::MPSOC_FLASH_WRITE_FAILED)); if (result != returnvalue::OK) { return ObjectManagerIF::CHILD_INIT_FAILED; } result = manager->subscribeToEvent( eventQueue->getId(), - event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_WRITE_SUCCESSFUL)); + event::getEventId(PlocMpsocSpecialComHelperLegacy::MPSOC_FLASH_WRITE_SUCCESSFUL)); if (result != returnvalue::OK) { return ObjectManagerIF::CHILD_INIT_FAILED; } result = manager->subscribeToEvent( eventQueue->getId(), - event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_READ_SUCCESSFUL)); + event::getEventId(PlocMpsocSpecialComHelperLegacy::MPSOC_FLASH_READ_SUCCESSFUL)); if (result != returnvalue::OK) { return ObjectManagerIF::CHILD_INIT_FAILED; } result = manager->subscribeToEvent( - eventQueue->getId(), event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_READ_FAILED)); + eventQueue->getId(), + event::getEventId(PlocMpsocSpecialComHelperLegacy::MPSOC_FLASH_READ_FAILED)); if (result != returnvalue::OK) { return ObjectManagerIF::CHILD_INIT_FAILED; } @@ -139,7 +141,7 @@ ReturnValue_t PlocMpsocHandler::executeAction(ActionId_t actionId, MessageQueueI } if (specialComHelperExecuting) { - return MPSoCReturnValuesIF::MPSOC_HELPER_EXECUTING; + return mpsoc::MPSOC_HELPER_EXECUTING; } switch (actionId) { @@ -408,7 +410,7 @@ ReturnValue_t PlocMpsocHandler::scanForReply(const uint8_t* start, size_t remain sif::debug << "PlocMPSoCHandler::scanForReply: Reply has invalid APID 0x" << std::hex << std::setfill('0') << std::setw(2) << apid << std::dec << std::endl; *foundLen = remainingSize; - return MPSoCReturnValuesIF::INVALID_APID; + return mpsoc::INVALID_APID; } } @@ -445,7 +447,7 @@ ReturnValue_t PlocMpsocHandler::interpretDeviceReply(DeviceCommandId_t id, const } case (mpsoc::TM_FLASH_DIRECTORY_CONTENT): { result = verifyPacket(packet, foundPacketLen); - if (result == MPSoCReturnValuesIF::CRC_FAILURE) { + if (result == mpsoc::CRC_FAILURE) { sif::warning << "PLOC MPSoC: Flash directory content reply invalid CRC" << std::endl; } /** Send data to commanding queue */ @@ -557,7 +559,7 @@ ReturnValue_t PlocMpsocHandler::prepareTcMemRead(const uint8_t* commandData, ReturnValue_t PlocMpsocHandler::prepareTcFlashDelete(const uint8_t* commandData, size_t commandDataLen) { if (commandDataLen > config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE) { - return MPSoCReturnValuesIF::NAME_TOO_LONG; + return mpsoc::NAME_TOO_LONG; } ReturnValue_t result = returnvalue::OK; mpsoc::TcFlashDelete tcFlashDelete(spParams, sequenceCount); @@ -718,7 +720,7 @@ ReturnValue_t PlocMpsocHandler::finishTcPrep(mpsoc::TcBase& tcBase) { ReturnValue_t PlocMpsocHandler::verifyPacket(const uint8_t* start, size_t foundLen) { if (CRC::crc16ccitt(start, foundLen) != 0) { - return MPSoCReturnValuesIF::CRC_FAILURE; + return mpsoc::CRC_FAILURE; } return returnvalue::OK; } @@ -727,12 +729,12 @@ ReturnValue_t PlocMpsocHandler::handleAckReport(const uint8_t* data) { ReturnValue_t result = returnvalue::OK; result = verifyPacket(data, mpsoc::SIZE_ACK_REPORT); - if (result == MPSoCReturnValuesIF::CRC_FAILURE) { + if (result == mpsoc::CRC_FAILURE) { sif::warning << "PlocMPSoCHandler::handleAckReport: CRC failure" << std::endl; nextReplyId = mpsoc::NONE; replyRawReplyIfnotWiretapped(data, mpsoc::SIZE_ACK_REPORT); triggerEvent(MPSOC_HANDLER_CRC_FAILURE); - sendFailureReport(mpsoc::ACK_REPORT, MPSoCReturnValuesIF::CRC_FAILURE); + sendFailureReport(mpsoc::ACK_REPORT, mpsoc::CRC_FAILURE); disableAllReplies(); return IGNORE_REPLY_DATA; } @@ -771,7 +773,7 @@ ReturnValue_t PlocMpsocHandler::handleExecutionReport(const uint8_t* data) { ReturnValue_t result = returnvalue::OK; result = verifyPacket(data, mpsoc::SIZE_EXE_REPORT); - if (result == MPSoCReturnValuesIF::CRC_FAILURE) { + if (result == mpsoc::CRC_FAILURE) { sif::warning << "PlocMPSoCHandler::handleExecutionReport: CRC failure" << std::endl; nextReplyId = mpsoc::NONE; return result; @@ -792,9 +794,9 @@ ReturnValue_t PlocMpsocHandler::handleExecutionReport(const uint8_t* data) { uint16_t status = mpsoc::getStatusFromRawData(data); sif::warning << "MPSoC EXE Failure: " << mpsoc::getStatusString(status) << std::endl; triggerEvent(EXE_FAILURE, commandId, status); - sendFailureReport(mpsoc::EXE_REPORT, MPSoCReturnValuesIF::RECEIVED_EXE_FAILURE); + sendFailureReport(mpsoc::EXE_REPORT, mpsoc::RECEIVED_EXE_FAILURE); result = IGNORE_REPLY_DATA; - cmdDoneHandler(false, MPSoCReturnValuesIF::RECEIVED_EXE_FAILURE); + cmdDoneHandler(false, mpsoc::RECEIVED_EXE_FAILURE); break; } default: { @@ -810,7 +812,7 @@ ReturnValue_t PlocMpsocHandler::handleExecutionReport(const uint8_t* data) { ReturnValue_t PlocMpsocHandler::handleMemoryReadReport(const uint8_t* data) { ReturnValue_t result = returnvalue::OK; result = verifyPacket(data, tmMemReadReport.rememberRequestedSize); - if (result == MPSoCReturnValuesIF::CRC_FAILURE) { + if (result == mpsoc::CRC_FAILURE) { sif::warning << "PlocMPSoCHandler::handleMemoryReadReport: Memory read report has invalid crc" << std::endl; } @@ -1004,7 +1006,7 @@ ReturnValue_t PlocMpsocHandler::handleGetHkReport(const uint8_t* data) { ReturnValue_t PlocMpsocHandler::handleCamCmdRpt(const uint8_t* data) { ReturnValue_t result = verifyPacket(data, foundPacketLen); - if (result == MPSoCReturnValuesIF::CRC_FAILURE) { + if (result == mpsoc::CRC_FAILURE) { sif::warning << "PlocMPSoCHandler::handleCamCmdRpt: CRC failure" << std::endl; } SpacePacketReader packetReader(data, foundPacketLen); diff --git a/linux/payload/PlocMpsocHandler.h b/archive/PlocMpsocHandler.h similarity index 97% rename from linux/payload/PlocMpsocHandler.h rename to archive/PlocMpsocHandler.h index cdab5884..f3f24851 100644 --- a/linux/payload/PlocMpsocHandler.h +++ b/archive/PlocMpsocHandler.h @@ -1,23 +1,19 @@ #ifndef BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_ #define BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_ -#include -#include +#include #include #include #include -#include - #include "fsfw/action/CommandActionHelper.h" #include "fsfw/action/CommandsActionsIF.h" #include "fsfw/devicehandlers/DeviceHandlerBase.h" -#include "fsfw/ipc/QueueFactory.h" #include "fsfw/tmtcservices/SourceSequenceCounter.h" #include "fsfw_hal/linux/gpio/Gpio.h" #include "fsfw_hal/linux/serial/SerialComIF.h" -static constexpr bool DEBUG_MPSOC_COMMUNICATION = false; +static constexpr bool DEBUG_MPSOC_COMMUNICATION = true; /** * @brief This is the device handler for the MPSoC of the payload computer. @@ -48,7 +44,7 @@ class PlocMpsocHandler : public DeviceHandlerBase, public CommandsActionsIF { * @param supervisorHandler Object ID of the supervisor handler */ PlocMpsocHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF* comCookie, - PlocMpsocSpecialComHelper* plocMPSoCHelper, Gpio uartIsolatorSwitch, + PlocMpsocSpecialComHelperLegacy* plocMPSoCHelper, Gpio uartIsolatorSwitch, object_id_t supervisorHandler); virtual ~PlocMpsocHandler(); virtual ReturnValue_t initialize() override; @@ -171,7 +167,7 @@ class PlocMpsocHandler : public DeviceHandlerBase, public CommandsActionsIF { SerialComIF* uartComIf = nullptr; - PlocMpsocSpecialComHelper* specialComHelper = nullptr; + PlocMpsocSpecialComHelperLegacy* specialComHelper = nullptr; Gpio uartIsolatorSwitch; object_id_t supervisorHandler = 0; CommandActionHelper commandActionHelper; @@ -186,7 +182,7 @@ class PlocMpsocHandler : public DeviceHandlerBase, public CommandsActionsIF { }; TmMemReadReport tmMemReadReport; - Countdown cmdCountdown = Countdown(10000); + Countdown cmdCountdown = Countdown(15000); struct TelemetryBuffer { uint16_t length = 0; diff --git a/archive/PlocMpsocSpecialComHelperLegacy.cpp b/archive/PlocMpsocSpecialComHelperLegacy.cpp new file mode 100644 index 00000000..5dcaeb18 --- /dev/null +++ b/archive/PlocMpsocSpecialComHelperLegacy.cpp @@ -0,0 +1,545 @@ +#include +#include +#include +#include + +#include +#include + +#ifdef XIPHOS_Q7S +#include "bsp_q7s/fs/FilesystemHelper.h" +#endif + +#include "mission/utility/Timestamp.h" + +using namespace ploc; + +PlocMpsocSpecialComHelperLegacy::PlocMpsocSpecialComHelperLegacy(object_id_t objectId) + : SystemObject(objectId) { + spParams.buf = commandBuffer; + spParams.maxSize = sizeof(commandBuffer); +} + +PlocMpsocSpecialComHelperLegacy::~PlocMpsocSpecialComHelperLegacy() {} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::initialize() { +#ifdef XIPHOS_Q7S + sdcMan = SdCardManager::instance(); + if (sdcMan == nullptr) { + sif::warning << "PlocMPSoCHelper::initialize: Invalid SD Card Manager" << std::endl; + return returnvalue::FAILED; + } +#endif + return returnvalue::OK; +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::performOperation(uint8_t operationCode) { + ReturnValue_t result = returnvalue::OK; + semaphore.acquire(); + while (true) { +#if OBSW_THREAD_TRACING == 1 + trace::threadTrace(opCounter, "PLOC MPSOC Helper"); +#endif + switch (internalState) { + case InternalState::IDLE: { + semaphore.acquire(); + break; + } + case InternalState::FLASH_WRITE: { + result = performFlashWrite(); + if (result == returnvalue::OK) { + triggerEvent(MPSOC_FLASH_WRITE_SUCCESSFUL, sequenceCount->get()); + } else { + triggerEvent(MPSOC_FLASH_WRITE_FAILED, sequenceCount->get()); + } + internalState = InternalState::IDLE; + break; + } + case InternalState::FLASH_READ: { + result = performFlashRead(); + if (result == returnvalue::OK) { + triggerEvent(MPSOC_FLASH_READ_SUCCESSFUL, sequenceCount->get()); + } else { + triggerEvent(MPSOC_FLASH_READ_FAILED, sequenceCount->get()); + } + internalState = InternalState::IDLE; + break; + } + default: + sif::debug << "PlocMPSoCHelper::performOperation: Invalid state" << std::endl; + break; + } + } +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::setComIF( + DeviceCommunicationIF* communicationInterface_) { + uartComIF = dynamic_cast(communicationInterface_); + if (uartComIF == nullptr) { + sif::warning << "PlocMPSoCHelper::initialize: Invalid uart com if" << std::endl; + return returnvalue::FAILED; + } + return returnvalue::OK; +} + +void PlocMpsocSpecialComHelperLegacy::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; } + +void PlocMpsocSpecialComHelperLegacy::setSequenceCount(SourceSequenceCounter* sequenceCount_) { + sequenceCount = sequenceCount_; +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::startFlashWrite(std::string obcFile, + std::string mpsocFile) { + if (internalState != InternalState::IDLE) { + return returnvalue::FAILED; + } + ReturnValue_t result = startFlashReadOrWriteBase(std::move(obcFile), std::move(mpsocFile)); + if (result != returnvalue::OK) { + return result; + } + internalState = InternalState::FLASH_WRITE; + return semaphore.release(); +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::startFlashRead(std::string obcFile, + std::string mpsocFile, + size_t readFileSize) { + if (internalState != InternalState::IDLE) { + return returnvalue::FAILED; + } + ReturnValue_t result = startFlashReadOrWriteBase(std::move(obcFile), std::move(mpsocFile)); + if (result != returnvalue::OK) { + return result; + } + flashReadAndWrite.totalReadSize = readFileSize; + internalState = InternalState::FLASH_READ; + return semaphore.release(); +} + +void PlocMpsocSpecialComHelperLegacy::resetHelper() { + spParams.buf = commandBuffer; + terminate = false; + uartComIF->flushUartRxBuffer(comCookie); +} + +void PlocMpsocSpecialComHelperLegacy::stopProcess() { terminate = true; } + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::performFlashWrite() { + ReturnValue_t result = returnvalue::OK; + std::ifstream file(flashReadAndWrite.obcFile, std::ifstream::binary); + if (file.bad()) { + return returnvalue::FAILED; + } + result = flashfopen(mpsoc::FileAccessModes::WRITE | mpsoc::FileAccessModes::OPEN_ALWAYS); + if (result != returnvalue::OK) { + return result; + } + // Set position of next character to end of file input stream + file.seekg(0, file.end); + // tellg returns position of character in input stream + size_t remainingSize = file.tellg(); + size_t dataLength = 0; + size_t bytesRead = 0; + while (remainingSize > 0) { + if (terminate) { + return returnvalue::OK; + } + // The minus 4 is necessary for unknown reasons. Maybe some bug in the ILH software? + if (remainingSize > mpsoc::MAX_FLASH_WRITE_DATA_SIZE - 4) { + dataLength = mpsoc::MAX_FLASH_WRITE_DATA_SIZE - 4; + } else { + dataLength = remainingSize; + } + if (file.bad() or not file.is_open()) { + return FILE_WRITE_ERROR; + } + file.seekg(bytesRead, file.beg); + file.read(reinterpret_cast(fileBuf.data()), dataLength); + bytesRead += dataLength; + remainingSize -= dataLength; + mpsoc::TcFlashWrite tc(spParams, *sequenceCount); + result = tc.setPayload(fileBuf.data(), dataLength); + if (result != returnvalue::OK) { + return result; + } + result = tc.finishPacket(); + if (result != returnvalue::OK) { + return result; + } + (*sequenceCount)++; + result = handlePacketTransmissionNoReply(tc); + if (result != returnvalue::OK) { + return result; + } + } + result = flashfclose(); + if (result != returnvalue::OK) { + return result; + } + return result; +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::performFlashRead() { + std::error_code e; + std::ofstream ofile(flashReadAndWrite.obcFile, std::ios::trunc | std::ios::binary); + if (ofile.bad()) { + return returnvalue::FAILED; + } + ReturnValue_t result = flashfopen(mpsoc::FileAccessModes::READ); + if (result != returnvalue::OK) { + std::filesystem::remove(flashReadAndWrite.obcFile, e); + return result; + } + size_t readSoFar = 0; + size_t nextReadSize = mpsoc::MAX_FLASH_READ_DATA_SIZE; + while (readSoFar < flashReadAndWrite.totalReadSize) { + if (terminate) { + std::filesystem::remove(flashReadAndWrite.obcFile, e); + return returnvalue::OK; + } + nextReadSize = mpsoc::MAX_FLASH_READ_DATA_SIZE; + if (flashReadAndWrite.totalReadSize - readSoFar < mpsoc::MAX_FLASH_READ_DATA_SIZE) { + nextReadSize = flashReadAndWrite.totalReadSize - readSoFar; + } + if (ofile.bad() or not ofile.is_open()) { + std::filesystem::remove(flashReadAndWrite.obcFile, e); + return FILE_READ_ERROR; + } + mpsoc::TcFlashRead flashReadRequest(spParams, *sequenceCount); + result = flashReadRequest.setPayload(nextReadSize); + if (result != returnvalue::OK) { + std::filesystem::remove(flashReadAndWrite.obcFile, e); + return result; + } + result = flashReadRequest.finishPacket(); + if (result != returnvalue::OK) { + std::filesystem::remove(flashReadAndWrite.obcFile, e); + return result; + } + (*sequenceCount)++; + result = handlePacketTransmissionFlashRead(flashReadRequest, ofile, nextReadSize); + if (result != returnvalue::OK) { + std::filesystem::remove(flashReadAndWrite.obcFile, e); + return result; + } + readSoFar += nextReadSize; + } + result = flashfclose(); + if (result != returnvalue::OK) { + return result; + } + return result; +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::flashfopen(uint8_t mode) { + spParams.buf = commandBuffer; + mpsoc::FlashFopen flashFopen(spParams, *sequenceCount); + ReturnValue_t result = flashFopen.setPayload(flashReadAndWrite.mpsocFile, mode); + if (result != returnvalue::OK) { + return result; + } + result = flashFopen.finishPacket(); + if (result != returnvalue::OK) { + return result; + } + (*sequenceCount)++; + result = handlePacketTransmissionNoReply(flashFopen); + if (result != returnvalue::OK) { + return result; + } + return returnvalue::OK; +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::flashfclose() { + spParams.buf = commandBuffer; + mpsoc::FlashFclose flashFclose(spParams, *sequenceCount); + ReturnValue_t result = flashFclose.finishPacket(); + if (result != returnvalue::OK) { + return result; + } + (*sequenceCount)++; + result = handlePacketTransmissionNoReply(flashFclose); + if (result != returnvalue::OK) { + return result; + } + return result; +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::handlePacketTransmissionFlashRead( + mpsoc::TcFlashRead& tc, std::ofstream& ofile, size_t expectedReadLen) { + ReturnValue_t result = sendCommand(tc); + if (result != returnvalue::OK) { + return result; + } + result = handleAck(); + if (result != returnvalue::OK) { + return result; + } + result = handleTmReception(); + if (result != returnvalue::OK) { + return result; + } + + // We have the nominal case where the flash read report appears first, or the case where we + // get an EXE failure immediately. + if (spReader.getApid() == mpsoc::apid::TM_FLASH_READ_REPORT) { + result = handleFlashReadReply(ofile, expectedReadLen); + if (result != returnvalue::OK) { + return result; + } + return handleExe(); + } else if (spReader.getApid() == mpsoc::apid::EXE_FAILURE) { + handleExeFailure(); + } else { + triggerEvent(MPSOC_EXE_INVALID_APID, spReader.getApid(), static_cast(internalState)); + sif::warning << "PLOC MPSoC: Expected execution report " + << "but received space packet with apid " << std::hex << spReader.getApid() + << std::endl; + } + return returnvalue::FAILED; +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::handlePacketTransmissionNoReply(ploc::SpTcBase& tc) { + ReturnValue_t result = sendCommand(tc); + if (result != returnvalue::OK) { + return result; + } + result = handleAck(); + if (result != returnvalue::OK) { + return result; + } + return handleExe(); +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::sendCommand(ploc::SpTcBase& tc) { + ReturnValue_t result = returnvalue::OK; + result = uartComIF->sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen()); + if (result != returnvalue::OK) { + sif::warning << "PlocMPSoCHelper::sendCommand: Failed to send command" << std::endl; + triggerEvent(MPSOC_SENDING_COMMAND_FAILED, result, static_cast(internalState)); + return result; + } + return result; +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::handleAck() { + ReturnValue_t result = returnvalue::OK; + result = handleTmReception(); + if (result != returnvalue::OK) { + return result; + } + result = checkReceivedTm(); + if (result != returnvalue::OK) { + return result; + } + uint16_t apid = spReader.getApid(); + if (apid != mpsoc::apid::ACK_SUCCESS) { + handleAckApidFailure(spReader); + return returnvalue::FAILED; + } + return returnvalue::OK; +} + +void PlocMpsocSpecialComHelperLegacy::handleAckApidFailure(const ploc::SpTmReader& reader) { + uint16_t apid = reader.getApid(); + if (apid == mpsoc::apid::ACK_FAILURE) { + uint16_t status = mpsoc::getStatusFromRawData(reader.getFullData()); + sif::warning << "PLOC MPSoC ACK Failure: " << mpsoc::getStatusString(status) << std::endl; + triggerEvent(MPSOC_ACK_FAILURE_REPORT, static_cast(internalState), status); + } else { + triggerEvent(MPSOC_ACK_INVALID_APID, apid, static_cast(internalState)); + sif::warning << "PlocMPSoCHelper::handleAckApidFailure: Expected acknowledgement report " + << "but received space packet with apid " << std::hex << apid << std::endl; + } +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::handleExe() { + ReturnValue_t result = returnvalue::OK; + + result = handleTmReception(); + if (result != returnvalue::OK) { + return result; + } + result = checkReceivedTm(); + if (result != returnvalue::OK) { + return result; + } + uint16_t apid = spReader.getApid(); + if (apid == mpsoc::apid::EXE_FAILURE) { + handleExeFailure(); + return returnvalue::FAILED; + } else if (apid != mpsoc::apid::EXE_SUCCESS) { + triggerEvent(MPSOC_EXE_INVALID_APID, apid, static_cast(internalState)); + sif::warning << "PLOC MPSoC: Expected execution report " + << "but received space packet with apid " << std::hex << apid << std::endl; + } + return returnvalue::OK; +} + +void PlocMpsocSpecialComHelperLegacy::handleExeFailure() { + uint16_t status = mpsoc::getStatusFromRawData(spReader.getFullData()); + sif::warning << "PLOC MPSoC EXE Failure: " << mpsoc::getStatusString(status) << std::endl; + triggerEvent(MPSOC_EXE_FAILURE_REPORT, static_cast(internalState)); +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::handleTmReception() { + ReturnValue_t result = returnvalue::OK; + tmCountdown.resetTimer(); + size_t readBytes = 0; + size_t currentBytes = 0; + uint32_t usleepDelay = 5; + size_t fullPacketLen = 0; + while (true) { + if (tmCountdown.hasTimedOut()) { + triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs()); + return returnvalue::FAILED; + } + result = receive(tmBuf.data() + readBytes, 6, ¤tBytes); + if (result != returnvalue::OK) { + return result; + } + spReader.setReadOnlyData(tmBuf.data(), tmBuf.size()); + fullPacketLen = spReader.getFullPacketLen(); + readBytes += currentBytes; + if (readBytes == 6) { + break; + } + usleep(usleepDelay); + if (usleepDelay < 200000) { + usleepDelay *= 4; + } + } + while (true) { + if (tmCountdown.hasTimedOut()) { + triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs()); + return returnvalue::FAILED; + } + result = receive(tmBuf.data() + readBytes, fullPacketLen - readBytes, ¤tBytes); + readBytes += currentBytes; + if (fullPacketLen == readBytes) { + break; + } + usleep(usleepDelay); + if (usleepDelay < 200000) { + usleepDelay *= 4; + } + } + // arrayprinter::print(tmBuf.data(), readBytes); + return result; +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::handleFlashReadReply(std::ofstream& ofile, + size_t expectedReadLen) { + ReturnValue_t result = checkReceivedTm(); + if (result != returnvalue::OK) { + return result; + } + uint16_t apid = spReader.getApid(); + if (apid != mpsoc::apid::TM_FLASH_READ_REPORT) { + triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_APID_ERROR); + sif::warning << "PLOC MPSoC Flash Read: Unexpected APID" << std::endl; + return result; + } + const uint8_t* packetData = spReader.getPacketData(); + size_t deserDummy = spReader.getPacketDataLen() - mpsoc::CRC_SIZE; + uint32_t receivedReadLen = 0; + // I think this is buggy, weird stuff in the short name field. + // std::string receivedShortName = std::string(reinterpret_cast(packetData), 12); + // if (receivedShortName != flashReadAndWrite.mpsocFile.substr(0, 11)) { + // sif::warning << "PLOC MPSoC Flash Read: Missmatch between request file name and " + // "received file name" + // << std::endl; + // triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_FILENAME_ERROR); + // return returnvalue::FAILED; + // } + packetData += 12; + result = SerializeAdapter::deSerialize(&receivedReadLen, &packetData, &deserDummy, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + if (receivedReadLen != expectedReadLen) { + sif::warning << "PLOC MPSoC Flash Read: Missmatch between request read length and " + "received read length" + << std::endl; + triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_READLEN_ERROR); + return returnvalue::FAILED; + } + ofile.write(reinterpret_cast(packetData), receivedReadLen); + return returnvalue::OK; +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::fileCheck(std::string obcFile) { +#ifdef XIPHOS_Q7S + ReturnValue_t result = FilesystemHelper::checkPath(obcFile); + if (result != returnvalue::OK) { + return result; + } +#elif defined(TE0720_1CFA) + if (not std::filesystem::exists(obcFile)) { + sif::warning << "PlocMPSoCHelper::startFlashWrite: File " << obcFile << "does not exist" + << std::endl; + return returnvalue::FAILED; + } +#endif + return returnvalue::OK; +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::startFlashReadOrWriteBase(std::string obcFile, + std::string mpsocFile) { + ReturnValue_t result = fileCheck(obcFile); + if (result != returnvalue::OK) { + return result; + } + + flashReadAndWrite.obcFile = std::move(obcFile); + flashReadAndWrite.mpsocFile = std::move(mpsocFile); + resetHelper(); + return returnvalue::OK; +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::checkReceivedTm() { + ReturnValue_t result = spReader.checkSize(); + if (result != returnvalue::OK) { + sif::error << "PLOC MPSoC: Size check on received TM failed" << std::endl; + triggerEvent(MPSOC_TM_SIZE_ERROR); + return result; + } + result = spReader.checkCrc(); + if (result != returnvalue::OK) { + sif::warning << "PLOC MPSoC: CRC check failed" << std::endl; + triggerEvent(MPSOC_TM_CRC_MISSMATCH, *sequenceCount); + return result; + } + uint16_t recvSeqCnt = spReader.getSequenceCount(); + if (recvSeqCnt != *sequenceCount) { + triggerEvent(MPSOC_HELPER_SEQ_CNT_MISMATCH, *sequenceCount, recvSeqCnt); + *sequenceCount = recvSeqCnt; + } + // This sequence count ping pong does not make any sense but it is how the MPSoC expects it. + (*sequenceCount)++; + return returnvalue::OK; +} + +ReturnValue_t PlocMpsocSpecialComHelperLegacy::receive(uint8_t* data, size_t requestBytes, + size_t* readBytes) { + ReturnValue_t result = returnvalue::OK; + uint8_t* buffer = nullptr; + result = uartComIF->requestReceiveMessage(comCookie, requestBytes); + if (result != returnvalue::OK) { + sif::warning << "PlocMPSoCHelper::receive: Failed to request reply" << std::endl; + triggerEvent(MPSOC_HELPER_REQUESTING_REPLY_FAILED, result, + static_cast(static_cast(internalState))); + return returnvalue::FAILED; + } + result = uartComIF->readReceivedMessage(comCookie, &buffer, readBytes); + if (result != returnvalue::OK) { + sif::warning << "PlocMPSoCHelper::receive: Failed to read received message" << std::endl; + triggerEvent(MPSOC_HELPER_READING_REPLY_FAILED, result, static_cast(internalState)); + return returnvalue::FAILED; + } + if (*readBytes > 0) { + std::memcpy(data, buffer, *readBytes); + } + return result; +} diff --git a/archive/PlocMpsocSpecialComHelperLegacy.h b/archive/PlocMpsocSpecialComHelperLegacy.h new file mode 100644 index 00000000..e3d5370f --- /dev/null +++ b/archive/PlocMpsocSpecialComHelperLegacy.h @@ -0,0 +1,200 @@ +#ifndef BSP_Q7S_DEVICES_PLOCMPSOCHELPER_H_ +#define BSP_Q7S_DEVICES_PLOCMPSOCHELPER_H_ + +#include +#include + +#include + +#include "OBSWConfig.h" +#include "fsfw/devicehandlers/CookieIF.h" +#include "fsfw/objectmanager/SystemObject.h" +#include "fsfw/osal/linux/BinarySemaphore.h" +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/tasks/ExecutableObjectIF.h" +#include "fsfw/tmtcservices/SourceSequenceCounter.h" +#include "fsfw_hal/linux/serial/SerialComIF.h" +#ifdef XIPHOS_Q7S +#include "bsp_q7s/fs/SdCardManager.h" +#endif + +/** + * @brief Helper class for MPSoC of PLOC intended to accelerate large data transfers between + * MPSoC and OBC. + * @author J. Meier + */ +class PlocMpsocSpecialComHelperLegacy : public SystemObject, public ExecutableObjectIF { + public: + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_MPSOC_HELPER; + + //! [EXPORT] : [COMMENT] Flash write fails + static const Event MPSOC_FLASH_WRITE_FAILED = MAKE_EVENT(0, severity::LOW); + //! [EXPORT] : [COMMENT] Flash write successful + static const Event MPSOC_FLASH_WRITE_SUCCESSFUL = MAKE_EVENT(1, severity::INFO); + //! [EXPORT] : [COMMENT] Communication interface returned failure when trying to send the command + //! to the MPSoC + //! P1: Return value returned by the communication interface sendMessage function + //! P2: Internal state of MPSoC helper + static const Event MPSOC_SENDING_COMMAND_FAILED = MAKE_EVENT(2, severity::LOW); + //! [EXPORT] : [COMMENT] Request receive message of communication interface failed + //! P1: Return value returned by the communication interface requestReceiveMessage function + //! P2: Internal state of MPSoC helper + static const Event MPSOC_HELPER_REQUESTING_REPLY_FAILED = MAKE_EVENT(3, severity::LOW); + //! [EXPORT] : [COMMENT] Reading receive message of communication interface failed + //! P1: Return value returned by the communication interface readingReceivedMessage function + //! P2: Internal state of MPSoC helper + static const Event MPSOC_HELPER_READING_REPLY_FAILED = MAKE_EVENT(4, severity::LOW); + //! [EXPORT] : [COMMENT] Did not receive acknowledgment report + //! P1: Number of bytes missing + //! P2: Internal state of MPSoC helper + static const Event MPSOC_MISSING_ACK = MAKE_EVENT(5, severity::LOW); + //! [EXPORT] : [COMMENT] Did not receive execution report + //! P1: Number of bytes missing + //! P2: Internal state of MPSoC helper + static const Event MPSOC_MISSING_EXE = MAKE_EVENT(6, severity::LOW); + //! [EXPORT] : [COMMENT] Received acknowledgment failure report + //! P1: Internal state of MPSoC + static const Event MPSOC_ACK_FAILURE_REPORT = MAKE_EVENT(7, severity::LOW); + //! [EXPORT] : [COMMENT] Received execution failure report + //! P1: Internal state of MPSoC + static const Event MPSOC_EXE_FAILURE_REPORT = MAKE_EVENT(8, severity::LOW); + //! [EXPORT] : [COMMENT] Expected acknowledgment report but received space packet with other apid + //! P1: Apid of received space packet + //! P2: Internal state of MPSoC + static const Event MPSOC_ACK_INVALID_APID = MAKE_EVENT(9, severity::LOW); + //! [EXPORT] : [COMMENT] Expected execution report but received space packet with other apid + //! P1: Apid of received space packet + //! P2: Internal state of MPSoC + static const Event MPSOC_EXE_INVALID_APID = MAKE_EVENT(10, severity::LOW); + //! [EXPORT] : [COMMENT] Received sequence count does not match expected sequence count + //! P1: Expected sequence count + //! P2: Received sequence count + static const Event MPSOC_HELPER_SEQ_CNT_MISMATCH = MAKE_EVENT(11, severity::LOW); + static const Event MPSOC_TM_SIZE_ERROR = MAKE_EVENT(12, severity::LOW); + static const Event MPSOC_TM_CRC_MISSMATCH = MAKE_EVENT(13, severity::LOW); + static const Event MPSOC_FLASH_READ_PACKET_ERROR = MAKE_EVENT(14, severity::LOW); + static const Event MPSOC_FLASH_READ_FAILED = MAKE_EVENT(15, severity::LOW); + static const Event MPSOC_FLASH_READ_SUCCESSFUL = MAKE_EVENT(16, severity::INFO); + static const Event MPSOC_READ_TIMEOUT = MAKE_EVENT(17, severity::LOW); + + enum FlashReadErrorType : uint32_t { + FLASH_READ_APID_ERROR = 0, + FLASH_READ_FILENAME_ERROR = 1, + FLASH_READ_READLEN_ERROR = 2 + }; + + PlocMpsocSpecialComHelperLegacy(object_id_t objectId); + virtual ~PlocMpsocSpecialComHelperLegacy(); + + ReturnValue_t initialize() override; + ReturnValue_t performOperation(uint8_t operationCode = 0) override; + + ReturnValue_t setComIF(DeviceCommunicationIF* communicationInterface_); + void setComCookie(CookieIF* comCookie_); + + /** + * @brief Starts flash write sequence + * + * @param obcFile File where to read from the data + * @param mpsocFile The file of the MPSoC where should be written to + * + * @return returnvalue::OK if successful, otherwise error return value + */ + ReturnValue_t startFlashWrite(std::string obcFile, std::string mpsocFile); + /** + * + * @param obcFile Full target file name on OBC + * @param mpsocFile The file on the MPSoC which should be copied ot the OBC + * @param readFileSize The size of the file on the MPSoC. + * @return + */ + ReturnValue_t startFlashRead(std::string obcFile, std::string mpsocFile, size_t readFileSize); + + /** + * @brief Can be used to interrupt a running data transfer. + */ + void stopProcess(); + + /** + * @brief Sets the sequence count object responsible for the sequence count handling + */ + void setSequenceCount(SourceSequenceCounter* sequenceCount_); + + private: + static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_MPSOC_HELPER; + + //! [EXPORT] : [COMMENT] File error occured for file transfers from OBC to the MPSoC. + static const ReturnValue_t FILE_WRITE_ERROR = MAKE_RETURN_CODE(0xA0); + //! [EXPORT] : [COMMENT] File error occured for file transfers from MPSoC to OBC. + static const ReturnValue_t FILE_READ_ERROR = MAKE_RETURN_CODE(0xA1); + + // Maximum number of times the communication interface retries polling data from the reply + // buffer + static const int RETRIES = 10000; + + struct FlashInfo { + std::string obcFile; + std::string mpsocFile; + }; + + struct FlashRead : public FlashInfo { + size_t totalReadSize = 0; + }; + + struct FlashRead flashReadAndWrite; +#if OBSW_THREAD_TRACING == 1 + uint32_t opCounter = 0; +#endif + + enum class InternalState { IDLE, FLASH_WRITE, FLASH_READ }; + + InternalState internalState = InternalState::IDLE; + + BinarySemaphore semaphore; +#ifdef XIPHOS_Q7S + SdCardManager* sdcMan = nullptr; +#endif + uint8_t commandBuffer[mpsoc::MAX_COMMAND_SIZE]; + SpacePacketCreator creator; + ploc::SpTcParams spParams = ploc::SpTcParams(creator); + + Countdown tmCountdown = Countdown(5000); + + std::array fileBuf{}; + std::array tmBuf{}; + + bool terminate = false; + + /** + * Communication interface of MPSoC responsible for low level access. Must be set by the + * MPSoC Handler. + */ + SerialComIF* uartComIF = nullptr; + // Communication cookie. Must be set by the MPSoC Handler + CookieIF* comCookie = nullptr; + // Sequence count, must be set by Ploc MPSoC Handler + SourceSequenceCounter* sequenceCount = nullptr; + ploc::SpTmReader spReader; + + void resetHelper(); + ReturnValue_t performFlashWrite(); + ReturnValue_t performFlashRead(); + ReturnValue_t flashfopen(uint8_t accessMode); + ReturnValue_t flashfclose(); + ReturnValue_t handlePacketTransmissionNoReply(ploc::SpTcBase& tc); + ReturnValue_t handlePacketTransmissionFlashRead(mpsoc::TcFlashRead& tc, std::ofstream& ofile, + size_t expectedReadLen); + ReturnValue_t handleFlashReadReply(std::ofstream& ofile, size_t expectedReadLen); + ReturnValue_t sendCommand(ploc::SpTcBase& tc); + ReturnValue_t receive(uint8_t* data, size_t requestBytes, size_t* readBytes); + ReturnValue_t handleAck(); + ReturnValue_t handleExe(); + ReturnValue_t startFlashReadOrWriteBase(std::string obcFile, std::string mpsocFile); + ReturnValue_t fileCheck(std::string obcFile); + void handleAckApidFailure(const ploc::SpTmReader& reader); + void handleExeFailure(); + ReturnValue_t handleTmReception(); + ReturnValue_t checkReceivedTm(); +}; + +#endif /* BSP_Q7S_DEVICES_PLOCMPSOCHELPER_H_ */ diff --git a/bsp_hosted/OBSWConfig.h.in b/bsp_hosted/OBSWConfig.h.in index 6e525e5a..41515578 100644 --- a/bsp_hosted/OBSWConfig.h.in +++ b/bsp_hosted/OBSWConfig.h.in @@ -48,6 +48,7 @@ #define OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP 1 #define OBSW_PRINT_MISSED_DEADLINES 1 +#define OBSW_MPSOC_JTAG_BOOT 0 #define OBSW_SYRLINKS_SIMULATED 1 #define OBSW_ADD_TEST_CODE 0 #define OBSW_ADD_TEST_TASK 0 diff --git a/bsp_hosted/fsfwconfig/events/translateEvents.cpp b/bsp_hosted/fsfwconfig/events/translateEvents.cpp index 0e05842a..8d67f14d 100644 --- a/bsp_hosted/fsfwconfig/events/translateEvents.cpp +++ b/bsp_hosted/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 324 translations. * @details - * Generated on: 2024-04-10 11:49:35 + * Generated on: 2024-04-17 11:22:10 */ #include "translateEvents.h" diff --git a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp index 37068dd1..c536b709 100644 --- a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp +++ b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp @@ -1,8 +1,8 @@ /** * @brief Auto-generated object translation file. * @details - * Contains 175 translations. - * Generated on: 2024-04-10 11:49:35 + * Contains 176 translations. + * Generated on: 2024-04-17 11:22:10 */ #include "translateObjects.h" @@ -65,6 +65,7 @@ const char *PTME_VC3_CFDP_TM_STRING = "PTME_VC3_CFDP_TM"; const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER"; const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER"; const char *PLOC_SUPERVISOR_HELPER_STRING = "PLOC_SUPERVISOR_HELPER"; +const char *PLOC_MPSOC_COMMUNICATION_STRING = "PLOC_MPSOC_COMMUNICATION"; const char *SCEX_STRING = "SCEX"; const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER"; const char *HEATER_HANDLER_STRING = "HEATER_HANDLER"; @@ -302,6 +303,8 @@ const char *translateObject(object_id_t object) { return PLOC_SUPERVISOR_HANDLER_STRING; case 0x44330017: return PLOC_SUPERVISOR_HELPER_STRING; + case 0x44330018: + return PLOC_MPSOC_COMMUNICATION_STRING; case 0x44330032: return SCEX_STRING; case 0x444100A2: diff --git a/bsp_hosted/objectFactory.cpp b/bsp_hosted/objectFactory.cpp index 30a4154b..1ffc6625 100644 --- a/bsp_hosted/objectFactory.cpp +++ b/bsp_hosted/objectFactory.cpp @@ -39,8 +39,6 @@ #include "devices/gpioIds.h" #include "fsfw_hal/linux/gpio/Gpio.h" #include "linux/payload/FreshSupvHandler.h" -#include "linux/payload/PlocMpsocHandler.h" -#include "linux/payload/PlocMpsocSpecialComHelper.h" #include "linux/payload/PlocSupvUartMan.h" #include "test/gpio/DummyGpioIF.h" #endif @@ -79,7 +77,10 @@ void ObjectFactory::produce(void* args) { switcherList.emplace_back(initVal); } dummySwitcher->setInitialSwitcherList(switcherList); + #ifdef PLATFORM_UNIX + // Obsolete dev handler.. + /* new SerialComIF(objects::UART_COM_IF); #if OBSW_ADD_PLOC_MPSOC == 1 std::string mpscoDev = ""; @@ -90,7 +91,8 @@ void ObjectFactory::produce(void* args) { new PlocMpsocHandler(objects::PLOC_MPSOC_HANDLER, objects::UART_COM_IF, mpsocCookie, plocMpsocHelper, Gpio(gpioIds::ENABLE_MPSOC_UART, dummyGpioIF), objects::PLOC_SUPERVISOR_HANDLER); -#endif /* OBSW_ADD_PLOC_MPSOC == 1 */ +#endif // OBSW_ADD_PLOC_MPSOC == 1 + */ #if OBSW_ADD_PLOC_SUPERVISOR == 1 std::string plocSupvString = "/dev/ploc_supv"; auto supervisorCookie = diff --git a/bsp_q7s/objectFactory.cpp b/bsp_q7s/objectFactory.cpp index ccd52bd2..f9ae8dc6 100644 --- a/bsp_q7s/objectFactory.cpp +++ b/bsp_q7s/objectFactory.cpp @@ -10,8 +10,9 @@ #include #include #include +#include +#include #include -#include #include #include #include @@ -47,6 +48,7 @@ #include "devices/gpioIds.h" #include "devices/powerSwitcherList.h" #include "eive/definitions.h" +#include "eive/objects.h" #include "fsfw/ipc/QueueFactory.h" #include "linux/ObjectFactory.h" #include "linux/boardtest/I2cTestClass.h" @@ -59,6 +61,9 @@ #include "linux/ipcore/Ptme.h" #include "linux/ipcore/PtmeConfig.h" #include "linux/payload/FreshSupvHandler.h" +#include "linux/payload/MpsocCommunication.h" +#include "linux/payload/PlocMpsocSpecialComHelper.h" +#include "linux/payload/SerialConfig.h" #include "mission/config/configfile.h" #include "mission/system/acs/AcsBoardFdir.h" #include "mission/system/acs/AcsSubsystem.h" @@ -624,14 +629,15 @@ void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwit auto mpsocGpioCookie = new GpioCookie; mpsocGpioCookie->addGpio(gpioIds::ENABLE_MPSOC_UART, gpioConfigMPSoC); gpioChecker(gpioComIF->addGpios(mpsocGpioCookie), "PLOC MPSoC"); - auto mpsocCookie = - new SerialCookie(objects::PLOC_MPSOC_HANDLER, q7s::UART_PLOC_MPSOC_DEV, - serial::PLOC_MPSOC_BAUD, mpsoc::MAX_REPLY_SIZE, UartModes::NON_CANONICAL); - mpsocCookie->setNoFixedSizeReply(); - auto plocMpsocHelper = new PlocMpsocSpecialComHelper(objects::PLOC_MPSOC_HELPER); - auto* mpsocHandler = new PlocMpsocHandler( - objects::PLOC_MPSOC_HANDLER, objects::UART_COM_IF, mpsocCookie, plocMpsocHelper, - Gpio(gpioIds::ENABLE_MPSOC_UART, gpioComIF), objects::PLOC_SUPERVISOR_HANDLER); + SerialConfig serialCfg(q7s::UART_PLOC_MPSOC_DEV, serial::PLOC_MPSOC_BAUD, mpsoc::MAX_REPLY_SIZE, + UartModes::NON_CANONICAL); + auto mpsocCommunication = new MpsocCommunication(objects::PLOC_MPSOC_COMMUNICATION, serialCfg); + auto specialComHelper = + new PlocMpsocSpecialComHelper(objects::PLOC_MPSOC_HELPER, *mpsocCommunication); + DhbConfig dhbConf(objects::PLOC_MPSOC_HANDLER); + auto* mpsocHandler = new FreshMpsocHandler(dhbConf, *mpsocCommunication, *specialComHelper, + Gpio(gpioIds::ENABLE_MPSOC_UART, gpioComIF), + objects::PLOC_SUPERVISOR_HANDLER); mpsocHandler->connectModeTreeParent(satsystem::payload::SUBSYSTEM); #endif /* OBSW_ADD_PLOC_MPSOC == 1 */ #if OBSW_ADD_PLOC_SUPERVISOR == 1 @@ -650,7 +656,7 @@ void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwit supv::MAX_PACKET_SIZE * 20, UartModes::NON_CANONICAL); supervisorCookie->setNoFixedSizeReply(); new PlocSupvUartManager(objects::PLOC_SUPERVISOR_HELPER); - DhbConfig dhbConf(objects::PLOC_SUPERVISOR_HANDLER); + dhbConf = DhbConfig(objects::PLOC_SUPERVISOR_HANDLER); auto* supvHandler = new FreshSupvHandler(dhbConf, supervisorCookie, Gpio(gpioIds::ENABLE_SUPV_UART, gpioComIF), pwrSwitcher, power::PDU1_CH6_PLOC_12V); diff --git a/common/config/eive/objects.h b/common/config/eive/objects.h index c7e56715..797bea1d 100644 --- a/common/config/eive/objects.h +++ b/common/config/eive/objects.h @@ -77,6 +77,7 @@ enum commonObjects : uint32_t { PLOC_MPSOC_HANDLER = 0x44330015, PLOC_SUPERVISOR_HANDLER = 0x44330016, PLOC_SUPERVISOR_HELPER = 0x44330017, + PLOC_MPSOC_COMMUNICATION = 0x44330018, SCEX = 0x44330032, SOLAR_ARRAY_DEPL_HANDLER = 0x444100A2, HEATER_HANDLER = 0x444100A4, diff --git a/common/config/eive/resultClassIds.h b/common/config/eive/resultClassIds.h index 35b2a419..8c30dd16 100644 --- a/common/config/eive/resultClassIds.h +++ b/common/config/eive/resultClassIds.h @@ -42,6 +42,7 @@ enum commonClassIds : uint8_t { PERSISTENT_TM_STORE, // PTM TM_SINK, // TMS VIRTUAL_CHANNEL, // VCS + PLOC_MPSOC_COM, // PLMPCOM COMMON_CLASS_ID_END // [EXPORT] : [END] }; } diff --git a/fsfw b/fsfw index 8b21dd27..42867ad0 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 8b21dd276de72b46b41bc7080d6646180bfa0662 +Subproject commit 42867ad0cba088ab1cb6cb672d001f991f7e4a60 diff --git a/generators/bsp_hosted_events.csv b/generators/bsp_hosted_events.csv index 3c05a3c2..6f5579c0 100644 --- a/generators/bsp_hosted_events.csv +++ b/generators/bsp_hosted_events.csv @@ -128,14 +128,14 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 11506;0x2cf2;DEPL_SA1_GPIO_SWTICH_OFF_FAILED;HIGH;No description;mission/SolarArrayDeploymentHandler.h 11507;0x2cf3;DEPL_SA2_GPIO_SWTICH_OFF_FAILED;HIGH;No description;mission/SolarArrayDeploymentHandler.h 11508;0x2cf4;AUTONOMOUS_DEPLOYMENT_COMPLETED;INFO;No description;mission/SolarArrayDeploymentHandler.h -11601;0x2d51;MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC crc failure in telemetry packet;linux/payload/PlocMpsocHandler.h -11602;0x2d52;ACK_FAILURE;LOW;PLOC receive acknowledgment failure report P1: Command Id which leads the acknowledgment failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/PlocMpsocHandler.h -11603;0x2d53;EXE_FAILURE;LOW;PLOC receive execution failure report P1: Command Id which leads the execution failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/PlocMpsocHandler.h -11604;0x2d54;MPSOC_HANDLER_CRC_FAILURE;LOW;PLOC reply has invalid crc;linux/payload/PlocMpsocHandler.h -11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/PlocMpsocHandler.h -11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/PlocMpsocHandler.h -11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/PlocMpsocHandler.h -11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;No description;linux/payload/PlocMpsocHandler.h +11601;0x2d51;MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC crc failure in telemetry packet;linux/payload/plocMpsocHelpers.h +11602;0x2d52;ACK_FAILURE;LOW;PLOC receive acknowledgment failure report P1: Command Id which leads the acknowledgment failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/plocMpsocHelpers.h +11603;0x2d53;EXE_FAILURE;LOW;PLOC receive execution failure report P1: Command Id which leads the execution failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/plocMpsocHelpers.h +11604;0x2d54;MPSOC_HANDLER_CRC_FAILURE;LOW;PLOC reply has invalid crc;linux/payload/plocMpsocHelpers.h +11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/plocMpsocHelpers.h +11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/plocMpsocHelpers.h +11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/plocMpsocHelpers.h +11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;No description;linux/payload/plocMpsocHelpers.h 11701;0x2db5;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11702;0x2db6;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11703;0x2db7;SELF_TEST_ADC_FAILURE;LOW;Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h diff --git a/generators/bsp_hosted_objects.csv b/generators/bsp_hosted_objects.csv index 254d093a..227371da 100644 --- a/generators/bsp_hosted_objects.csv +++ b/generators/bsp_hosted_objects.csv @@ -57,6 +57,7 @@ 0x44330015;PLOC_MPSOC_HANDLER 0x44330016;PLOC_SUPERVISOR_HANDLER 0x44330017;PLOC_SUPERVISOR_HELPER +0x44330018;PLOC_MPSOC_COMMUNICATION 0x44330032;SCEX 0x444100A2;SOLAR_ARRAY_DEPL_HANDLER 0x444100A4;HEATER_HANDLER diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv index 3c05a3c2..6f5579c0 100644 --- a/generators/bsp_q7s_events.csv +++ b/generators/bsp_q7s_events.csv @@ -128,14 +128,14 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 11506;0x2cf2;DEPL_SA1_GPIO_SWTICH_OFF_FAILED;HIGH;No description;mission/SolarArrayDeploymentHandler.h 11507;0x2cf3;DEPL_SA2_GPIO_SWTICH_OFF_FAILED;HIGH;No description;mission/SolarArrayDeploymentHandler.h 11508;0x2cf4;AUTONOMOUS_DEPLOYMENT_COMPLETED;INFO;No description;mission/SolarArrayDeploymentHandler.h -11601;0x2d51;MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC crc failure in telemetry packet;linux/payload/PlocMpsocHandler.h -11602;0x2d52;ACK_FAILURE;LOW;PLOC receive acknowledgment failure report P1: Command Id which leads the acknowledgment failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/PlocMpsocHandler.h -11603;0x2d53;EXE_FAILURE;LOW;PLOC receive execution failure report P1: Command Id which leads the execution failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/PlocMpsocHandler.h -11604;0x2d54;MPSOC_HANDLER_CRC_FAILURE;LOW;PLOC reply has invalid crc;linux/payload/PlocMpsocHandler.h -11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/PlocMpsocHandler.h -11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/PlocMpsocHandler.h -11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/PlocMpsocHandler.h -11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;No description;linux/payload/PlocMpsocHandler.h +11601;0x2d51;MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC crc failure in telemetry packet;linux/payload/plocMpsocHelpers.h +11602;0x2d52;ACK_FAILURE;LOW;PLOC receive acknowledgment failure report P1: Command Id which leads the acknowledgment failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/plocMpsocHelpers.h +11603;0x2d53;EXE_FAILURE;LOW;PLOC receive execution failure report P1: Command Id which leads the execution failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/plocMpsocHelpers.h +11604;0x2d54;MPSOC_HANDLER_CRC_FAILURE;LOW;PLOC reply has invalid crc;linux/payload/plocMpsocHelpers.h +11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/plocMpsocHelpers.h +11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/plocMpsocHelpers.h +11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/plocMpsocHelpers.h +11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;No description;linux/payload/plocMpsocHelpers.h 11701;0x2db5;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11702;0x2db6;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11703;0x2db7;SELF_TEST_ADC_FAILURE;LOW;Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h diff --git a/generators/bsp_q7s_objects.csv b/generators/bsp_q7s_objects.csv index 1ada26dd..8fc1bd22 100644 --- a/generators/bsp_q7s_objects.csv +++ b/generators/bsp_q7s_objects.csv @@ -56,6 +56,7 @@ 0x44330015;PLOC_MPSOC_HANDLER 0x44330016;PLOC_SUPERVISOR_HANDLER 0x44330017;PLOC_SUPERVISOR_HELPER +0x44330018;PLOC_MPSOC_COMMUNICATION 0x44330032;SCEX 0x444100A2;SOLAR_ARRAY_DEPL_HANDLER 0x444100A4;HEATER_HANDLER diff --git a/generators/bsp_q7s_returnvalues.csv b/generators/bsp_q7s_returnvalues.csv index 72d47797..ec9a7fe5 100644 --- a/generators/bsp_q7s_returnvalues.csv +++ b/generators/bsp_q7s_returnvalues.csv @@ -561,16 +561,17 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x67a2;SADPL_MainSwitchTimeoutFailure;No description;162;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h 0x67a3;SADPL_SwitchingDeplSa1Failed;No description;163;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h 0x67a4;SADPL_SwitchingDeplSa2Failed;No description;164;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h -0x68a0;MPSOCRTVIF_CrcFailure;Space Packet received from PLOC has invalid CRC;160;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h -0x68a1;MPSOCRTVIF_ReceivedAckFailure;Received ACK failure reply from PLOC;161;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h -0x68a2;MPSOCRTVIF_ReceivedExeFailure;Received execution failure reply from PLOC;162;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h -0x68a3;MPSOCRTVIF_InvalidApid;Received space packet with invalid APID from PLOC;163;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h -0x68a4;MPSOCRTVIF_InvalidLength;Received command with invalid length;164;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h -0x68a5;MPSOCRTVIF_FilenameTooLong;Filename of file in OBC filesystem is too long;165;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h -0x68a6;MPSOCRTVIF_MpsocHelperExecuting;MPSoC helper is currently executing a command;166;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h -0x68a7;MPSOCRTVIF_MpsocFilenameTooLong;Filename of MPSoC file is to long (max. 256 bytes);167;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h -0x68a8;MPSOCRTVIF_InvalidParameter;Command has invalid parameter;168;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h -0x68a9;MPSOCRTVIF_NameTooLong;Received command has file string with invalid length;169;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h +0x6810;MPSOCRTVIF_CommandTimeout;Command has timed out.;16;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h +0x68a0;MPSOCRTVIF_CrcFailure;Space Packet received from PLOC has invalid CRC;160;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h +0x68a1;MPSOCRTVIF_ReceivedAckFailure;Received ACK failure reply from PLOC;161;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h +0x68a2;MPSOCRTVIF_ReceivedExeFailure;Received execution failure reply from PLOC;162;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h +0x68a3;MPSOCRTVIF_InvalidApid;Received space packet with invalid APID from PLOC;163;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h +0x68a4;MPSOCRTVIF_InvalidLength;Received command with invalid length;164;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h +0x68a5;MPSOCRTVIF_FilenameTooLong;Filename of file in OBC filesystem is too long;165;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h +0x68a6;MPSOCRTVIF_MpsocHelperExecuting;MPSoC helper is currently executing a command;166;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h +0x68a7;MPSOCRTVIF_MpsocFilenameTooLong;Filename of MPSoC file is to long (max. 256 bytes);167;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h +0x68a8;MPSOCRTVIF_InvalidParameter;Command has invalid parameter;168;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h +0x68a9;MPSOCRTVIF_NameTooLong;Received command has file string with invalid length;169;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h 0x69a0;SPVRTVIF_CrcFailure;Space Packet received from PLOC supervisor has invalid CRC;160;SUPV_RETURN_VALUES_IF;linux/payload/plocSupvDefs.h 0x69a1;SPVRTVIF_InvalidServiceId;No description;161;SUPV_RETURN_VALUES_IF;linux/payload/plocSupvDefs.h 0x69a2;SPVRTVIF_ReceivedAckFailure;Received ACK failure reply from PLOC supervisor;162;SUPV_RETURN_VALUES_IF;linux/payload/plocSupvDefs.h @@ -626,4 +627,7 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x6f02;TMS_NoWriteActive;No description;2;TM_SINK;mission/tmtc/DirectTmSinkIF.h 0x6f03;TMS_Timeout;No description;3;TM_SINK;mission/tmtc/DirectTmSinkIF.h 0x7000;VCS_ChannelDoesNotExist;No description;0;VIRTUAL_CHANNEL;mission/com/VirtualChannel.h -0x7200;SCBU_KeyNotFound;No description;0;SCRATCH_BUFFER;bsp_q7s/memory/scratchApi.h +0x7100;PLMPCOM_PacketReceived;No description;0;PLOC_MPSOC_COM;linux/payload/MpsocCommunication.h +0x7101;PLMPCOM_FaultyPacketSize;No description;1;PLOC_MPSOC_COM;linux/payload/MpsocCommunication.h +0x7102;PLMPCOM_CrcCheckFailed;No description;2;PLOC_MPSOC_COM;linux/payload/MpsocCommunication.h +0x7300;SCBU_KeyNotFound;No description;0;SCRATCH_BUFFER;bsp_q7s/memory/scratchApi.h diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index 0e05842a..8d67f14d 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 324 translations. * @details - * Generated on: 2024-04-10 11:49:35 + * Generated on: 2024-04-17 11:22:10 */ #include "translateEvents.h" diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index 7632605f..5ef8a2a7 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -1,8 +1,8 @@ /** * @brief Auto-generated object translation file. * @details - * Contains 179 translations. - * Generated on: 2024-04-10 11:49:35 + * Contains 180 translations. + * Generated on: 2024-04-17 11:22:10 */ #include "translateObjects.h" @@ -64,6 +64,7 @@ const char *PTME_VC3_CFDP_TM_STRING = "PTME_VC3_CFDP_TM"; const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER"; const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER"; const char *PLOC_SUPERVISOR_HELPER_STRING = "PLOC_SUPERVISOR_HELPER"; +const char *PLOC_MPSOC_COMMUNICATION_STRING = "PLOC_MPSOC_COMMUNICATION"; const char *SCEX_STRING = "SCEX"; const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER"; const char *HEATER_HANDLER_STRING = "HEATER_HANDLER"; @@ -304,6 +305,8 @@ const char *translateObject(object_id_t object) { return PLOC_SUPERVISOR_HANDLER_STRING; case 0x44330017: return PLOC_SUPERVISOR_HELPER_STRING; + case 0x44330018: + return PLOC_MPSOC_COMMUNICATION_STRING; case 0x44330032: return SCEX_STRING; case 0x444100A2: diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index 0e05842a..8d67f14d 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 324 translations. * @details - * Generated on: 2024-04-10 11:49:35 + * Generated on: 2024-04-17 11:22:10 */ #include "translateEvents.h" diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index 7632605f..5ef8a2a7 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -1,8 +1,8 @@ /** * @brief Auto-generated object translation file. * @details - * Contains 179 translations. - * Generated on: 2024-04-10 11:49:35 + * Contains 180 translations. + * Generated on: 2024-04-17 11:22:10 */ #include "translateObjects.h" @@ -64,6 +64,7 @@ const char *PTME_VC3_CFDP_TM_STRING = "PTME_VC3_CFDP_TM"; const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER"; const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER"; const char *PLOC_SUPERVISOR_HELPER_STRING = "PLOC_SUPERVISOR_HELPER"; +const char *PLOC_MPSOC_COMMUNICATION_STRING = "PLOC_MPSOC_COMMUNICATION"; const char *SCEX_STRING = "SCEX"; const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER"; const char *HEATER_HANDLER_STRING = "HEATER_HANDLER"; @@ -304,6 +305,8 @@ const char *translateObject(object_id_t object) { return PLOC_SUPERVISOR_HANDLER_STRING; case 0x44330017: return PLOC_SUPERVISOR_HELPER_STRING; + case 0x44330018: + return PLOC_MPSOC_COMMUNICATION_STRING; case 0x44330032: return SCEX_STRING; case 0x444100A2: diff --git a/linux/payload/CMakeLists.txt b/linux/payload/CMakeLists.txt index 48fb9d96..f0212c2e 100644 --- a/linux/payload/CMakeLists.txt +++ b/linux/payload/CMakeLists.txt @@ -1,7 +1,9 @@ target_sources( ${OBSW_NAME} PUBLIC PlocMemoryDumper.cpp - PlocMpsocHandler.cpp + MpsocCommunication.cpp + SerialCommunicationHelper.cpp + FreshMpsocHandler.cpp FreshSupvHandler.cpp PlocMpsocSpecialComHelper.cpp plocMpsocHelpers.cpp diff --git a/linux/payload/FreshMpsocHandler.cpp b/linux/payload/FreshMpsocHandler.cpp new file mode 100644 index 00000000..021ebc5a --- /dev/null +++ b/linux/payload/FreshMpsocHandler.cpp @@ -0,0 +1,1260 @@ +#include "FreshMpsocHandler.h" + +#include "OBSWConfig.h" +#include "eive/objects.h" +#include "fsfw/action/CommandActionHelper.h" +#include "fsfw/datapool/PoolReadGuard.h" +#include "fsfw/devicehandlers/DeviceHandlerIF.h" +#include "fsfw/devicehandlers/FreshDeviceHandlerBase.h" +#include "fsfw/ipc/MessageQueueIF.h" +#include "fsfw/ipc/QueueFactory.h" +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/serialize/SerializeAdapter.h" +#include "linux/payload/MpsocCommunication.h" +#include "linux/payload/plocMpsocHelpers.h" +#include "linux/payload/plocSupvDefs.h" + +FreshMpsocHandler::FreshMpsocHandler(DhbConfig cfg, MpsocCommunication& comInterface, + PlocMpsocSpecialComHelper& specialComHelper, + Gpio uartIsolatorSwitch, object_id_t supervisorHandler) + : FreshDeviceHandlerBase(cfg), + comInterface(comInterface), + specialComHelper(specialComHelper), + commandActionHelper(this), + uartIsolatorSwitch(uartIsolatorSwitch), + hkReport(this), + supervisorHandler(supervisorHandler) { + commandActionHelperQueue = QueueFactory::instance()->createMessageQueue(10); + eventQueue = QueueFactory::instance()->createMessageQueue(10); + spParams.maxSize = sizeof(commandBuffer); + spParams.buf = commandBuffer; +} + +void FreshMpsocHandler::performDeviceOperation(uint8_t opCode) { + if (transitionState == TransitionState::NONE and (mode == MODE_OFF or mode == MODE_UNDEFINED)) { + // Nothing to do for now. + return; + } + + if (opCode == OpCode::DEFAULT_OPERATION) { + performDefaultDeviceOperation(); + } else if (opCode == OpCode::PARSE_TM and not specialComHelperExecuting) { + // Just need to call this once, this should take care of processing the whole received + // Linux UART RX buffer. + comInterface.readSerialInterface(); + // Handle all received packets. + while (true) { + ReturnValue_t result = comInterface.parseAndRetrieveNextPacket(); + if (result == MpsocCommunication::PACKET_RECEIVED) { + handleDeviceReply(); + continue; + } + break; + } + } +} + +void FreshMpsocHandler::performDefaultDeviceOperation() { + if (transitionState != TransitionState::NONE) { + if (transitionState == TransitionState::TO_ON) { + handleTransitionToOn(); + } else if (transitionState == TransitionState::TO_OFF) { + handleTransitionToOff(); + } else if (transitionState == TransitionState::SUBMODE) { + if (!activeCmdInfo.pending) { + commandSubmodeTransition(); + } + } else { + // This should never happen. + sif::error << "FreshMpsocHandler: Invalid transition mode: " << targetMode << std::endl; + targetMode = MODE_OFF; + targetSubmode = 0; + handleTransitionToOff(); + } + if (modeHelper.isTimedOut()) { + // Set old mode and submode. + setMode(mode, submode); + } + } + + if (mode == MODE_NORMAL and not activeCmdInfo.pending) { + // TODO: Take care of regular periodic commanding here. + } + + if (activeCmdInfo.pending and activeCmdInfo.cmdCountdown.hasTimedOut()) { + sif::warning << "PlocMpsocHandler: Command " << activeCmdInfo.pendingCmd << " has timed out" + << std::endl; + cmdDoneHandler(false, mpsoc::COMMAND_TIMEOUT); + } + EventMessage event; + for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK; + result = eventQueue->receiveMessage(&event)) { + switch (event.getMessageId()) { + case EventMessage::EVENT_MESSAGE: + handleEvent(&event); + break; + default: + sif::debug << "PlocMPSoCHandler::performOperationHook: Did not subscribe to this event" + << " message" << std::endl; + break; + } + } + CommandMessage message; + for (ReturnValue_t result = commandActionHelperQueue->receiveMessage(&message); + result == returnvalue::OK; result = commandActionHelperQueue->receiveMessage(&message)) { + result = commandActionHelper.handleReply(&message); + if (result == returnvalue::OK) { + continue; + } + } +} + +ReturnValue_t FreshMpsocHandler::handleCommandMessage(CommandMessage* message) { + return returnvalue::FAILED; +} + +ReturnValue_t FreshMpsocHandler::initialize() { + ReturnValue_t result = FreshDeviceHandlerBase::initialize(); + if (result != returnvalue::OK) { + return result; + } + EventManagerIF* manager = ObjectManager::instance()->get(objects::EVENT_MANAGER); + if (manager == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "PlocMPSoCHandler::initialize: Invalid event manager" << std::endl; +#endif + return ObjectManagerIF::CHILD_INIT_FAILED; + ; + } + result = manager->registerListener(eventQueue->getId()); + if (result != returnvalue::OK) { + return result; + } + result = manager->subscribeToEvent( + eventQueue->getId(), event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_WRITE_FAILED)); + if (result != returnvalue::OK) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + result = manager->subscribeToEvent( + eventQueue->getId(), + event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_WRITE_SUCCESSFUL)); + if (result != returnvalue::OK) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + result = manager->subscribeToEvent( + eventQueue->getId(), + event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_READ_SUCCESSFUL)); + if (result != returnvalue::OK) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + result = manager->subscribeToEvent( + eventQueue->getId(), event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_READ_FAILED)); + if (result != returnvalue::OK) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + result = commandActionHelper.initialize(); + if (result != returnvalue::OK) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + return result; +} + +// HK manager abstract functions. +LocalPoolDataSetBase* FreshMpsocHandler::getDataSetHandle(sid_t sid) { + if (sid == hkReport.getSid()) { + return &hkReport; + } + return nullptr; +} + +ReturnValue_t FreshMpsocHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) { + localDataPoolMap.emplace(mpsoc::poolid::STATUS, &peStatus); + localDataPoolMap.emplace(mpsoc::poolid::MODE, &peMode); + localDataPoolMap.emplace(mpsoc::poolid::DOWNLINK_PWR_ON, &peDownlinkPwrOn); + localDataPoolMap.emplace(mpsoc::poolid::DOWNLINK_REPLY_ACTIIVE, &peDownlinkReplyActive); + localDataPoolMap.emplace(mpsoc::poolid::DOWNLINK_JESD_SYNC_STATUS, &peDownlinkJesdSyncStatus); + localDataPoolMap.emplace(mpsoc::poolid::DOWNLINK_DAC_STATUS, &peDownlinkDacStatus); + localDataPoolMap.emplace(mpsoc::poolid::CAM_STATUS, &peCameraStatus); + localDataPoolMap.emplace(mpsoc::poolid::CAM_SDI_STATUS, &peCameraSdiStatus); + localDataPoolMap.emplace(mpsoc::poolid::CAM_FPGA_TEMP, &peCameraFpgaTemp); + localDataPoolMap.emplace(mpsoc::poolid::CAM_SOC_TEMP, &peCameraSocTemp); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_TEMP, &peSysmonTemp); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCCINT, &peSysmonVccInt); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCCAUX, &peSysmonVccAux); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCCBRAM, &peSysmonVccBram); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCCPAUX, &peSysmonVccPaux); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCCPINT, &peSysmonVccPint); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCCPDRO, &peSysmonVccPdro); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_MB12V, &peSysmonMb12V); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_MB3V3, &peSysmonMb3V3); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_MB1V8, &peSysmonMb1V8); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC12V, &peSysmonVcc12V); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC5V, &peSysmonVcc5V); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC3V3, &peSysmonVcc3V3); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC3V3VA, &peSysmonVcc3V3VA); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC2V5DDR, &peSysmonVcc2V5DDR); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC1V2DDR, &peSysmonVcc1V2DDR); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC0V9, &peSysmonVcc0V9); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC0V6VTT, &peSysmonVcc0V6VTT); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_SAFE_COTS_CUR, &peSysmonSafeCotsCur); + localDataPoolMap.emplace(mpsoc::poolid::SYSMON_NVM4_XO_CUR, &peSysmonNvm4XoCur); + localDataPoolMap.emplace(mpsoc::poolid::SEM_UNCORRECTABLE_ERRS, &peSemUncorrectableErrs); + localDataPoolMap.emplace(mpsoc::poolid::SEM_CORRECTABLE_ERRS, &peSemCorrectableErrs); + localDataPoolMap.emplace(mpsoc::poolid::SEM_STATUS, &peSemStatus); + localDataPoolMap.emplace(mpsoc::poolid::REBOOT_MPSOC_REQUIRED, &peRebootMpsocRequired); + poolManager.subscribeForRegularPeriodicPacket( + subdp::RegularHkPeriodicParams(hkReport.getSid(), false, 10.0)); + return returnvalue::OK; +} + +// Mode abstract functions +ReturnValue_t FreshMpsocHandler::checkModeCommand(Mode_t mode, Submode_t submode, + uint32_t* msToReachTheMode) { + if (this->mode == MODE_OFF or this->mode == MODE_UNDEFINED) { + // Device needs to be commanded to ON or NORMAL first before commanding submode. + if (submode != mpsoc::Submode::IDLE_OR_NONE) { + return HasModesIF::INVALID_SUBMODE; + } + } + if (mode == MODE_ON or mode == MODE_NORMAL) { + if (submode != mpsoc::Submode::IDLE_OR_NONE && submode != mpsoc::Submode::REPLAY && + submode != mpsoc::Submode::SNAPSHOT) { + return HasModesIF::INVALID_SUBMODE; + } + } + *msToReachTheMode = MPSOC_MODE_CMD_TIMEOUT_MS; + return returnvalue::OK; +} + +// Action override. Forward to user. +ReturnValue_t FreshMpsocHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) { + ReturnValue_t result = returnvalue::OK; + switch (actionId) { + case mpsoc::SET_UART_TX_TRISTATE: { + uartIsolatorSwitch.pullLow(); + return EXECUTION_FINISHED; + break; + } + case mpsoc::RELEASE_UART_TX: { + uartIsolatorSwitch.pullHigh(); + return EXECUTION_FINISHED; + break; + default: + break; + } + } + + if (specialComHelperExecuting) { + return mpsoc::MPSOC_HELPER_EXECUTING; + } + + // We do not accept the rest of the commands if we are not on. + if (mode != MODE_ON && mode != MODE_NORMAL) { + return HasModesIF::INVALID_MODE; + } + + switch (actionId) { + case mpsoc::TC_FLASH_WRITE_FULL_FILE: { + mpsoc::FlashBasePusCmd flashWritePusCmd; + result = flashWritePusCmd.extractFields(data, size); + if (result != returnvalue::OK) { + return result; + } + result = specialComHelper.startFlashWrite(flashWritePusCmd.getObcFile(), + flashWritePusCmd.getMpsocFile()); + if (result != returnvalue::OK) { + return result; + } + commonSpecialComInit(); + return EXECUTION_FINISHED; + } + case mpsoc::TC_FLASH_READ_FULL_FILE: { + mpsoc::FlashReadPusCmd flashReadPusCmd; + result = flashReadPusCmd.extractFields(data, size); + if (result != returnvalue::OK) { + return result; + } + result = specialComHelper.startFlashRead(flashReadPusCmd.getObcFile(), + flashReadPusCmd.getMpsocFile(), + flashReadPusCmd.getReadSize()); + if (result != returnvalue::OK) { + return result; + } + sif::info << "PLOC MPSoC: Reading " << flashReadPusCmd.getMpsocFile() << " with size " + << flashReadPusCmd.getReadSize() << " to " << flashReadPusCmd.getObcFile() + << std::endl; + commonSpecialComInit(); + return EXECUTION_FINISHED; + } + case (mpsoc::OBSW_RESET_SEQ_COUNT_LEGACY): { + commandSequenceCount = 0; + return EXECUTION_FINISHED; + } + default: + break; + } + // For longer commands, do not set these. + // TODO: Do all the stuff the form buildDeviceFromDevice blah did. + executeRegularCmd(actionId, commandedBy, data, size); + return returnvalue::OK; +} + +void FreshMpsocHandler::commonSpecialComInit() { + specialComHelperExecuting = true; + specialComHelper.setCommandSequenceCount(commandSequenceCount.get()); +} + +/** + * @overload + * @param submode + */ +void FreshMpsocHandler::startTransition(Mode_t newMode, Submode_t submode) { + // OFF commands are always accepted. Otherwise, ignore transition requests. + if (transitionState != TransitionState::NONE && newMode != HasModesIF::MODE_OFF) { + return; + } + // We are already on and only a submode change is commanded. + if ((mode == MODE_ON or mode == MODE_NORMAL) && (newMode == MODE_ON or newMode == MODE_NORMAL)) { + transitionState = TransitionState::SUBMODE; + } else if ((newMode == MODE_ON or newMode == MODE_NORMAL) && + ((mode == MODE_OFF) or (mode == MODE_UNDEFINED))) { + transitionState = TransitionState::TO_ON; + } else if (newMode == MODE_OFF) { + transitionState = TransitionState::TO_OFF; + } + targetMode = newMode; + targetSubmode = submode; +} + +ReturnValue_t FreshMpsocHandler::performDeviceOperationPreQueueHandling(uint8_t opCode) { + return returnvalue::OK; +} + +void FreshMpsocHandler::commandSubmodeTransition() { + if (targetSubmode == mpsoc::Submode::IDLE_OR_NONE) { + commandTcModeIdle(); + } else if (targetSubmode == mpsoc::Submode::SNAPSHOT) { + commandTcModeSnapshot(); + } else if (targetSubmode == mpsoc::Submode::REPLAY) { + commandTcModeReplay(); + } else { + sif::error << "FreshMpsocHandler::handleTransitionToOn: Invalid submode" << std::endl; + } +} + +void FreshMpsocHandler::handleTransitionToOn() { + if (startupState == StartupState::IDLE) { + startupState = StartupState::HW_INIT; + } + if (startupState == StartupState::HW_INIT) { + if (handleHwStartup()) { + startupState = StartupState::DONE; + } + } + if (startupState == StartupState::DONE) { + setMode(targetMode, targetSubmode); + transitionState = TransitionState::NONE; + hkReport.setReportingEnabled(true); + powerState = PowerState::IDLE; + startupState = StartupState::IDLE; + } +} + +void FreshMpsocHandler::handleTransitionToOff() { + if (handleHwShutdown()) { + hkReport.setReportingEnabled(false); + setMode(MODE_OFF, 0); + transitionState = TransitionState::NONE; + activeCmdInfo.reset(); + powerState = PowerState::IDLE; + startupState = StartupState::IDLE; + } +} + +MessageQueueIF* FreshMpsocHandler::getCommandQueuePtr() { return commandActionHelperQueue; } + +void FreshMpsocHandler::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) { return; } + +void FreshMpsocHandler::stepFailedReceived(ActionId_t actionId, uint8_t step, + ReturnValue_t returnCode) { + switch (actionId) { + case supv::START_MPSOC: { + sif::warning << "PlocMPSoCHandler::stepFailedReceived: Failed to start MPSoC" << std::endl; + break; + } + case supv::SHUTDOWN_MPSOC: { + triggerEvent(mpsoc::MPSOC_SHUTDOWN_FAILED); + sif::warning << "PlocMPSoCHandler::stepFailedReceived: Failed to shutdown MPSoC" << std::endl; + break; + } + default: + sif::debug << "PlocMPSoCHandler::stepFailedReceived: Received unexpected action reply" + << std::endl; + break; + } + powerState = PowerState::SUPV_FAILED; +} + +void FreshMpsocHandler::dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) { + return; +} + +void FreshMpsocHandler::completionSuccessfulReceived(ActionId_t actionId) { + switch (powerState) { + case PowerState::PENDING_STARTUP: { + if (actionId != supv::START_MPSOC) { + return; + } + mpsocBootTransitionCd.resetTimer(); + powerState = PowerState::DONE; + break; + } + case PowerState::PENDING_SHUTDOWN: { + if (actionId != supv::SHUTDOWN_MPSOC) { + return; + } + powerState = PowerState::DONE; + break; + } + default: { + break; + } + } +} + +void FreshMpsocHandler::completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) { + handleActionCommandFailure(actionId, returnCode); +} + +void FreshMpsocHandler::handleActionCommandFailure(ActionId_t actionId, ReturnValue_t returnCode) { + switch (powerState) { + case PowerState::PENDING_STARTUP: { + if (actionId != supv::START_MPSOC) { + return; + } + sif::info << "PlocMPSoCHandler::handleActionCommandFailure: MPSoC boot command failed" + << std::endl; + // This is commonly the case when the MPSoC is already operational. Thus the power state is + // set to on here + break; + } + case PowerState::PENDING_SHUTDOWN: { + // FDIR will intercept event and switch PLOC power off + triggerEvent(mpsoc::MPSOC_SHUTDOWN_FAILED); + if (actionId != supv::SHUTDOWN_MPSOC) { + return; + } + sif::warning << "PlocMPSoCHandler::handleActionCommandFailure: Failed to shutdown MPSoC" + << std::endl; + break; + } + default: + break; + } + powerState = PowerState::SUPV_FAILED; + return; +} + +ReturnValue_t FreshMpsocHandler::executeRegularCmd(ActionId_t actionId, + MessageQueueId_t commandedBy, + const uint8_t* commandData, + size_t commandDataLen) { + ReturnValue_t result; + switch (actionId) { + case (mpsoc::TC_MEM_WRITE): { + result = commandTcMemWrite(commandData, commandDataLen); + break; + } + case (mpsoc::TC_VERIFY_BOOT): { + uint8_t cmdDataForDeadbeefCheck[6]{}; + size_t serLen = 0; + uint16_t wordLen = 1; + SerializeAdapter::serialize(&mpsoc::DEADBEEF_ADDR, cmdDataForDeadbeefCheck, &serLen, 4, + SerializeIF::Endianness::NETWORK); + SerializeAdapter::serialize(&wordLen, cmdDataForDeadbeefCheck + 4, &serLen, 2, + SerializeIF::Endianness::NETWORK); + result = commandTcMemRead(cmdDataForDeadbeefCheck, 6); + break; + } + case (mpsoc::TC_MEM_READ): { + result = commandTcMemRead(commandData, commandDataLen); + break; + } + case (mpsoc::TC_FLASHFOPEN): { + mpsoc::TcFlashFopen cmd(spParams, commandSequenceCount); + // C string constructor. + std::string filename = std::string(reinterpret_cast(commandData)); + if (filename.size() > mpsoc::MAX_FILENAME_SIZE) { + return mpsoc::NAME_TOO_LONG; + } + uint8_t mode = commandData[filename.size() + 2]; + cmd.setPayload(filename, mode); + result = finishAndSendTc(actionId, cmd); + break; + } + case (mpsoc::TC_FLASHFCLOSE): { + mpsoc::TcFlashFclose cmd(spParams, commandSequenceCount); + result = finishAndSendTc(actionId, cmd); + break; + } + case (mpsoc::TC_FLASHDELETE): { + result = commandTcFlashDelete(commandData, commandDataLen); + break; + } + case (mpsoc::TC_REPLAY_START): { + result = commandTcReplayStart(commandData, commandDataLen); + break; + } + case (mpsoc::TC_REPLAY_STOP): { + result = commandTcReplayStop(); + break; + } + case (mpsoc::TC_DOWNLINK_PWR_ON): { + result = commandTcDownlinkPwrOn(commandData, commandDataLen); + break; + } + case (mpsoc::TC_DOWNLINK_PWR_OFF): { + result = commandTcDownlinkPwrOff(); + break; + } + case (mpsoc::TC_REPLAY_WRITE_SEQUENCE): { + result = commandTcReplayWriteSequence(commandData, commandDataLen); + break; + } + case (mpsoc::TC_ENABLE_TC_EXECTION): { + mpsoc::TcEnableTcExec cmd(spParams, commandSequenceCount); + result = cmd.setPayload(commandData, commandDataLen); + if (result != returnvalue::OK) { + return result; + } + result = finishAndSendTc(actionId, cmd); + break; + } + case (mpsoc::TC_FLASH_MKFS): { + if (commandDataLen != 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + if (commandData[0] != mpsoc::FlashId::FLASH_0 && commandData[1] != mpsoc::FlashId::FLASH_1) { + return HasActionsIF::INVALID_PARAMETERS; + } + mpsoc::TcFlashMkfs cmd(spParams, commandSequenceCount, + static_cast(commandData[0])); + sif::info << "PLOC MPSoC: Formatting Flash " << (int)commandData[0] << std::endl; + result = finishAndSendTc(actionId, cmd, mpsoc::CMD_TIMEOUT_MKFS); + break; + } + case (mpsoc::TC_GET_HK_REPORT): { + result = commandTcGetHkReport(); + break; + } + case (mpsoc::TC_FLASH_GET_DIRECTORY_CONTENT): { + result = commandTcGetDirContent(commandData, commandDataLen); + break; + } + case (mpsoc::TC_CAM_CMD_SEND): { + result = commandTcCamCmdSend(commandData, commandDataLen); + break; + } + case (mpsoc::TC_CAM_TAKE_PIC): { + result = commandTcCamTakePic(commandData, commandDataLen); + break; + } + case (mpsoc::TC_SIMPLEX_STREAM_FILE): { + if (submode != mpsoc::Submode::SNAPSHOT) { + return HasModesIF::INVALID_SUBMODE; + } + result = commandTcSimplexStreamFile(commandData, commandDataLen); + break; + } + case (mpsoc::TC_SIMPLEX_STORE_FILE): { + result = commandTcSimplexStoreFile(commandData, commandDataLen); + break; + } + case (mpsoc::TC_DOWNLINK_DATA_MODULATE): { + result = commandTcDownlinkDataModulate(commandData, commandDataLen); + break; + } + default: + sif::debug << "PlocMPSoCHandler::buildCommandFromCommand: Command not implemented" + << std::endl; + result = DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; + break; + } + + if (result == returnvalue::OK) { + activeCmdInfo.start(actionId, commandedBy); + /** + * Flushing the receive buffer to make sure there are no data left from a faulty reply. + */ + comInterface.getComHelper().flushUartRxBuffer(); + } + + return result; +} + +ReturnValue_t FreshMpsocHandler::commandTcMemWrite(const uint8_t* commandData, + size_t commandDataLen) { + ReturnValue_t result = returnvalue::OK; + mpsoc::TcMemWrite tcMemWrite(spParams, commandSequenceCount); + result = tcMemWrite.setPayload(commandData, commandDataLen); + if (result != returnvalue::OK) { + return result; + } + finishAndSendTc(mpsoc::TC_MEM_WRITE, tcMemWrite); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcMemRead(const uint8_t* commandData, + size_t commandDataLen) { + ReturnValue_t result = returnvalue::OK; + mpsoc::TcMemRead tcMemRead(spParams, commandSequenceCount); + result = tcMemRead.setPayload(commandData, commandDataLen); + if (result != returnvalue::OK) { + return result; + } + finishAndSendTc(mpsoc::TC_MEM_READ, tcMemRead); + tmMemReadReport.rememberRequestedSize = tcMemRead.getMemLen() * 4 + TmMemReadReport::FIX_SIZE; + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcFlashDelete(const uint8_t* commandData, + size_t commandDataLen) { + if (commandDataLen > mpsoc::FILENAME_FIELD_SIZE) { + return mpsoc::NAME_TOO_LONG; + } + ReturnValue_t result = returnvalue::OK; + mpsoc::TcFlashDelete tcFlashDelete(spParams, commandSequenceCount); + std::string filename = std::string(reinterpret_cast(commandData), commandDataLen); + result = tcFlashDelete.setPayload(filename); + if (result != returnvalue::OK) { + return result; + } + finishAndSendTc(mpsoc::TC_FLASHDELETE, tcFlashDelete); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcReplayStart(const uint8_t* commandData, + size_t commandDataLen) { + ReturnValue_t result = returnvalue::OK; + mpsoc::TcReplayStart tcReplayStart(spParams, commandSequenceCount); + result = tcReplayStart.setPayload(commandData, commandDataLen); + if (result != returnvalue::OK) { + return result; + } + finishAndSendTc(mpsoc::TC_REPLAY_START, tcReplayStart); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcReplayStop() { + mpsoc::TcReplayStop tcReplayStop(spParams, commandSequenceCount); + finishAndSendTc(mpsoc::TC_REPLAY_STOP, tcReplayStop); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcDownlinkPwrOn(const uint8_t* commandData, + size_t commandDataLen) { + ReturnValue_t result = returnvalue::OK; + mpsoc::TcDownlinkPwrOn tcDownlinkPwrOn(spParams, commandSequenceCount); + result = tcDownlinkPwrOn.setPayload(commandData, commandDataLen); + if (result != returnvalue::OK) { + return result; + } + finishAndSendTc(mpsoc::TC_DOWNLINK_PWR_ON, tcDownlinkPwrOn); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcDownlinkPwrOff() { + mpsoc::TcDownlinkPwrOff tcDownlinkPwrOff(spParams, commandSequenceCount); + finishAndSendTc(mpsoc::TC_DOWNLINK_PWR_OFF, tcDownlinkPwrOff); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcGetHkReport() { + mpsoc::TcGetHkReport tcGetHkReport(spParams, commandSequenceCount); + finishAndSendTc(mpsoc::TC_GET_HK_REPORT, tcGetHkReport); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcReplayWriteSequence(const uint8_t* commandData, + size_t commandDataLen) { + mpsoc::TcReplayWriteSeq tcReplayWriteSeq(spParams, commandSequenceCount); + ReturnValue_t result = tcReplayWriteSeq.setPayload(commandData, commandDataLen); + if (result != returnvalue::OK) { + return result; + } + finishAndSendTc(mpsoc::TC_REPLAY_WRITE_SEQUENCE, tcReplayWriteSeq); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcModeReplay() { + mpsoc::TcModeReplay tcModeReplay(spParams, commandSequenceCount); + finishAndSendTc(mpsoc::TC_MODE_REPLAY, tcModeReplay); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcModeIdle() { + mpsoc::TcModeIdle tcModeIdle(spParams, commandSequenceCount); + finishAndSendTc(mpsoc::TC_MODE_IDLE, tcModeIdle); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcCamCmdSend(const uint8_t* commandData, + size_t commandDataLen) { + mpsoc::TcCamcmdSend tcCamCmdSend(spParams, commandSequenceCount); + ReturnValue_t result = tcCamCmdSend.setPayload(commandData, commandDataLen); + if (result != returnvalue::OK) { + return result; + } + finishAndSendTc(mpsoc::TC_CAM_CMD_SEND, tcCamCmdSend); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcCamTakePic(const uint8_t* commandData, + size_t commandDataLen) { + mpsoc::TcCamTakePic tcCamTakePic(spParams, commandSequenceCount); + ReturnValue_t result = tcCamTakePic.setPayload(commandData, commandDataLen); + if (result != returnvalue::OK) { + return result; + } + sif::info << "PLOC MPSoC Take Picture Command" << std::endl; + sif::info << "filename: " << tcCamTakePic.fileName << std::endl; + sif::info << "encoder [Y, Cb, Cr]: [" << (int)tcCamTakePic.encoderSettingY << ", " + << (int)tcCamTakePic.encoderSettingsCb << ", " << (int)tcCamTakePic.encoderSettingsCr + << "]" << std::endl; + sif::info << "quantization [Y, Cb, Cr]: [" << tcCamTakePic.quantizationY << ", " + << tcCamTakePic.quantizationCb << ", " << tcCamTakePic.quantizationCr << "]" + << std::endl; + sif::info << "bypass compressor: " << (int)tcCamTakePic.bypassCompressor << std::endl; + finishAndSendTc(mpsoc::TC_CAM_TAKE_PIC, tcCamTakePic); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcSimplexStreamFile(const uint8_t* commandData, + size_t commandDataLen) { + mpsoc::TcSimplexStreamFile tcSimplexStreamFile(spParams, commandSequenceCount); + ReturnValue_t result = tcSimplexStreamFile.setPayload(commandData, commandDataLen); + if (result != returnvalue::OK) { + return result; + } + finishAndSendTc(mpsoc::TC_SIMPLEX_STREAM_FILE, tcSimplexStreamFile); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcSimplexStoreFile(const uint8_t* commandData, + size_t commandDataLen) { + mpsoc::TcSimplexStoreFile tcSimplexStoreFile(spParams, commandSequenceCount); + ReturnValue_t result = tcSimplexStoreFile.setPayload(commandData, commandDataLen); + if (result != returnvalue::OK) { + return result; + } + finishAndSendTc(mpsoc::TC_SIMPLEX_STORE_FILE, tcSimplexStoreFile); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcGetDirContent(const uint8_t* commandData, + size_t commandDataLen) { + mpsoc::TcGetDirContent tcGetDirContent(spParams, commandSequenceCount); + ReturnValue_t result = tcGetDirContent.setPayload(commandData, commandDataLen); + if (result != returnvalue::OK) { + return result; + } + finishAndSendTc(mpsoc::TC_FLASH_GET_DIRECTORY_CONTENT, tcGetDirContent); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcDownlinkDataModulate(const uint8_t* commandData, + size_t commandDataLen) { + mpsoc::TcDownlinkDataModulate tcDownlinkDataModulate(spParams, commandSequenceCount); + ReturnValue_t result = tcDownlinkDataModulate.setPayload(commandData, commandDataLen); + if (result != returnvalue::OK) { + return result; + } + finishAndSendTc(mpsoc::TC_DOWNLINK_DATA_MODULATE, tcDownlinkDataModulate); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::commandTcModeSnapshot() { + mpsoc::TcModeSnapshot tcModeSnapshot(spParams, commandSequenceCount); + finishAndSendTc(mpsoc::TC_MODE_SNAPSHOT, tcModeSnapshot); + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::finishAndSendTc(DeviceCommandId_t cmdId, mpsoc::TcBase& tcBase, + uint32_t cmdCountdownMs) { + ReturnValue_t result = tcBase.finishPacket(); + if (result != returnvalue::OK) { + return result; + } + // TODO: We should find a way so this works with the old implementation. + commandSequenceCount++; + + mpsoc::printTxPacket(tcBase); + activeCmdInfo.cmdCountdown.setTimeout(cmdCountdownMs); + activeCmdInfo.cmdCountdown.resetTimer(); + activeCmdInfo.pending = true; + activeCmdInfo.pendingCmd = cmdId; + activeCmdInfo.pendingCmdMpsocApid = tcBase.getApid(); + return comInterface.send(tcBase.getFullPacket(), tcBase.getFullPacketLen()); +} + +void FreshMpsocHandler::handleEvent(EventMessage* eventMessage) { + object_id_t objectId = eventMessage->getReporter(); + switch (objectId) { + case objects::PLOC_MPSOC_HELPER: { + commonSpecialComStop(); + break; + } + default: + sif::debug << "PlocMPSoCHandler::handleEvent: Did not subscribe to this event" << std::endl; + break; + } +} +void FreshMpsocHandler::commonSpecialComStop() { + specialComHelperExecuting = false; + commandSequenceCount.set(specialComHelper.getCommandSequenceCount()); +} + +void FreshMpsocHandler::cmdDoneHandler(bool success, ReturnValue_t result) { + if (transitionState == TransitionState::SUBMODE) { + if (success) { + setMode(targetMode, targetSubmode); + } else { + // Keep the old submode. + setMode(targetMode); + } + transitionState = TransitionState::NONE; + } + if (activeCmdInfo.pending && (activeCmdInfo.commandedBy != MessageQueueIF::NO_QUEUE)) { + actionHelper.finish(success, activeCmdInfo.commandedBy, activeCmdInfo.pendingCmd, result); + } + activeCmdInfo.reset(); +} + +ReturnValue_t FreshMpsocHandler::handleDeviceReply() { + ReturnValue_t result = returnvalue::OK; + + // SpacePacketReader spacePacket; + // spacePacket.setReadOnlyData(start, remainingSize); + const auto& replyReader = comInterface.getSpReader(); + if (replyReader.isNull()) { + return returnvalue::FAILED; + } + mpsoc::printRxPacket(replyReader); + uint16_t apid = replyReader.getApid(); + + switch (apid) { + case (mpsoc::apid::ACK_SUCCESS): + result = handleAckReport(); + break; + case (mpsoc::apid::ACK_FAILURE): + break; + case (mpsoc::apid::TM_MEMORY_READ_REPORT): + if (activeCmdInfo.pendingCmd == mpsoc::TC_VERIFY_BOOT) { + // 6 byte header, 4 byte address, 2 byte read width, 4 byte read back value + if (replyReader.getFullPacketLen() >= 6 + 4 + 2 + 4) { + uint32_t readBack = 0; + size_t deserLen = 0; + result = SerializeAdapter::deSerialize(&readBack, replyReader.getFullData() + 6 + 4 + 2, + &deserLen, SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK or readBack != mpsoc::DEADBEEF_VALUE) { + cmdDoneHandler(false, result); + } else { + cmdDoneHandler(true, returnvalue::OK); + } + } else { + cmdDoneHandler(false, result); + } + } + result = reportReplyData(mpsoc::TM_MEMORY_READ_REPORT); + break; + case (mpsoc::apid::TM_CAM_CMD_RPT): + result = reportReplyData(mpsoc::TM_CAM_CMD_RPT); + break; + case (mpsoc::apid::TM_HK_GET_REPORT): { + result = handleGetHkReport(); + break; + } + case (mpsoc::apid::TM_FLASH_DIRECTORY_CONTENT): { + result = reportReplyData(mpsoc::TM_FLASH_DIRECTORY_CONTENT); + break; + } + case (mpsoc::apid::EXE_SUCCESS): + case (mpsoc::apid::EXE_FAILURE): { + result = handleExecutionReport(); + break; + } + default: { + sif::debug << "FreshMpsocHandler:: Reply has invalid APID 0x" << std::hex << std::setfill('0') + << std::setw(2) << apid << std::dec << std::endl; + //*foundLen = remainingSize; + return mpsoc::INVALID_APID; + } + } + + // TODO: We should implement some way so this can also be used with the former implementation. + uint16_t sequenceCount = replyReader.getSequenceCount(); + if (sequenceCount != lastReplySequenceCount + 1) { + // TODO: Trigger event for possible missing reply packet to inform operator. + } + lastReplySequenceCount = sequenceCount; + + return result; +} + +ReturnValue_t FreshMpsocHandler::handleExecutionReport() { + ReturnValue_t result = returnvalue::OK; + auto& replyReader = comInterface.getSpReader(); + + switch (replyReader.getApid()) { + case (mpsoc::apid::EXE_SUCCESS): { + cmdDoneHandler(true, result); + break; + } + case (mpsoc::apid::EXE_FAILURE): { + DeviceCommandId_t commandId = activeCmdInfo.pendingCmd; + // Ensure idempotency: If the device is already in the mode, the command was successful. + if (mpsoc::getStatusFromRawData(replyReader.getFullData()) == + mpsoc::statusCode::TC_NOT_ALLOWED_IN_MODE) { + if ((activeCmdInfo.pendingCmdMpsocApid == mpsoc::apid::TC_MODE_SNAPSHOT && + submode == mpsoc::Submode::SNAPSHOT) or + (activeCmdInfo.pendingCmdMpsocApid == mpsoc::apid::TC_MODE_IDLE && + submode == mpsoc::Submode::IDLE_OR_NONE) or + (activeCmdInfo.pendingCmdMpsocApid == mpsoc::apid::TC_MODE_REPLAY && + submode == mpsoc::Submode::REPLAY)) { + cmdDoneHandler(true, returnvalue::OK); + return result; + } + } + if (commandId == DeviceHandlerIF::NO_COMMAND_ID) { + sif::warning << "FreshMpsocHandler::handleExecutionReport: Unknown Command ID" << std::endl; + } + uint16_t status = mpsoc::getStatusFromRawData(replyReader.getFullData()); + sif::warning << "MPSoC EXE Failure: " << mpsoc::getStatusString(status) << std::endl; + triggerEvent(mpsoc::EXE_FAILURE, commandId, status); + cmdDoneHandler(false, mpsoc::RECEIVED_EXE_FAILURE); + break; + } + default: { + sif::warning << "PlocMPSoCHandler::handleExecutionReport: Unknown APID" << std::endl; + result = returnvalue::FAILED; + break; + } + } + return result; +} + +ReturnValue_t FreshMpsocHandler::handleAckReport() { + ReturnValue_t result = returnvalue::OK; + auto& replyReader = comInterface.getSpReader(); + + switch (replyReader.getApid()) { + case mpsoc::apid::ACK_FAILURE: { + // DeviceCommandId_t commandId = getPendingCommand(); + uint16_t status = mpsoc::getStatusFromRawData(replyReader.getFullData()); + sif::warning << "MPSoC ACK Failure: " << mpsoc::getStatusString(status) << std::endl; + triggerEvent(mpsoc::ACK_FAILURE, activeCmdInfo.pendingCmd, status); + cmdDoneHandler(false, status); + break; + } + case mpsoc::apid::ACK_SUCCESS: { + break; + } + default: { + sif::error << "FreshMpsocHandler::handleAckReport: Invalid APID in ACK report" << std::endl; + result = returnvalue::FAILED; + break; + } + } + + return result; +} + +ReturnValue_t FreshMpsocHandler::getParameter(uint8_t domainId, uint8_t uniqueId, + ParameterWrapper* parameterWrapper, + const ParameterWrapper* newValues, + uint16_t startAtIndex) { + if (uniqueId == mpsoc::ParamId::SKIP_SUPV_ON_COMMANDING) { + uint8_t value = 0; + newValues->getElement(&value); + if (value > 1) { + return HasParametersIF::INVALID_VALUE; + } + parameterWrapper->set(skipSupvCommandingToOn); + return returnvalue::OK; + } + return FreshDeviceHandlerBase::getParameter(domainId, uniqueId, parameterWrapper, newValues, + startAtIndex); +} + +ReturnValue_t FreshMpsocHandler::reportReplyData(DeviceCommandId_t tmId) { + auto& replyReader = comInterface.getSpReader(); + if (activeCmdInfo.commandedBy != MessageQueueIF::NO_QUEUE) { + return actionHelper.reportData( + activeCmdInfo.commandedBy, tmId, replyReader.getFullData() + mpsoc::DATA_FIELD_OFFSET, + replyReader.getFullPacketLen() - mpsoc::DATA_FIELD_OFFSET - mpsoc::CRC_SIZE); + } + return returnvalue::OK; +} + +ReturnValue_t FreshMpsocHandler::handleGetHkReport() { + auto& spReader = comInterface.getSpReader(); + const uint8_t* dataStart = spReader.getFullData() + 6; + PoolReadGuard pg(&hkReport); + size_t deserLen = mpsoc::SIZE_TM_HK_REPORT; + SerializeIF::Endianness endianness = SerializeIF::Endianness::NETWORK; + ReturnValue_t result = + SerializeAdapter::deSerialize(&hkReport.status.value, &dataStart, &deserLen, endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.mode.value, &dataStart, &deserLen, endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.downlinkPwrOn.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.downlinkReplyActive.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.downlinkJesdSyncStatus.value, &dataStart, + &deserLen, endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.downlinkDacStatus.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = + SerializeAdapter::deSerialize(&hkReport.camStatus.value, &dataStart, &deserLen, endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.camSdiStatus.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = + SerializeAdapter::deSerialize(&hkReport.camFpgaTemp.value, &dataStart, &deserLen, endianness); + if (result != returnvalue::OK) { + return result; + } + result = + SerializeAdapter::deSerialize(&hkReport.sysmonTemp.value, &dataStart, &deserLen, endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonVccInt.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonVccAux.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonVccBram.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonVccPaux.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonVccPint.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonVccPdro.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = + SerializeAdapter::deSerialize(&hkReport.sysmonMb12V.value, &dataStart, &deserLen, endianness); + if (result != returnvalue::OK) { + return result; + } + result = + SerializeAdapter::deSerialize(&hkReport.sysmonMb3V3.value, &dataStart, &deserLen, endianness); + if (result != returnvalue::OK) { + return result; + } + result = + SerializeAdapter::deSerialize(&hkReport.sysmonMb1V8.value, &dataStart, &deserLen, endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonVcc12V.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = + SerializeAdapter::deSerialize(&hkReport.sysmonVcc5V.value, &dataStart, &deserLen, endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonVcc3V3.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonVcc3V3VA.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonVcc2V5DDR.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonVcc1V2DDR.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonVcc0V9.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonVcc0V6VTT.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonSafeCotsCur.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.sysmonNvm4XoCur.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.semUncorrectableErrs.value, &dataStart, + &deserLen, endianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&hkReport.semCorrectableErrs.value, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + result = + SerializeAdapter::deSerialize(&hkReport.semStatus.value, &dataStart, &deserLen, endianness); + if (result != returnvalue::OK) { + return result; + } + // Skip the weird filename + dataStart += 256; + result = SerializeAdapter::deSerialize(&hkReport.rebootMpsocRequired, &dataStart, &deserLen, + endianness); + if (result != returnvalue::OK) { + return result; + } + hkReport.setValidity(true, true); + return returnvalue::OK; +} + +bool FreshMpsocHandler::handleHwStartup() { +#if OBSW_MPSOC_JTAG_BOOT == 1 + uartIsolatorSwitch.pullHigh(); + startupState = StartupState::WAIT_CYCLES; + return true; +#endif + if (powerState == PowerState::IDLE) { + if (skipSupvCommandingToOn) { + powerState = PowerState::DONE; + } else { + if (supv::SUPV_ON) { + commandActionHelper.commandAction(supervisorHandler, supv::START_MPSOC); + supvTransitionCd.resetTimer(); + powerState = PowerState::PENDING_STARTUP; + } else { + triggerEvent(mpsoc::SUPV_NOT_ON, 1); + // Set back to OFF for now, failing the transition. + setMode(MODE_OFF); + } + } + } + if (powerState == PowerState::SUPV_FAILED) { + setMode(MODE_OFF); + powerState = PowerState::IDLE; + return false; + } + if (powerState == PowerState::PENDING_STARTUP) { + if (supvTransitionCd.hasTimedOut()) { + // Process with transition nonetheless.. + triggerEvent(mpsoc::SUPV_REPLY_TIMEOUT); + powerState = PowerState::DONE; + } else { + return false; + } + } + if (powerState == PowerState::DONE) { + // Wait a bit for the MPSoC to fully boot. + if (!mpsocBootTransitionCd.hasTimedOut()) { + return false; + } + uartIsolatorSwitch.pullHigh(); + comInterface.getComHelper().flushUartTxAndRxBuf(); + powerState = PowerState::IDLE; + } + return true; +} + +bool FreshMpsocHandler::handleHwShutdown() { + stopSpecialComHelper(); + uartIsolatorSwitch.pullLow(); +#if OBSW_MPSOC_JTAG_BOOT == 1 + powerState = PowerState::DONE; + return true; +#endif + + if (powerState == PowerState::IDLE) { + if (supv::SUPV_ON) { + commandActionHelper.commandAction(supervisorHandler, supv::SHUTDOWN_MPSOC); + supvTransitionCd.resetTimer(); + powerState = PowerState::PENDING_SHUTDOWN; + } else { + triggerEvent(mpsoc::SUPV_NOT_ON, 0); + powerState = PowerState::DONE; + } + } + if (powerState == PowerState::PENDING_SHUTDOWN) { + if (supvTransitionCd.hasTimedOut()) { + powerState = PowerState::DONE; + // Process with transition nonetheless.. + triggerEvent(mpsoc::SUPV_REPLY_TIMEOUT); + return true; + } else { + // Wait till power state is OFF. + return false; + } + } + return true; +} + +void FreshMpsocHandler::stopSpecialComHelper() { + specialComHelper.stopProcess(); + specialComHelperExecuting = false; +} diff --git a/linux/payload/FreshMpsocHandler.h b/linux/payload/FreshMpsocHandler.h new file mode 100644 index 00000000..88460764 --- /dev/null +++ b/linux/payload/FreshMpsocHandler.h @@ -0,0 +1,205 @@ +#include "fsfw/action/CommandsActionsIF.h" +#include "fsfw/devicehandlers/DeviceHandlerIF.h" +#include "fsfw/devicehandlers/FreshDeviceHandlerBase.h" +#include "fsfw/ipc/MessageQueueIF.h" +#include "fsfw/ipc/messageQueueDefinitions.h" +#include "fsfw/modes/ModeMessage.h" +#include "fsfw/objectmanager/SystemObjectIF.h" +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw_hal/linux/gpio/Gpio.h" +#include "linux/payload/MpsocCommunication.h" +#include "linux/payload/PlocMpsocSpecialComHelper.h" +#include "linux/payload/plocMpsocHelpers.h" + +class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsIF { + public: + enum OpCode { DEFAULT_OPERATION = 0, PARSE_TM = 1 }; + static constexpr uint32_t MPSOC_MODE_CMD_TIMEOUT_MS = 120000; + + FreshMpsocHandler(DhbConfig cfg, MpsocCommunication& comInterface, + PlocMpsocSpecialComHelper& specialComHelper, Gpio uartIsolatorSwitch, + object_id_t supervisorHandler); + + /** + * Periodic helper executed function, implemented by child class. + */ + void performDeviceOperation(uint8_t opCode) override; + + void performDefaultDeviceOperation(); + + /** + * Implemented by child class. Handle all command messages which are + * not health, mode, action or housekeeping messages. + * @param message + * @return + */ + ReturnValue_t handleCommandMessage(CommandMessage* message) override; + + ReturnValue_t initialize() override; + + private: + enum class StartupState { IDLE, HW_INIT, DONE } startupState = StartupState::IDLE; + enum class PowerState { IDLE, PENDING_STARTUP, PENDING_SHUTDOWN, SUPV_FAILED, DONE }; + + enum TransitionState { NONE, TO_ON, TO_OFF, SUBMODE } transitionState = TransitionState::NONE; + MpsocCommunication& comInterface; + PlocMpsocSpecialComHelper& specialComHelper; + MessageQueueIF* eventQueue = nullptr; + SourceSequenceCounter commandSequenceCount = SourceSequenceCounter(0); + MessageQueueIF* commandActionHelperQueue = nullptr; + CommandActionHelper commandActionHelper; + Gpio uartIsolatorSwitch; + mpsoc::HkReport hkReport; + object_id_t supervisorHandler; + + Countdown mpsocBootTransitionCd = Countdown(6500); + Countdown supvTransitionCd = Countdown(3000); + + PoolEntry peStatus = PoolEntry(); + PoolEntry peMode = PoolEntry(); + PoolEntry peDownlinkPwrOn = PoolEntry(); + PoolEntry peDownlinkReplyActive = PoolEntry(); + PoolEntry peDownlinkJesdSyncStatus = PoolEntry(); + PoolEntry peDownlinkDacStatus = PoolEntry(); + PoolEntry peCameraStatus = PoolEntry(); + PoolEntry peCameraSdiStatus = PoolEntry(); + PoolEntry peCameraFpgaTemp = PoolEntry(); + PoolEntry peCameraSocTemp = PoolEntry(); + PoolEntry peSysmonTemp = PoolEntry(); + PoolEntry peSysmonVccInt = PoolEntry(); + PoolEntry peSysmonVccAux = PoolEntry(); + PoolEntry peSysmonVccBram = PoolEntry(); + PoolEntry peSysmonVccPaux = PoolEntry(); + PoolEntry peSysmonVccPint = PoolEntry(); + PoolEntry peSysmonVccPdro = PoolEntry(); + PoolEntry peSysmonMb12V = PoolEntry(); + PoolEntry peSysmonMb3V3 = PoolEntry(); + PoolEntry peSysmonMb1V8 = PoolEntry(); + PoolEntry peSysmonVcc12V = PoolEntry(); + PoolEntry peSysmonVcc5V = PoolEntry(); + PoolEntry peSysmonVcc3V3 = PoolEntry(); + PoolEntry peSysmonVcc3V3VA = PoolEntry(); + PoolEntry peSysmonVcc2V5DDR = PoolEntry(); + PoolEntry peSysmonVcc1V2DDR = PoolEntry(); + PoolEntry peSysmonVcc0V9 = PoolEntry(); + PoolEntry peSysmonVcc0V6VTT = PoolEntry(); + PoolEntry peSysmonSafeCotsCur = PoolEntry(); + PoolEntry peSysmonNvm4XoCur = PoolEntry(); + PoolEntry peSemUncorrectableErrs = PoolEntry(); + PoolEntry peSemCorrectableErrs = PoolEntry(); + PoolEntry peSemStatus = PoolEntry(); + PoolEntry peRebootMpsocRequired = PoolEntry(); + + PowerState powerState; + bool specialComHelperExecuting = false; + + struct ActionCommandInfo { + Countdown cmdCountdown = Countdown(mpsoc::DEFAULT_CMD_TIMEOUT_MS); + bool pending = false; + MessageQueueId_t commandedBy = MessageQueueIF::NO_QUEUE; + DeviceCommandId_t pendingCmd = DeviceHandlerIF::NO_COMMAND_ID; + uint16_t pendingCmdMpsocApid = 0; + + void reset() { + pending = false; + commandedBy = MessageQueueIF::NO_QUEUE; + pendingCmd = DeviceHandlerIF::NO_COMMAND_ID; + } + + void start(DeviceCommandId_t commandId, MessageQueueId_t commandedBy) { + pending = true; + cmdCountdown.resetTimer(); + pendingCmd = commandId; + this->commandedBy = commandedBy; + } + } activeCmdInfo; + + uint8_t commandBuffer[mpsoc::MAX_COMMAND_SIZE]; + SpacePacketCreator creator; + ploc::SpTcParams spParams = ploc::SpTcParams(creator); + Mode_t targetMode = HasModesIF::MODE_UNDEFINED; + Submode_t targetSubmode = 0; + + struct TmMemReadReport { + static const uint8_t FIX_SIZE = 14; + size_t rememberRequestedSize = 0; + }; + + TmMemReadReport tmMemReadReport; + uint32_t lastReplySequenceCount = 0; + uint8_t skipSupvCommandingToOn = false; + + // HK manager abstract functions. + LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; + ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; + + // Mode abstract functions + ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, + uint32_t* msToReachTheMode) override; + // Action override. Forward to user. + ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) override; + + /** + * @overload + * @param submode + */ + void startTransition(Mode_t newMode, Submode_t submode) override; + + ReturnValue_t performDeviceOperationPreQueueHandling(uint8_t opCode) override; + + // CommandsActionsIF overrides. + MessageQueueIF* getCommandQueuePtr() override; + + void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) override; + void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) override; + void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) override; + void completionSuccessfulReceived(ActionId_t actionId) override; + void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) override; + ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper, + const ParameterWrapper* newValues, uint16_t startAtIndex) override; + + void handleActionCommandFailure(ActionId_t actionId, ReturnValue_t returnCode); + ReturnValue_t executeRegularCmd(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t dataLen); + void handleTransitionToOn(); + void handleTransitionToOff(); + + ReturnValue_t commandTcModeReplay(); + ReturnValue_t commandTcMemWrite(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t commandTcMemRead(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t commandTcFlashDelete(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t commandTcReplayStart(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t commandTcReplayStop(); + ReturnValue_t commandTcDownlinkPwrOn(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t commandTcDownlinkPwrOff(); + ReturnValue_t commandTcGetHkReport(); + ReturnValue_t commandTcGetDirContent(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t commandTcReplayWriteSequence(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t commandTcCamCmdSend(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t commandTcModeIdle(); + ReturnValue_t commandTcCamTakePic(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t commandTcSimplexStreamFile(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t commandTcSimplexStoreFile(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t commandTcDownlinkDataModulate(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t commandTcModeSnapshot(); + + ReturnValue_t finishAndSendTc(DeviceCommandId_t cmdId, mpsoc::TcBase& tcBase, + uint32_t cmdCountdown = mpsoc::DEFAULT_CMD_TIMEOUT_MS); + void handleEvent(EventMessage* eventMessage); + void cmdDoneHandler(bool success, ReturnValue_t result); + ReturnValue_t handleDeviceReply(); + ReturnValue_t handleAckReport(); + ReturnValue_t handleExecutionReport(); + void sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status); + ReturnValue_t reportReplyData(DeviceCommandId_t tmId); + ReturnValue_t handleGetHkReport(); + bool handleHwStartup(); + bool handleHwShutdown(); + + void stopSpecialComHelper(); + void commandSubmodeTransition(); + void commonSpecialComInit(); + void commonSpecialComStop(); +}; diff --git a/linux/payload/FreshSupvHandler.cpp b/linux/payload/FreshSupvHandler.cpp index 4bf89f01..1252f9d8 100644 --- a/linux/payload/FreshSupvHandler.cpp +++ b/linux/payload/FreshSupvHandler.cpp @@ -1299,7 +1299,7 @@ void FreshSupvHandler::handleExecutionFailureReport(ActiveCmdInfo& info, Executi triggerEvent(SUPV_EXE_FAILURE, info.commandId, static_cast(report.getStatusCode())); } if (info.commandedBy) { - actionHelper.finish(false, info.commandedBy, info.commandId, report.getStatusCode()); + actionHelper.finish(false, info.commandedBy, info.commandId, result::RECEIVED_EXE_FAILURE); } info.isPending = false; } diff --git a/linux/payload/MpsocCommunication.cpp b/linux/payload/MpsocCommunication.cpp new file mode 100644 index 00000000..edb88225 --- /dev/null +++ b/linux/payload/MpsocCommunication.cpp @@ -0,0 +1,75 @@ +#include "MpsocCommunication.h" + +#include "fsfw/globalfunctions/CRC.h" +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" +#include "fsfw/tmtcpacket/ccsds/header.h" +#include "linux/payload/plocMpsocHelpers.h" +#include "unistd.h" + +MpsocCommunication::MpsocCommunication(object_id_t objectId, SerialConfig cfg) + : SystemObject(objectId), readRingBuf(4096, true), helper(cfg) {} + +ReturnValue_t MpsocCommunication::initialize() { return helper.initialize(); } + +ReturnValue_t MpsocCommunication::send(const uint8_t* data, size_t dataLen) { + if (MPSOC_LOW_LEVEL_TX_WIRETAPPING) { + sif::debug << "SEND MPSOC packet with size " << dataLen << std::endl; + } + return helper.send(data, dataLen); +} + +ReturnValue_t MpsocCommunication::parseAndRetrieveNextPacket() { + // We do not have a data link layer, so this whole thing is a mess in any case.. + // But basically, we try to parse space packets from the internal ring buffer and trasnfer + // them to the higher level device handler. The CRC check is performed here as well, with + // few other ways to detect if we even have a valid packet. + size_t availableReadData = readRingBuf.getAvailableReadData(); + // Minimum valid size for a space packet header. + if (availableReadData < ccsds::HEADER_LEN + 1) { + return returnvalue::OK; + } + readRingBuf.readData(readBuf, availableReadData); + spReader.setReadOnlyData(readBuf, sizeof(readBuf)); + auto res = spReader.checkSize(); + if (res != returnvalue::OK) { + return res; + } + // The packet might be garbage, with no way to recover without a data link layer. + if (spReader.getFullPacketLen() > 4096) { + readRingBuf.clear(); + // TODO: Maybe we should also clear the serial input buffer in Linux? + return FAULTY_PACKET_SIZE; + } + if (availableReadData < spReader.getFullPacketLen()) { + // Might be split packet where the rest still has to be read. + return returnvalue::OK; + } + if (CRC::crc16ccitt(readBuf, spReader.getFullPacketLen()) != 0) { + // Possibly invalid packet. We can not even trust the detected packet length. + // Just clear the whole read buffer as well. + readRingBuf.clear(); + triggerEvent(mpsoc::CRC_FAILURE); + return CRC_CHECK_FAILED; + } + readRingBuf.deleteData(spReader.getFullPacketLen()); + return PACKET_RECEIVED; +} + +ReturnValue_t MpsocCommunication::readSerialInterface() { + int bytesRead = read(helper.rawFd(), readBuf, sizeof(readBuf)); + if (bytesRead < 0) { + return returnvalue::FAILED; + } + if (bytesRead > 0) { + if (MPSOC_LOW_LEVEL_RX_WIRETAPPING) { + sif::debug << "Read " << bytesRead << " bytes on the MPSoC interface" << std::endl; + } + return readRingBuf.writeData(readBuf, bytesRead); + } + return returnvalue::OK; +} + +const SpacePacketReader& MpsocCommunication::getSpReader() const { return spReader; } + +SerialCommunicationHelper& MpsocCommunication::getComHelper() { return helper; } diff --git a/linux/payload/MpsocCommunication.h b/linux/payload/MpsocCommunication.h new file mode 100644 index 00000000..3e26051e --- /dev/null +++ b/linux/payload/MpsocCommunication.h @@ -0,0 +1,44 @@ + +#pragma once + +#include + +#include "eive/resultClassIds.h" +#include "fsfw/container/SimpleRingBuffer.h" +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" +#include "linux/payload/SerialCommunicationHelper.h" + +static constexpr bool MPSOC_LOW_LEVEL_TX_WIRETAPPING = true; +static constexpr bool MPSOC_LOW_LEVEL_RX_WIRETAPPING = true; + +class MpsocCommunication : public SystemObject { + public: + static const uint8_t CLASS_ID = CLASS_ID::PLOC_MPSOC_COM; + static constexpr ReturnValue_t PACKET_RECEIVED = returnvalue::makeCode(CLASS_ID, 0); + static constexpr ReturnValue_t FAULTY_PACKET_SIZE = returnvalue::makeCode(CLASS_ID, 1); + static constexpr ReturnValue_t CRC_CHECK_FAILED = returnvalue::makeCode(CLASS_ID, 2); + + MpsocCommunication(object_id_t objectId, SerialConfig cfg); + ReturnValue_t initialize() override; + + ReturnValue_t send(const uint8_t* data, size_t dataLen); + + // Should be called periodically to transfer the received data from the MPSoC from the Linux + // buffer to the internal ring buffer for further processing. + ReturnValue_t readSerialInterface(); + + // Parses the internal ring buffer for packets and checks whether a packet was received. + ReturnValue_t parseAndRetrieveNextPacket(); + + // Can be used to read the parse packet, if one was received. + const SpacePacketReader& getSpReader() const; + + SerialCommunicationHelper& getComHelper(); + + private: + SpacePacketReader spReader; + uint8_t readBuf[4096]; + SimpleRingBuffer readRingBuf; + SerialCommunicationHelper helper; +}; diff --git a/linux/payload/PlocMpsocSpecialComHelper.cpp b/linux/payload/PlocMpsocSpecialComHelper.cpp index 66712a90..c3a70cd6 100644 --- a/linux/payload/PlocMpsocSpecialComHelper.cpp +++ b/linux/payload/PlocMpsocSpecialComHelper.cpp @@ -6,16 +6,21 @@ #include #include +#include "fsfw/serviceinterface/ServiceInterfacePrinter.h" +#include "fsfw/serviceinterface/ServiceInterfaceStream.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" +#include "linux/payload/MpsocCommunication.h" +#include "linux/payload/plocMpsocHelpers.h" + #ifdef XIPHOS_Q7S #include "bsp_q7s/fs/FilesystemHelper.h" #endif -#include "mission/utility/Timestamp.h" - using namespace ploc; -PlocMpsocSpecialComHelper::PlocMpsocSpecialComHelper(object_id_t objectId) - : SystemObject(objectId) { +PlocMpsocSpecialComHelper::PlocMpsocSpecialComHelper(object_id_t objectId, + MpsocCommunication& comInterface) + : SystemObject(objectId), comInterface(comInterface) { spParams.buf = commandBuffer; spParams.maxSize = sizeof(commandBuffer); } @@ -48,9 +53,9 @@ ReturnValue_t PlocMpsocSpecialComHelper::performOperation(uint8_t operationCode) case InternalState::FLASH_WRITE: { result = performFlashWrite(); if (result == returnvalue::OK) { - triggerEvent(MPSOC_FLASH_WRITE_SUCCESSFUL, sequenceCount->get()); + triggerEvent(MPSOC_FLASH_WRITE_SUCCESSFUL, txSequenceCount.get()); } else { - triggerEvent(MPSOC_FLASH_WRITE_FAILED, sequenceCount->get()); + triggerEvent(MPSOC_FLASH_WRITE_FAILED, txSequenceCount.get()); } internalState = InternalState::IDLE; break; @@ -58,9 +63,10 @@ ReturnValue_t PlocMpsocSpecialComHelper::performOperation(uint8_t operationCode) case InternalState::FLASH_READ: { result = performFlashRead(); if (result == returnvalue::OK) { - triggerEvent(MPSOC_FLASH_READ_SUCCESSFUL, sequenceCount->get()); + triggerEvent(MPSOC_FLASH_READ_SUCCESSFUL, txSequenceCount.get()); } else { - triggerEvent(MPSOC_FLASH_READ_FAILED, sequenceCount->get()); + sif::printWarning("PLOC MPSoC Helper: Flash read failed with code %04x\n", result); + triggerEvent(MPSOC_FLASH_READ_FAILED, txSequenceCount.get(), result); } internalState = InternalState::IDLE; break; @@ -72,19 +78,12 @@ ReturnValue_t PlocMpsocSpecialComHelper::performOperation(uint8_t operationCode) } } -ReturnValue_t PlocMpsocSpecialComHelper::setComIF(DeviceCommunicationIF* communicationInterface_) { - uartComIF = dynamic_cast(communicationInterface_); - if (uartComIF == nullptr) { - sif::warning << "PlocMPSoCHelper::initialize: Invalid uart com if" << std::endl; - return returnvalue::FAILED; - } - return returnvalue::OK; +void PlocMpsocSpecialComHelper::setCommandSequenceCount(uint16_t sequenceCount_) { + txSequenceCount.set(sequenceCount_); } -void PlocMpsocSpecialComHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; } - -void PlocMpsocSpecialComHelper::setSequenceCount(SourceSequenceCounter* sequenceCount_) { - sequenceCount = sequenceCount_; +uint16_t PlocMpsocSpecialComHelper::getCommandSequenceCount() const { + return txSequenceCount.get(); } ReturnValue_t PlocMpsocSpecialComHelper::startFlashWrite(std::string obcFile, @@ -117,7 +116,8 @@ ReturnValue_t PlocMpsocSpecialComHelper::startFlashRead(std::string obcFile, std void PlocMpsocSpecialComHelper::resetHelper() { spParams.buf = commandBuffer; terminate = false; - uartComIF->flushUartRxBuffer(comCookie); + auto& helper = comInterface.getComHelper(); + helper.flushUartRxBuffer(); } void PlocMpsocSpecialComHelper::stopProcess() { terminate = true; } @@ -155,7 +155,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashWrite() { file.read(reinterpret_cast(fileBuf.data()), dataLength); bytesRead += dataLength; remainingSize -= dataLength; - mpsoc::TcFlashWrite tc(spParams, *sequenceCount); + mpsoc::TcFlashWrite tc(spParams, txSequenceCount); result = tc.setPayload(fileBuf.data(), dataLength); if (result != returnvalue::OK) { return result; @@ -164,7 +164,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashWrite() { if (result != returnvalue::OK) { return result; } - (*sequenceCount)++; + txSequenceCount.increment(); result = handlePacketTransmissionNoReply(tc); if (result != returnvalue::OK) { return result; @@ -203,7 +203,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashRead() { std::filesystem::remove(flashReadAndWrite.obcFile, e); return FILE_READ_ERROR; } - mpsoc::TcFlashRead flashReadRequest(spParams, *sequenceCount); + mpsoc::TcFlashRead flashReadRequest(spParams, txSequenceCount); result = flashReadRequest.setPayload(nextReadSize); if (result != returnvalue::OK) { std::filesystem::remove(flashReadAndWrite.obcFile, e); @@ -214,7 +214,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashRead() { std::filesystem::remove(flashReadAndWrite.obcFile, e); return result; } - (*sequenceCount)++; + txSequenceCount.increment(); result = handlePacketTransmissionFlashRead(flashReadRequest, ofile, nextReadSize); if (result != returnvalue::OK) { std::filesystem::remove(flashReadAndWrite.obcFile, e); @@ -231,7 +231,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashRead() { ReturnValue_t PlocMpsocSpecialComHelper::flashfopen(uint8_t mode) { spParams.buf = commandBuffer; - mpsoc::FlashFopen flashFopen(spParams, *sequenceCount); + mpsoc::TcFlashFopen flashFopen(spParams, txSequenceCount); ReturnValue_t result = flashFopen.setPayload(flashReadAndWrite.mpsocFile, mode); if (result != returnvalue::OK) { return result; @@ -240,7 +240,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::flashfopen(uint8_t mode) { if (result != returnvalue::OK) { return result; } - (*sequenceCount)++; + txSequenceCount.increment(); result = handlePacketTransmissionNoReply(flashFopen); if (result != returnvalue::OK) { return result; @@ -250,12 +250,12 @@ ReturnValue_t PlocMpsocSpecialComHelper::flashfopen(uint8_t mode) { ReturnValue_t PlocMpsocSpecialComHelper::flashfclose() { spParams.buf = commandBuffer; - mpsoc::FlashFclose flashFclose(spParams, *sequenceCount); + mpsoc::TcFlashFclose flashFclose(spParams, txSequenceCount); ReturnValue_t result = flashFclose.finishPacket(); if (result != returnvalue::OK) { return result; } - (*sequenceCount)++; + txSequenceCount.increment(); result = handlePacketTransmissionNoReply(flashFclose); if (result != returnvalue::OK) { return result; @@ -278,6 +278,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handlePacketTransmissionFlashRead(mpsoc if (result != returnvalue::OK) { return result; } + auto& spReader = comInterface.getSpReader(); // We have the nominal case where the flash read report appears first, or the case where we // get an EXE failure immediately. @@ -288,7 +289,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handlePacketTransmissionFlashRead(mpsoc } return handleExe(); } else if (spReader.getApid() == mpsoc::apid::EXE_FAILURE) { - handleExeFailure(); + handleExeFailure(spReader); } else { triggerEvent(MPSOC_EXE_INVALID_APID, spReader.getApid(), static_cast(internalState)); sif::warning << "PLOC MPSoC: Expected execution report " @@ -311,8 +312,8 @@ ReturnValue_t PlocMpsocSpecialComHelper::handlePacketTransmissionNoReply(ploc::S } ReturnValue_t PlocMpsocSpecialComHelper::sendCommand(ploc::SpTcBase& tc) { - ReturnValue_t result = returnvalue::OK; - result = uartComIF->sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen()); + ReturnValue_t result = comInterface.send(tc.getFullPacket(), tc.getFullPacketLen()); + mpsoc::printTxPacket(tc); if (result != returnvalue::OK) { sif::warning << "PlocMPSoCHelper::sendCommand: Failed to send command" << std::endl; triggerEvent(MPSOC_SENDING_COMMAND_FAILED, result, static_cast(internalState)); @@ -331,6 +332,8 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleAck() { if (result != returnvalue::OK) { return result; } + const auto& spReader = comInterface.getSpReader(); + uint16_t apid = spReader.getApid(); if (apid != mpsoc::apid::ACK_SUCCESS) { handleAckApidFailure(spReader); @@ -339,7 +342,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleAck() { return returnvalue::OK; } -void PlocMpsocSpecialComHelper::handleAckApidFailure(const ploc::SpTmReader& reader) { +void PlocMpsocSpecialComHelper::handleAckApidFailure(const SpacePacketReader& reader) { uint16_t apid = reader.getApid(); if (apid == mpsoc::apid::ACK_FAILURE) { uint16_t status = mpsoc::getStatusFromRawData(reader.getFullData()); @@ -363,9 +366,10 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleExe() { if (result != returnvalue::OK) { return result; } + const auto& spReader = comInterface.getSpReader(); uint16_t apid = spReader.getApid(); if (apid == mpsoc::apid::EXE_FAILURE) { - handleExeFailure(); + handleExeFailure(spReader); return returnvalue::FAILED; } else if (apid != mpsoc::apid::EXE_SUCCESS) { triggerEvent(MPSOC_EXE_INVALID_APID, apid, static_cast(internalState)); @@ -375,7 +379,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleExe() { return returnvalue::OK; } -void PlocMpsocSpecialComHelper::handleExeFailure() { +void PlocMpsocSpecialComHelper::handleExeFailure(const SpacePacketReader& spReader) { uint16_t status = mpsoc::getStatusFromRawData(spReader.getFullData()); sif::warning << "PLOC MPSoC EXE Failure: " << mpsoc::getStatusString(status) << std::endl; triggerEvent(MPSOC_EXE_FAILURE_REPORT, static_cast(internalState)); @@ -384,46 +388,32 @@ void PlocMpsocSpecialComHelper::handleExeFailure() { ReturnValue_t PlocMpsocSpecialComHelper::handleTmReception() { ReturnValue_t result = returnvalue::OK; tmCountdown.resetTimer(); - size_t readBytes = 0; - size_t currentBytes = 0; uint32_t usleepDelay = 5; - size_t fullPacketLen = 0; while (true) { if (tmCountdown.hasTimedOut()) { triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs()); return returnvalue::FAILED; } - result = receive(tmBuf.data() + readBytes, 6, ¤tBytes); + result = tryReceiveNextReply(); + if (result == MpsocCommunication::PACKET_RECEIVED) { + // Need to convert this, we are faking a synchronous API here. + result = returnvalue::OK; + break; + } if (result != returnvalue::OK) { + if (result == MpsocCommunication::FAULTY_PACKET_SIZE) { + sif::printWarning("PLOC MPSoC Helper: retrieving next reply failed: faulty packet size\n"); + } else if (result == MpsocCommunication::CRC_CHECK_FAILED) { + sif::printWarning("PLOC MPSoC Helper: retrieving next reply failed: CRC check failed\n"); + } + sif::printWarning("PLOC MPSoC Helper: retrieving next reply failed with code %d\n", result); return result; } - spReader.setReadOnlyData(tmBuf.data(), tmBuf.size()); - fullPacketLen = spReader.getFullPacketLen(); - readBytes += currentBytes; - if (readBytes == 6) { - break; - } usleep(usleepDelay); if (usleepDelay < 200000) { usleepDelay *= 4; } } - while (true) { - if (tmCountdown.hasTimedOut()) { - triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs()); - return returnvalue::FAILED; - } - result = receive(tmBuf.data() + readBytes, fullPacketLen - readBytes, ¤tBytes); - readBytes += currentBytes; - if (fullPacketLen == readBytes) { - break; - } - usleep(usleepDelay); - if (usleepDelay < 200000) { - usleepDelay *= 4; - } - } - // arrayprinter::print(tmBuf.data(), readBytes); return result; } @@ -433,6 +423,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleFlashReadReply(std::ofstream& ofi if (result != returnvalue::OK) { return result; } + auto& spReader = comInterface.getSpReader(); uint16_t apid = spReader.getApid(); if (apid != mpsoc::apid::TM_FLASH_READ_REPORT) { triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_APID_ERROR); @@ -498,47 +489,25 @@ ReturnValue_t PlocMpsocSpecialComHelper::startFlashReadOrWriteBase(std::string o } ReturnValue_t PlocMpsocSpecialComHelper::checkReceivedTm() { + const auto& spReader = comInterface.getSpReader(); ReturnValue_t result = spReader.checkSize(); if (result != returnvalue::OK) { sif::error << "PLOC MPSoC: Size check on received TM failed" << std::endl; triggerEvent(MPSOC_TM_SIZE_ERROR); return result; } - result = spReader.checkCrc(); - if (result != returnvalue::OK) { - sif::warning << "PLOC MPSoC: CRC check failed" << std::endl; - triggerEvent(MPSOC_TM_CRC_MISSMATCH, *sequenceCount); - return result; - } - uint16_t recvSeqCnt = spReader.getSequenceCount(); - if (recvSeqCnt != *sequenceCount) { - triggerEvent(MPSOC_HELPER_SEQ_CNT_MISMATCH, *sequenceCount, recvSeqCnt); - *sequenceCount = recvSeqCnt; - } - // This sequence count ping pong does not make any sense but it is how the MPSoC expects it. - (*sequenceCount)++; + rxSequenceCount = spReader.getSequenceCount(); + mpsoc::printRxPacket(spReader); return returnvalue::OK; } -ReturnValue_t PlocMpsocSpecialComHelper::receive(uint8_t* data, size_t requestBytes, - size_t* readBytes) { +ReturnValue_t PlocMpsocSpecialComHelper::tryReceiveNextReply() { ReturnValue_t result = returnvalue::OK; - uint8_t* buffer = nullptr; - result = uartComIF->requestReceiveMessage(comCookie, requestBytes); + result = comInterface.readSerialInterface(); if (result != returnvalue::OK) { - sif::warning << "PlocMPSoCHelper::receive: Failed to request reply" << std::endl; triggerEvent(MPSOC_HELPER_REQUESTING_REPLY_FAILED, result, static_cast(static_cast(internalState))); return returnvalue::FAILED; } - result = uartComIF->readReceivedMessage(comCookie, &buffer, readBytes); - if (result != returnvalue::OK) { - sif::warning << "PlocMPSoCHelper::receive: Failed to read received message" << std::endl; - triggerEvent(MPSOC_HELPER_READING_REPLY_FAILED, result, static_cast(internalState)); - return returnvalue::FAILED; - } - if (*readBytes > 0) { - std::memcpy(data, buffer, *readBytes); - } - return result; + return comInterface.parseAndRetrieveNextPacket(); } diff --git a/linux/payload/PlocMpsocSpecialComHelper.h b/linux/payload/PlocMpsocSpecialComHelper.h index bc6bec8c..dce6892b 100644 --- a/linux/payload/PlocMpsocSpecialComHelper.h +++ b/linux/payload/PlocMpsocSpecialComHelper.h @@ -6,14 +6,13 @@ #include -#include "OBSWConfig.h" -#include "fsfw/devicehandlers/CookieIF.h" #include "fsfw/objectmanager/SystemObject.h" #include "fsfw/osal/linux/BinarySemaphore.h" #include "fsfw/returnvalues/returnvalue.h" #include "fsfw/tasks/ExecutableObjectIF.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" #include "fsfw/tmtcservices/SourceSequenceCounter.h" -#include "fsfw_hal/linux/serial/SerialComIF.h" +#include "linux/payload/MpsocCommunication.h" #ifdef XIPHOS_Q7S #include "bsp_q7s/fs/SdCardManager.h" #endif @@ -83,15 +82,12 @@ class PlocMpsocSpecialComHelper : public SystemObject, public ExecutableObjectIF FLASH_READ_READLEN_ERROR = 2 }; - PlocMpsocSpecialComHelper(object_id_t objectId); + PlocMpsocSpecialComHelper(object_id_t objectId, MpsocCommunication& comInterface); virtual ~PlocMpsocSpecialComHelper(); ReturnValue_t initialize() override; ReturnValue_t performOperation(uint8_t operationCode = 0) override; - ReturnValue_t setComIF(DeviceCommunicationIF* communicationInterface_); - void setComCookie(CookieIF* comCookie_); - /** * @brief Starts flash write sequence * @@ -118,7 +114,8 @@ class PlocMpsocSpecialComHelper : public SystemObject, public ExecutableObjectIF /** * @brief Sets the sequence count object responsible for the sequence count handling */ - void setSequenceCount(SourceSequenceCounter* sequenceCount_); + void setCommandSequenceCount(uint16_t sequenceCount_); + uint16_t getCommandSequenceCount() const; private: static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_MPSOC_HELPER; @@ -169,12 +166,14 @@ class PlocMpsocSpecialComHelper : public SystemObject, public ExecutableObjectIF * Communication interface of MPSoC responsible for low level access. Must be set by the * MPSoC Handler. */ - SerialComIF* uartComIF = nullptr; + // SerialComIF* uartComIF = nullptr; // Communication cookie. Must be set by the MPSoC Handler - CookieIF* comCookie = nullptr; + // CookieIF* comCookie = nullptr; + MpsocCommunication& comInterface; // Sequence count, must be set by Ploc MPSoC Handler - SourceSequenceCounter* sequenceCount = nullptr; - ploc::SpTmReader spReader; + // ploc::SpTmReader spReader; + uint16_t rxSequenceCount = 0; + SourceSequenceCounter txSequenceCount = 0; void resetHelper(); ReturnValue_t performFlashWrite(); @@ -186,13 +185,13 @@ class PlocMpsocSpecialComHelper : public SystemObject, public ExecutableObjectIF size_t expectedReadLen); ReturnValue_t handleFlashReadReply(std::ofstream& ofile, size_t expectedReadLen); ReturnValue_t sendCommand(ploc::SpTcBase& tc); - ReturnValue_t receive(uint8_t* data, size_t requestBytes, size_t* readBytes); + ReturnValue_t tryReceiveNextReply(); ReturnValue_t handleAck(); ReturnValue_t handleExe(); ReturnValue_t startFlashReadOrWriteBase(std::string obcFile, std::string mpsocFile); ReturnValue_t fileCheck(std::string obcFile); - void handleAckApidFailure(const ploc::SpTmReader& reader); - void handleExeFailure(); + void handleAckApidFailure(const SpacePacketReader& reader); + void handleExeFailure(const SpacePacketReader& reader); ReturnValue_t handleTmReception(); ReturnValue_t checkReceivedTm(); }; diff --git a/linux/payload/PlocSupvUartMan.cpp b/linux/payload/PlocSupvUartMan.cpp index 56bb3dd5..8009e89e 100644 --- a/linux/payload/PlocSupvUartMan.cpp +++ b/linux/payload/PlocSupvUartMan.cpp @@ -437,6 +437,8 @@ ReturnValue_t PlocSupvUartManager::writeUpdatePackets() { // Useful to allow restarting the update triggerEvent(SUPV_UPDATE_PROGRESS, buildProgParams1(progPercent, update.sequenceCount), update.bytesWritten); + sif::info << "PLOC SUPV update progress " << (int)progPercent << " % at " + << update.bytesWritten << " bytes" << std::endl; } } supv::WriteMemory packet(spParams); diff --git a/linux/payload/SerialCommunicationHelper.cpp b/linux/payload/SerialCommunicationHelper.cpp new file mode 100644 index 00000000..cb35e03f --- /dev/null +++ b/linux/payload/SerialCommunicationHelper.cpp @@ -0,0 +1,126 @@ +#include "SerialCommunicationHelper.h" + +#include +#include +#include +#include + +#include + +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw_hal/linux/serial/helper.h" + +SerialCommunicationHelper::SerialCommunicationHelper(SerialConfig cfg) : cfg(cfg) {} + +ReturnValue_t SerialCommunicationHelper::initialize() { + fd = configureUartPort(); + if (fd < 0) { + return returnvalue::FAILED; + } + return returnvalue::OK; +} + +int SerialCommunicationHelper::rawFd() const { return fd; } + +ReturnValue_t SerialCommunicationHelper::send(const uint8_t* data, size_t dataLen) { + if (write(fd, data, dataLen) != static_cast(dataLen)) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "UartComIF::sendMessage: Failed to send data with error code " << errno + << ": Error description: " << strerror(errno) << std::endl; +#endif + return returnvalue::FAILED; + } + return returnvalue::OK; +} + +int SerialCommunicationHelper::configureUartPort() { + struct termios options = {}; + + int flags = O_RDWR; + if (cfg.getUartMode() == UartModes::CANONICAL) { + // In non-canonical mode, don't specify O_NONBLOCK because these properties will be + // controlled by the VTIME and VMIN parameters and O_NONBLOCK would override this + flags |= O_NONBLOCK; + } + int fd = open(cfg.getDeviceFile().c_str(), flags); + + if (fd < 0) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "UartComIF::configureUartPort: Failed to open uart " + << cfg.getDeviceFile().c_str() + + << "with error code " << errno << strerror(errno) << std::endl; +#endif + return fd; + } + + /* Read in existing settings */ + if (tcgetattr(fd, &options) != 0) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "UartComIF::configureUartPort: Error " << errno + << "from tcgetattr: " << strerror(errno) << std::endl; +#endif + return fd; + } + + serial::setParity(options, cfg.getParity()); + serial::setStopbits(options, cfg.getStopBits()); + serial::setBitsPerWord(options, cfg.getBitsPerWord()); + setFixedOptions(&options); + serial::setMode(options, cfg.getUartMode()); + tcflush(fd, TCIFLUSH); + + /* Sets uart to non-blocking mode. Read returns immediately when there are no data available */ + options.c_cc[VTIME] = 0; + options.c_cc[VMIN] = 0; + + serial::setBaudrate(options, cfg.getBaudrate()); + + /* Save option settings */ + if (tcsetattr(fd, TCSANOW, &options) != 0) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "UartComIF::configureUartPort: Failed to set options with error " << errno + << ": " << strerror(errno); +#endif + return fd; + } + return fd; +} + +void SerialCommunicationHelper::setFixedOptions(struct termios* options) { + /* Disable RTS/CTS hardware flow control */ + options->c_cflag &= ~CRTSCTS; + /* Turn on READ & ignore ctrl lines (CLOCAL = 1) */ + options->c_cflag |= CREAD | CLOCAL; + /* Disable echo */ + options->c_lflag &= ~ECHO; + /* Disable erasure */ + options->c_lflag &= ~ECHOE; + /* Disable new-line echo */ + options->c_lflag &= ~ECHONL; + /* Disable interpretation of INTR, QUIT and SUSP */ + options->c_lflag &= ~ISIG; + /* Turn off s/w flow ctrl */ + options->c_iflag &= ~(IXON | IXOFF | IXANY); + /* Disable any special handling of received bytes */ + options->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); + /* Prevent special interpretation of output bytes (e.g. newline chars) */ + options->c_oflag &= ~OPOST; + /* Prevent conversion of newline to carriage return/line feed */ + options->c_oflag &= ~ONLCR; +} + +ReturnValue_t SerialCommunicationHelper::flushUartRxBuffer() { + serial::flushRxBuf(fd); + return returnvalue::OK; +} + +ReturnValue_t SerialCommunicationHelper::flushUartTxBuffer() { + serial::flushTxBuf(fd); + return returnvalue::OK; +} + +ReturnValue_t SerialCommunicationHelper::flushUartTxAndRxBuf() { + serial::flushTxRxBuf(fd); + return returnvalue::OK; +} diff --git a/linux/payload/SerialCommunicationHelper.h b/linux/payload/SerialCommunicationHelper.h new file mode 100644 index 00000000..79431894 --- /dev/null +++ b/linux/payload/SerialCommunicationHelper.h @@ -0,0 +1,69 @@ +#pragma once + +#include +#include +#include +#include + +#include "SerialConfig.h" +#include "fsfw/returnvalues/returnvalue.h" + +/** + * @brief This is the communication interface to access serial ports on linux based operating + * systems. + * + * @details The implementation follows the instructions from https://blog.mbedded.ninja/programming/ + * operating-systems/linux/linux-serial-ports-using-c-cpp/#disabling-canonical-mode + * + * @author J. Meier + */ +class SerialCommunicationHelper { + public: + SerialCommunicationHelper(SerialConfig serialCfg); + + ReturnValue_t send(const uint8_t* data, size_t dataLen); + + int rawFd() const; + + ReturnValue_t initialize(); + + /** + * @brief This function discards all data received but not read in the UART buffer. + */ + ReturnValue_t flushUartRxBuffer(); + + /** + * @brief This function discards all data in the transmit buffer of the UART driver. + */ + ReturnValue_t flushUartTxBuffer(); + + /** + * @brief This function discards both data in the transmit and receive buffer of the UART. + */ + ReturnValue_t flushUartTxAndRxBuf(); + + private: + SerialConfig cfg; + int fd = 0; + + /** + * @brief This function opens and configures a uart device by using the information stored + * in the uart cookie. + * @param uartCookie Pointer to uart cookie with information about the uart. Contains the + * uart device file, baudrate, parity, stopbits etc. + * @return The file descriptor of the configured uart. + */ + int configureUartPort(); + + void setStopBitOptions(struct termios* options); + + /** + * @brief This function sets options which are not configurable by the uartCookie. + */ + void setFixedOptions(struct termios* options); + + /** + * @brief With this function the datasize settings are added to the termios options struct. + */ + void setDatasizeOptions(struct termios* options); +}; diff --git a/linux/payload/SerialConfig.h b/linux/payload/SerialConfig.h new file mode 100644 index 00000000..2ef8ccdf --- /dev/null +++ b/linux/payload/SerialConfig.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include + +#include + +/** + * @brief Cookie for the UartComIF. There are many options available to configure the UART driver. + * The constructor only requests for common options like the baudrate. Other options can + * be set by member functions. + * + * @author J. Meier + */ +class SerialConfig : public CookieIF { + public: + /** + * @brief Constructor for the uart cookie. + * @param deviceFile The device file specifying the uart to use, e.g. "/dev/ttyPS1" + * @param uartMode Specify the UART mode. The canonical mode should be used if the + * messages are separated by a delimited character like '\n'. See the + * termios documentation for more information + * @param baudrate The baudrate to use for input and output. + * @param maxReplyLen The maximum size an object using this cookie expects + * @details + * Default configuration: No parity + * 8 databits (number of bits transfered with one uart frame) + * One stop bit + */ + SerialConfig(std::string deviceFile, UartBaudRate baudrate, size_t maxReplyLen, + UartModes uartMode = UartModes::NON_CANONICAL) + : deviceFile(deviceFile), baudrate(baudrate), maxReplyLen(maxReplyLen), uartMode(uartMode) {} + + virtual ~SerialConfig() = default; + + UartBaudRate getBaudrate() const { return baudrate; } + size_t getMaxReplyLen() const { return maxReplyLen; } + std::string getDeviceFile() const { return deviceFile; } + Parity getParity() const { return parity; } + BitsPerWord getBitsPerWord() const { return bitsPerWord; } + StopBits getStopBits() const { return stopBits; } + UartModes getUartMode() const { return uartMode; } + + /** + * Functions two enable parity checking. + */ + void setParityOdd() { parity = Parity::ODD; } + void setParityEven() { parity = Parity::EVEN; } + + /** + * Function two set number of bits per UART frame. + */ + void setBitsPerWord(BitsPerWord bitsPerWord_) { bitsPerWord = bitsPerWord_; } + + /** + * Function to specify the number of stopbits. + */ + void setTwoStopBits() { stopBits = StopBits::TWO_STOP_BITS; } + void setOneStopBit() { stopBits = StopBits::ONE_STOP_BIT; } + + private: + std::string deviceFile; + UartBaudRate baudrate; + size_t maxReplyLen = 0; + const UartModes uartMode; + Parity parity = Parity::NONE; + BitsPerWord bitsPerWord = BitsPerWord::BITS_8; + StopBits stopBits = StopBits::ONE_STOP_BIT; +}; diff --git a/linux/payload/mpsocRetvals.h b/linux/payload/mpsocRetvals.h deleted file mode 100644 index 032211e0..00000000 --- a/linux/payload/mpsocRetvals.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef MPSOC_RETURN_VALUES_IF_H_ -#define MPSOC_RETURN_VALUES_IF_H_ - -#include "eive/resultClassIds.h" -#include "fsfw/returnvalues/returnvalue.h" - -class MPSoCReturnValuesIF { - public: - static const uint8_t INTERFACE_ID = CLASS_ID::MPSOC_RETURN_VALUES_IF; - - //! [EXPORT] : [COMMENT] Space Packet received from PLOC has invalid CRC - static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA0); - //! [EXPORT] : [COMMENT] Received ACK failure reply from PLOC - static const ReturnValue_t RECEIVED_ACK_FAILURE = MAKE_RETURN_CODE(0xA1); - //! [EXPORT] : [COMMENT] Received execution failure reply from PLOC - static const ReturnValue_t RECEIVED_EXE_FAILURE = MAKE_RETURN_CODE(0xA2); - //! [EXPORT] : [COMMENT] Received space packet with invalid APID from PLOC - static const ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(0xA3); - //! [EXPORT] : [COMMENT] Received command with invalid length - static const ReturnValue_t INVALID_LENGTH = MAKE_RETURN_CODE(0xA4); - //! [EXPORT] : [COMMENT] Filename of file in OBC filesystem is too long - static const ReturnValue_t FILENAME_TOO_LONG = MAKE_RETURN_CODE(0xA5); - //! [EXPORT] : [COMMENT] MPSoC helper is currently executing a command - static const ReturnValue_t MPSOC_HELPER_EXECUTING = MAKE_RETURN_CODE(0xA6); - //! [EXPORT] : [COMMENT] Filename of MPSoC file is to long (max. 256 bytes) - static const ReturnValue_t MPSOC_FILENAME_TOO_LONG = MAKE_RETURN_CODE(0xA7); - //! [EXPORT] : [COMMENT] Command has invalid parameter - static const ReturnValue_t INVALID_PARAMETER = MAKE_RETURN_CODE(0xA8); - //! [EXPORT] : [COMMENT] Received command has file string with invalid length - static const ReturnValue_t NAME_TOO_LONG = MAKE_RETURN_CODE(0xA9); -}; - -#endif /* MPSOC_RETURN_VALUES_IF_H_ */ diff --git a/linux/payload/plocMpsocHelpers.cpp b/linux/payload/plocMpsocHelpers.cpp index 9e5b11c9..2109749e 100644 --- a/linux/payload/plocMpsocHelpers.cpp +++ b/linux/payload/plocMpsocHelpers.cpp @@ -1,87 +1,94 @@ #include "plocMpsocHelpers.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" +#include "mission/payload/plocSpBase.h" + uint16_t mpsoc::getStatusFromRawData(const uint8_t* data) { return (*(data + STATUS_OFFSET) << 8) | *(data + STATUS_OFFSET + 1); } std::string mpsoc::getStatusString(uint16_t status) { switch (status) { - case (mpsoc::status_code::UNKNOWN_APID): { + case (mpsoc::statusCode::UNKNOWN_APID): { return "Unknown APID"; break; } - case (mpsoc::status_code::INCORRECT_LENGTH): { + case (mpsoc::statusCode::INCORRECT_LENGTH): { return "Incorrect length"; break; } - case (mpsoc::status_code::INCORRECT_CRC): { + case (mpsoc::statusCode::FLASH_DRIVE_ERROR): { + return "flash drive error"; + break; + } + case (mpsoc::statusCode::INCORRECT_CRC): { return "Incorrect crc"; break; } - case (mpsoc::status_code::INCORRECT_PKT_SEQ_CNT): { + case (mpsoc::statusCode::INCORRECT_PKT_SEQ_CNT): { return "Incorrect packet sequence count"; break; } - case (mpsoc::status_code::TC_NOT_ALLOWED_IN_MODE): { + case (mpsoc::statusCode::TC_NOT_ALLOWED_IN_MODE): { return "TC not allowed in this mode"; break; } - case (mpsoc::status_code::TC_EXEUTION_DISABLED): { + case (mpsoc::statusCode::TC_EXEUTION_DISABLED): { return "TC execution disabled"; break; } - case (mpsoc::status_code::FLASH_MOUNT_FAILED): { + case (mpsoc::statusCode::FLASH_MOUNT_FAILED): { return "Flash mount failed"; break; } - case (mpsoc::status_code::FLASH_FILE_ALREADY_OPEN): { + case (mpsoc::statusCode::FLASH_FILE_ALREADY_OPEN): { return "Flash file already open"; break; } - case (mpsoc::status_code::FLASH_FILE_ALREADY_CLOSED): { + case (mpsoc::statusCode::FLASH_FILE_ALREADY_CLOSED): { return "Flash file already closed"; break; } - case (mpsoc::status_code::FLASH_FILE_OPEN_FAILED): { + case (mpsoc::statusCode::FLASH_FILE_OPEN_FAILED): { return "Flash file open failed"; break; } - case (mpsoc::status_code::FLASH_FILE_NOT_OPEN): { + case (mpsoc::statusCode::FLASH_FILE_NOT_OPEN): { return "Flash file not open"; break; } - case (mpsoc::status_code::FLASH_UNMOUNT_FAILED): { + case (mpsoc::statusCode::FLASH_UNMOUNT_FAILED): { return "Flash unmount failed"; break; } - case (mpsoc::status_code::HEAP_ALLOCATION_FAILED): { + case (mpsoc::statusCode::HEAP_ALLOCATION_FAILED): { return "Heap allocation failed"; break; } - case (mpsoc::status_code::INVALID_PARAMETER): { + case (mpsoc::statusCode::INVALID_PARAMETER): { return "Invalid parameter"; break; } - case (mpsoc::status_code::NOT_INITIALIZED): { + case (mpsoc::statusCode::NOT_INITIALIZED): { return "Not initialized"; break; } - case (mpsoc::status_code::REBOOT_IMMINENT): { + case (mpsoc::statusCode::REBOOT_IMMINENT): { return "Reboot imminent"; break; } - case (mpsoc::status_code::CORRUPT_DATA): { + case (mpsoc::statusCode::CORRUPT_DATA): { return "Corrupt data"; break; } - case (mpsoc::status_code::FLASH_CORRECTABLE_MISMATCH): { + case (mpsoc::statusCode::FLASH_CORRECTABLE_MISMATCH): { return "Flash correctable mismatch"; break; } - case (mpsoc::status_code::FLASH_UNCORRECTABLE_MISMATCH): { + case (mpsoc::statusCode::FLASH_UNCORRECTABLE_MISMATCH): { return "Flash uncorrectable mismatch"; break; } - case (mpsoc::status_code::DEFAULT_ERROR_CODE): { + case (mpsoc::statusCode::DEFAULT_ERROR_CODE): { return "Default error code"; break; } @@ -93,3 +100,19 @@ std::string mpsoc::getStatusString(uint16_t status) { } return ""; } + +void mpsoc::printRxPacket(const SpacePacketReader& spReader) { + if (mpsoc::MPSOC_RX_WIRETAPPING) { + sif::debug << "RECV MPSOC packet. APID 0x" << std::hex << std::setw(3) << spReader.getApid() + << std::dec << " Size " << spReader.getFullPacketLen() << " SSC " + << spReader.getSequenceCount() << std::endl; + } +} + +void mpsoc::printTxPacket(const ploc::SpTcBase& tcBase) { + if (mpsoc::MPSOC_TX_WIRETAPPING) { + sif::debug << "SEND MPSOC packet. APID 0x" << std::hex << std::setw(3) << tcBase.getApid() + << " Size " << std::dec << tcBase.getFullPacketLen() << " SSC " + << tcBase.getSeqCount() << std::endl; + } +} diff --git a/linux/payload/plocMpsocHelpers.h b/linux/payload/plocMpsocHelpers.h index ffd077d9..53b9a5a1 100644 --- a/linux/payload/plocMpsocHelpers.h +++ b/linux/payload/plocMpsocHelpers.h @@ -3,16 +3,117 @@ #include #include -#include #include -#include "OBSWConfig.h" -#include "eive/definitions.h" -#include "fsfw/globalfunctions/CRC.h" +#include "eive/eventSubsystemIds.h" +#include "eive/resultClassIds.h" +#include "fsfw/action/HasActionsIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/serialize/SerializeAdapter.h" +#include "fsfw/serialize/SerializeIF.h" namespace mpsoc { +static constexpr size_t CRC_SIZE = 2; + +/** + * @brief Abstract base class for TC space packet of MPSoC. + */ +class TcBase : public ploc::SpTcBase { + public: + virtual ~TcBase() = default; + + // Initial length field of space packet. Will always be updated when packet is created. + static const uint16_t INIT_LENGTH = CRC_SIZE; + + /** + * @brief Constructor + * + * @param sequenceCount Sequence count of space packet which will be incremented with each + * sent and received packets. + */ + TcBase(ploc::SpTcParams params, uint16_t apid, uint16_t sequenceCount) + : ploc::SpTcBase(params, apid, 0, sequenceCount) { + payloadStart = spParams.buf + ccsds::HEADER_LEN; + spParams.setFullPayloadLen(INIT_LENGTH); + } + + /** + * @brief Function to finsh and write the space packet. It is expected that the user has + * set the payload fields in the child class* + * @return returnvalue::OK if packet creation was successful, otherwise error return value + */ + ReturnValue_t finishPacket() { + updateSpFields(); + ReturnValue_t res = checkSizeAndSerializeHeader(); + if (res != returnvalue::OK) { + return res; + } + return calcAndSetCrc(); + } +}; + +void printRxPacket(const SpacePacketReader& spReader); +void printTxPacket(const ploc::SpTcBase& tcBase); + +static constexpr bool MPSOC_TX_WIRETAPPING = true; +static constexpr bool MPSOC_RX_WIRETAPPING = true; + +static constexpr uint32_t DEFAULT_CMD_TIMEOUT_MS = 5000; +static constexpr uint32_t CMD_TIMEOUT_MKFS = 15000; + +enum FlashId : uint8_t { FLASH_0 = 0, FLASH_1 = 1 }; + +static const uint8_t INTERFACE_ID = CLASS_ID::MPSOC_RETURN_VALUES_IF; + +//! [EXPORT] : [COMMENT] Space Packet received from PLOC has invalid CRC +static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA0); +//! [EXPORT] : [COMMENT] Received ACK failure reply from PLOC +static const ReturnValue_t RECEIVED_ACK_FAILURE = MAKE_RETURN_CODE(0xA1); +//! [EXPORT] : [COMMENT] Received execution failure reply from PLOC +static const ReturnValue_t RECEIVED_EXE_FAILURE = MAKE_RETURN_CODE(0xA2); +//! [EXPORT] : [COMMENT] Received space packet with invalid APID from PLOC +static const ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(0xA3); +//! [EXPORT] : [COMMENT] Received command with invalid length +static const ReturnValue_t INVALID_LENGTH = MAKE_RETURN_CODE(0xA4); +//! [EXPORT] : [COMMENT] Filename of file in OBC filesystem is too long +static const ReturnValue_t FILENAME_TOO_LONG = MAKE_RETURN_CODE(0xA5); +//! [EXPORT] : [COMMENT] MPSoC helper is currently executing a command +static const ReturnValue_t MPSOC_HELPER_EXECUTING = MAKE_RETURN_CODE(0xA6); +//! [EXPORT] : [COMMENT] Filename of MPSoC file is to long (max. 256 bytes) +static const ReturnValue_t MPSOC_FILENAME_TOO_LONG = MAKE_RETURN_CODE(0xA7); +//! [EXPORT] : [COMMENT] Command has invalid parameter +static const ReturnValue_t INVALID_PARAMETER = MAKE_RETURN_CODE(0xA8); +//! [EXPORT] : [COMMENT] Received command has file string with invalid length +static const ReturnValue_t NAME_TOO_LONG = MAKE_RETURN_CODE(0xA9); +//! [EXPORT] : [COMMENT] Command has timed out. +static const ReturnValue_t COMMAND_TIMEOUT = MAKE_RETURN_CODE(0x10); + +static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_MPSOC_HANDLER; + +//! [EXPORT] : [COMMENT] PLOC crc failure in telemetry packet +static const Event MEMORY_READ_RPT_CRC_FAILURE = MAKE_EVENT(1, severity::LOW); +//! [EXPORT] : [COMMENT] PLOC receive acknowledgment failure report +//! P1: Command Id which leads the acknowledgment failure report +//! P2: The status field inserted by the MPSoC into the data field +static const Event ACK_FAILURE = MAKE_EVENT(2, severity::LOW); +//! [EXPORT] : [COMMENT] PLOC receive execution failure report +//! P1: Command Id which leads the execution failure report +//! P2: The status field inserted by the MPSoC into the data field +static const Event EXE_FAILURE = MAKE_EVENT(3, severity::LOW); +//! [EXPORT] : [COMMENT] PLOC reply has invalid crc +static const Event MPSOC_HANDLER_CRC_FAILURE = MAKE_EVENT(4, severity::LOW); +//! [EXPORT] : [COMMENT] Packet sequence count in received space packet does not match expected +//! count P1: Expected sequence count P2: Received sequence count +static const Event MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH = MAKE_EVENT(5, severity::LOW); +//! [EXPORT] : [COMMENT] Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and +//! thus also to shutdown the supervisor. +static const Event MPSOC_SHUTDOWN_FAILED = MAKE_EVENT(6, severity::HIGH); +//! [EXPORT] : [COMMENT] SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for +//! ON transition. +static constexpr Event SUPV_NOT_ON = event::makeEvent(SUBSYSTEM_ID, 7, severity::LOW); +static constexpr Event SUPV_REPLY_TIMEOUT = event::makeEvent(SUBSYSTEM_ID, 8, severity::LOW); + enum ParamId : uint8_t { SKIP_SUPV_ON_COMMANDING = 0x01 }; enum FileAccessModes : uint8_t { @@ -30,6 +131,8 @@ enum FileAccessModes : uint8_t { }; static constexpr uint32_t HK_SET_ID = 0; +static constexpr uint32_t DEADBEEF_ADDR = 0x40000004; +static constexpr uint32_t DEADBEEF_VALUE = 0xdeadbeef; namespace poolid { enum { @@ -92,7 +195,8 @@ static const DeviceCommandId_t TM_CAM_CMD_RPT = 19; static const DeviceCommandId_t SET_UART_TX_TRISTATE = 20; static const DeviceCommandId_t RELEASE_UART_TX = 21; static const DeviceCommandId_t TC_CAM_TAKE_PIC = 22; -static const DeviceCommandId_t TC_SIMPLEX_SEND_FILE = 23; +// Stream file down using E-Band component directly. +static const DeviceCommandId_t TC_SIMPLEX_STREAM_FILE = 23; static const DeviceCommandId_t TC_DOWNLINK_DATA_MODULATE = 24; static const DeviceCommandId_t TC_MODE_SNAPSHOT = 25; static const DeviceCommandId_t TC_GET_HK_REPORT = 26; @@ -100,16 +204,33 @@ static const DeviceCommandId_t TM_GET_HK_REPORT = 27; static const DeviceCommandId_t TC_FLASH_GET_DIRECTORY_CONTENT = 28; static const DeviceCommandId_t TM_FLASH_DIRECTORY_CONTENT = 29; static constexpr DeviceCommandId_t TC_FLASH_READ_FULL_FILE = 30; +// Store file on MPSoC. +static const DeviceCommandId_t TC_SIMPLEX_STORE_FILE = 31; +static const DeviceCommandId_t TC_VERIFY_BOOT = 32; +static const DeviceCommandId_t TC_ENABLE_TC_EXECTION = 33; +static const DeviceCommandId_t TC_FLASH_MKFS = 34; -// Will reset the sequence count of the OBSW -static const DeviceCommandId_t OBSW_RESET_SEQ_COUNT = 50; +// Will reset the sequence count of the OBSW. Not required anymore after MPSoC update. +static const DeviceCommandId_t OBSW_RESET_SEQ_COUNT_LEGACY = 50; static const uint16_t SIZE_ACK_REPORT = 14; static const uint16_t SIZE_EXE_REPORT = 14; -static const uint16_t SIZE_TM_MEM_READ_REPORT = 18; -static const uint16_t SIZE_TM_CAM_CMD_RPT = 18; +// static const uint16_t SIZE_TM_MEM_READ_REPORT = 18; +// static const uint16_t SIZE_TM_CAM_CMD_RPT = 18; static constexpr size_t SIZE_TM_HK_REPORT = 369; +enum Submode : uint8_t { IDLE_OR_NONE = 0, REPLAY = 1, SNAPSHOT = 2 }; + +// Setting the internal mode value to the actual telecommand ID +/* +enum InternalMode { + OFF = HasModesIF::MODE_OFF, + IDLE = , + REPLAY = TC_MODE_REPLAY, + SNAPSHOT = TC_MODE_SNAPSHOT +}; +*/ + /** * SpacePacket apids of PLOC telecommands and telemetry. */ @@ -134,6 +255,8 @@ static const uint16_t TC_MODE_SNAPSHOT = 0x120; static const uint16_t TC_DOWNLINK_DATA_MODULATE = 0x121; static constexpr uint16_t TC_HK_GET_REPORT = 0x123; static const uint16_t TC_DOWNLINK_PWR_OFF = 0x124; +static constexpr uint16_t TC_ENABLE_TC_EXECUTION = 0x129; +static constexpr uint16_t TC_FLASH_MKFS = 0x12A; static const uint16_t TC_CAM_CMD_SEND = 0x12C; static constexpr uint16_t TC_FLASH_COPY_FILE = 0x12E; static const uint16_t TC_SIMPLEX_SEND_FILE = 0x130; @@ -158,15 +281,15 @@ static const uint8_t SPACE_PACKET_HEADER_SIZE = 6; static const uint8_t STATUS_OFFSET = 10; -static constexpr size_t CRC_SIZE = 2; - /** * The size of payload data which will be forwarded to the requesting object. e.g. PUS Service * 8. */ static const uint8_t SIZE_MEM_READ_RPT_FIX = 6; -static const size_t MAX_FILENAME_SIZE = 256; +static const size_t FILENAME_FIELD_SIZE = 256; +// Subtract size of NULL terminator. +static const size_t MAX_FILENAME_SIZE = FILENAME_FIELD_SIZE - 1; /** * PLOC space packet length for fixed size packets. This is the size of the whole packet data @@ -201,8 +324,9 @@ static const uint16_t TC_DOWNLINK_PWR_ON_EXECUTION_DELAY = 8; static const uint16_t TC_CAM_TAKE_PIC_EXECUTION_DELAY = 20; static const uint16_t TC_SIMPLEX_SEND_FILE_DELAY = 80; -namespace status_code { +namespace statusCode { static const uint16_t DEFAULT_ERROR_CODE = 0x1; +static constexpr uint16_t FLASH_DRIVE_ERROR = 0xb; static const uint16_t UNKNOWN_APID = 0x5DD; static const uint16_t INCORRECT_LENGTH = 0x5DE; static const uint16_t INCORRECT_CRC = 0x5DF; @@ -227,49 +351,12 @@ static const uint16_t RESERVED_1 = 0x5F1; static const uint16_t RESERVED_2 = 0x5F2; static const uint16_t RESERVED_3 = 0x5F3; static const uint16_t RESERVED_4 = 0x5F4; -} // namespace status_code - -/** - * @brief Abstract base class for TC space packet of MPSoC. - */ -class TcBase : public ploc::SpTcBase, public MPSoCReturnValuesIF { - public: - virtual ~TcBase() = default; - - // Initial length field of space packet. Will always be updated when packet is created. - static const uint16_t INIT_LENGTH = CRC_SIZE; - - /** - * @brief Constructor - * - * @param sequenceCount Sequence count of space packet which will be incremented with each - * sent and received packets. - */ - TcBase(ploc::SpTcParams params, uint16_t apid, uint16_t sequenceCount) - : ploc::SpTcBase(params, apid, 0, sequenceCount) { - payloadStart = spParams.buf + ccsds::HEADER_LEN; - spParams.setFullPayloadLen(INIT_LENGTH); - } - - /** - * @brief Function to finsh and write the space packet. It is expected that the user has - * set the payload fields in the child class* - * @return returnvalue::OK if packet creation was successful, otherwise error return value - */ - ReturnValue_t finishPacket() { - updateSpFields(); - ReturnValue_t res = checkSizeAndSerializeHeader(); - if (res != returnvalue::OK) { - return res; - } - return calcAndSetCrc(); - } -}; +} // namespace statusCode /** * @brief This class helps to build the memory read command for the PLOC. */ -class TcMemRead : public TcBase { +class TcMemRead : public mpsoc::TcBase { public: /** * @brief Constructor @@ -319,7 +406,7 @@ class TcMemRead : public TcBase { * @brief This class helps to generate the space packet to write data to a memory address within * the PLOC. */ -class TcMemWrite : public TcBase { +class TcMemWrite : public mpsoc::TcBase { public: /** * @brief Constructor @@ -369,24 +456,21 @@ class TcMemWrite : public TcBase { /** * @brief Class to help creation of flash fopen command. */ -class FlashFopen : public TcBase { +class TcFlashFopen : public mpsoc::TcBase { public: - FlashFopen(ploc::SpTcParams params, uint16_t sequenceCount) + TcFlashFopen(ploc::SpTcParams params, uint16_t sequenceCount) : TcBase(params, apid::TC_FLASHFOPEN, sequenceCount) {} ReturnValue_t setPayload(std::string filename, uint8_t mode) { accessMode = mode; - size_t nameSize = filename.size(); - spParams.setFullPayloadLen(256 + sizeof(uint8_t) + CRC_SIZE); ReturnValue_t result = checkPayloadLen(); if (result != returnvalue::OK) { return result; } - std::memcpy(payloadStart, filename.c_str(), nameSize); - // payloadStart[nameSize] = NULL_TERMINATOR; - std::memset(payloadStart + nameSize, 0, 256 - nameSize); - // payloadStart[255] = NULL_TERMINATOR; - payloadStart[256] = accessMode; + std::memset(payloadStart, 0, FILENAME_FIELD_SIZE); + std::memcpy(payloadStart, filename.c_str(), filename.size()); + payloadStart[FILENAME_FIELD_SIZE] = accessMode; + spParams.setFullPayloadLen(FILENAME_FIELD_SIZE + 1 + CRC_SIZE); return returnvalue::OK; } @@ -397,14 +481,46 @@ class FlashFopen : public TcBase { /** * @brief Class to help creation of flash fclose command. */ -class FlashFclose : public TcBase { +class TcFlashFclose : public TcBase { public: - FlashFclose(ploc::SpTcParams params, uint16_t sequenceCount) + TcFlashFclose(ploc::SpTcParams params, uint16_t sequenceCount) : TcBase(params, apid::TC_FLASHFCLOSE, sequenceCount) { spParams.setFullPayloadLen(CRC_SIZE); } }; +class TcEnableTcExec : public TcBase { + public: + TcEnableTcExec(ploc::SpTcParams params, uint16_t sequenceCount) + : TcBase(params, apid::TC_ENABLE_TC_EXECUTION, sequenceCount) { + spParams.setFullPayloadLen(CRC_SIZE); + } + + ReturnValue_t setPayload(const uint8_t* cmdData, size_t cmdDataLen) { + if (cmdDataLen != 2) { + return HasActionsIF::INVALID_PARAMETERS; + } + std::memcpy(payloadStart, cmdData, 2); + spParams.setFullPayloadLen(2 + CRC_SIZE); + return returnvalue::OK; + } +}; + +class TcFlashMkfs : public TcBase { + public: + TcFlashMkfs(ploc::SpTcParams params, uint16_t sequenceCount, FlashId flashId) + : TcBase(params, apid::TC_FLASH_MKFS, sequenceCount) { + const char* flashIdStr = "0:\\"; + if (flashId == FlashId::FLASH_1) { + flashIdStr = "1:\\"; + } + std::memcpy(payloadStart, flashIdStr, 3); + // Null terminator + payloadStart[3] = 0; + spParams.setFullPayloadLen(4 + CRC_SIZE); + } +}; + /** * @brief Class to build flash write space packet. */ @@ -464,15 +580,6 @@ class TcFlashRead : public TcBase { if (result != returnvalue::OK) { return result; } - updateSpFields(); - result = checkSizeAndSerializeHeader(); - if (result != returnvalue::OK) { - return result; - } - result = calcAndSetCrc(); - if (result != returnvalue::OK) { - return result; - } readSize = readLen; return result; } @@ -490,20 +597,14 @@ class TcFlashDelete : public TcBase { ReturnValue_t setPayload(std::string filename) { size_t nameSize = filename.size(); - spParams.setFullPayloadLen(nameSize + sizeof(NULL_TERMINATOR) + CRC_SIZE); + spParams.setFullPayloadLen(FILENAME_FIELD_SIZE + CRC_SIZE); auto res = checkPayloadLen(); if (res != returnvalue::OK) { return res; } std::memcpy(payloadStart, filename.c_str(), nameSize); *(payloadStart + nameSize) = NULL_TERMINATOR; - - updateSpFields(); - res = checkSizeAndSerializeHeader(); - if (res != returnvalue::OK) { - return res; - } - return calcAndSetCrc(); + return returnvalue::OK; } }; @@ -655,8 +756,9 @@ class TcGetDirContent : public TcBase { if (result != returnvalue::OK) { return result; } + std::memset(payloadStart, 0, 256); std::memcpy(payloadStart, commandData, commandDataLen); - payloadStart[255] = '\0'; + payloadStart[255] = 0; return result; } }; @@ -697,7 +799,7 @@ class TcReplayWriteSeq : public TcBase { static const size_t USE_DECODING_LENGTH = 1; ReturnValue_t lengthCheck(size_t commandDataLen) { - if (commandDataLen > USE_DECODING_LENGTH + MAX_FILENAME_SIZE or + if (commandDataLen > USE_DECODING_LENGTH + FILENAME_FIELD_SIZE or checkPayloadLen() != returnvalue::OK) { sif::warning << "TcReplayWriteSeq: Command has invalid length " << commandDataLen << std::endl; @@ -710,24 +812,24 @@ class TcReplayWriteSeq : public TcBase { /** * @brief Helps to extract the fields of the flash write command from the PUS packet. */ -class FlashBasePusCmd : public MPSoCReturnValuesIF { +class FlashBasePusCmd { public: FlashBasePusCmd() = default; virtual ~FlashBasePusCmd() = default; virtual ReturnValue_t extractFields(const uint8_t* commandData, size_t commandDataLen) { - if (commandDataLen > (config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE + MAX_FILENAME_SIZE)) { + if (commandDataLen > FILENAME_FIELD_SIZE) { return INVALID_LENGTH; } size_t fileLen = strnlen(reinterpret_cast(commandData), commandDataLen); - if (fileLen > (config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE)) { + if (fileLen > MAX_FILENAME_SIZE) { return FILENAME_TOO_LONG; } obcFile = std::string(reinterpret_cast(commandData), fileLen); fileLen = strnlen(reinterpret_cast(commandData + obcFile.size() + SIZE_NULL_TERMINATOR), commandDataLen - obcFile.size() - 1); - if (fileLen > MAX_FILENAME_SIZE) { + if (fileLen > FILENAME_FIELD_SIZE) { return MPSOC_FILENAME_TOO_LONG; } mpsocFile = std::string( @@ -738,11 +840,11 @@ class FlashBasePusCmd : public MPSoCReturnValuesIF { const std::string& getObcFile() const { return obcFile; } - const std::string& getMPSoCFile() const { return mpsocFile; } + const std::string& getMpsocFile() const { return mpsocFile; } protected: size_t getParsedSize() const { - return getObcFile().size() + getMPSoCFile().size() + 2 * SIZE_NULL_TERMINATOR; + return getObcFile().size() + getMpsocFile().size() + 2 * SIZE_NULL_TERMINATOR; } static const size_t SIZE_NULL_TERMINATOR = 1; @@ -809,49 +911,190 @@ class TcCamTakePic : public TcBase { : TcBase(params, apid::TC_CAM_TAKE_PIC, sequenceCount) {} ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { - if (commandDataLen > MAX_DATA_LENGTH) { + const uint8_t** dataPtr = &commandData; + if (commandDataLen > FULL_PAYLOAD_SIZE) { return INVALID_LENGTH; } - std::string fileName(reinterpret_cast(commandData)); - if (fileName.size() + sizeof(NULL_TERMINATOR) > MAX_FILENAME_SIZE) { + size_t deserLen = commandDataLen; + size_t serLen = 0; + fileName = reinterpret_cast(commandData); + if (fileName.size() > MAX_FILENAME_SIZE) { return FILENAME_TOO_LONG; } - if (commandDataLen - (fileName.size() + sizeof(NULL_TERMINATOR)) != PARAMETER_SIZE) { - return INVALID_LENGTH; + deserLen -= fileName.length() + 1; + *dataPtr += fileName.length() + 1; + uint8_t** payloadPtr = &payloadStart; + memcpy(payloadStart, fileName.data(), fileName.size()); + *payloadPtr += FILENAME_FIELD_SIZE; + serLen += FILENAME_FIELD_SIZE; + ReturnValue_t result = SerializeAdapter::deSerialize(&encoderSettingY, dataPtr, &deserLen, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; } - spParams.setFullPayloadLen(commandDataLen + CRC_SIZE); - std::memcpy(payloadStart, commandData, commandDataLen); + result = SerializeAdapter::serialize(&encoderSettingY, payloadPtr, &serLen, FULL_PAYLOAD_SIZE, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + + result = SerializeAdapter::deSerialize(&quantizationY, dataPtr, &deserLen, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::serialize(&quantizationY, payloadPtr, &serLen, FULL_PAYLOAD_SIZE, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + + result = SerializeAdapter::deSerialize(&encoderSettingsCb, dataPtr, &deserLen, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::serialize(&encoderSettingsCb, payloadPtr, &serLen, FULL_PAYLOAD_SIZE, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + + result = SerializeAdapter::deSerialize(&quantizationCb, dataPtr, &deserLen, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::serialize(&quantizationCb, payloadPtr, &serLen, FULL_PAYLOAD_SIZE, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + + result = SerializeAdapter::deSerialize(&encoderSettingsCr, dataPtr, &deserLen, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::serialize(&encoderSettingsCr, payloadPtr, &serLen, FULL_PAYLOAD_SIZE, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + + result = SerializeAdapter::deSerialize(&quantizationCr, dataPtr, &deserLen, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::serialize(&quantizationCr, payloadPtr, &serLen, FULL_PAYLOAD_SIZE, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + + result = SerializeAdapter::deSerialize(&bypassCompressor, dataPtr, &deserLen, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::serialize(&bypassCompressor, payloadPtr, &serLen, FULL_PAYLOAD_SIZE, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + + spParams.setFullPayloadLen(FULL_PAYLOAD_SIZE + CRC_SIZE); return returnvalue::OK; } + std::string fileName; + uint8_t encoderSettingY = 7; + uint64_t quantizationY = 0; + uint8_t encoderSettingsCb = 7; + uint64_t quantizationCb = 0; + uint8_t encoderSettingsCr = 7; + uint64_t quantizationCr = 0; + uint8_t bypassCompressor = 0; + private: - static const size_t MAX_DATA_LENGTH = 286; static const size_t PARAMETER_SIZE = 28; + static constexpr size_t FULL_PAYLOAD_SIZE = FILENAME_FIELD_SIZE + PARAMETER_SIZE; }; /** * @brief Class to build simplex send file command */ -class TcSimplexSendFile : public TcBase { +class TcSimplexStreamFile : public TcBase { public: - TcSimplexSendFile(ploc::SpTcParams params, uint16_t sequenceCount) + TcSimplexStreamFile(ploc::SpTcParams params, uint16_t sequenceCount) : TcBase(params, apid::TC_SIMPLEX_SEND_FILE, sequenceCount) {} ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { - if (commandDataLen > MAX_DATA_LENGTH) { + if (commandDataLen > MAX_FILENAME_SIZE) { return INVALID_LENGTH; } std::string fileName(reinterpret_cast(commandData)); - if (fileName.size() + sizeof(NULL_TERMINATOR) > MAX_FILENAME_SIZE) { + if (fileName.size() > MAX_FILENAME_SIZE) { return FILENAME_TOO_LONG; } - spParams.setFullPayloadLen(commandDataLen + CRC_SIZE); - std::memcpy(payloadStart, commandData, commandDataLen); + + std::memset(payloadStart, 0, FILENAME_FIELD_SIZE); + std::memcpy(payloadStart, fileName.data(), fileName.length()); + payloadStart[fileName.length()] = 0; + spParams.setFullPayloadLen(FILENAME_FIELD_SIZE + CRC_SIZE); + ; return returnvalue::OK; } private: - static const size_t MAX_DATA_LENGTH = 256; +}; + +/** + * @brief Class to build simplex send file command + */ +class TcSimplexStoreFile : public TcBase { + public: + TcSimplexStoreFile(ploc::SpTcParams params, uint16_t sequenceCount) + : TcBase(params, apid::TC_SIMPLEX_SEND_FILE, sequenceCount) {} + + ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { + if (commandDataLen < MIN_DATA_LENGTH) { + return INVALID_LENGTH; + } + if (commandDataLen > MAX_DATA_LENGTH) { + return INVALID_LENGTH; + } + const uint8_t** dataPtr = &commandData; + ReturnValue_t result = SerializeAdapter::deSerialize(&chunkParameter, dataPtr, &commandDataLen, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + /// No chunks makes no sense, and DIV str can not be longer than whats representable with 3 + /// decimal digits. + if (chunkParameter == 0 or chunkParameter > 999) { + return INVALID_PARAMETER; + } + std::string fileName(reinterpret_cast(*dataPtr)); + if (fileName.size() > MAX_FILENAME_SIZE) { + return FILENAME_TOO_LONG; + } + char divStr[16]{}; + sprintf(divStr, "DIV%03u", chunkParameter); + std::memcpy(payloadStart, divStr, DIV_STR_LEN); + payloadStart[DIV_STR_LEN] = 0; + std::memset(payloadStart + DIV_STR_LEN + 1, 0, FILENAME_FIELD_SIZE - DIV_STR_LEN - 1); + std::memcpy(payloadStart + DIV_STR_LEN + 1, fileName.data(), fileName.length()); + spParams.setFullPayloadLen(FILENAME_FIELD_SIZE + CRC_SIZE); + return returnvalue::OK; + } + + private: + uint32_t chunkParameter = 0; + static constexpr size_t MIN_DATA_LENGTH = 4; + static constexpr size_t DIV_STR_LEN = 6; + static constexpr size_t MAX_DATA_LENGTH = 4 + MAX_FILENAME_SIZE; }; /** diff --git a/mission/pollingSeqTables.cpp b/mission/pollingSeqTables.cpp index b6e99899..9a1a1324 100644 --- a/mission/pollingSeqTables.cpp +++ b/mission/pollingSeqTables.cpp @@ -10,6 +10,7 @@ #include "OBSWConfig.h" #include "eive/definitions.h" #include "eive/objects.h" +#include "linux/payload/FreshMpsocHandler.h" #include "linux/payload/FreshSupvHandler.h" #ifndef RPI_TEST_ADIS16507 @@ -617,17 +618,21 @@ ReturnValue_t pst::pstPayload(FixedTimeslotTaskIF *thisSequence) { thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE); - thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE); - thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0, FreshSupvHandler::OpCode::DEFAULT_OPERATION); - // Two COM TM steps, which might cover telemetry which takes a bit longer to be sent. + // Parse TM with a bit of delay. Two COM steps which might cover telemetry wehich takes a bit + // longer to send thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.1, FreshSupvHandler::OpCode::PARSE_TM); thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.2, FreshSupvHandler::OpCode::PARSE_TM); + // Parse TM with a bit of delay. Two COM steps which might cover telemetry wehich takes a bit + // longer to send + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.2, + FreshMpsocHandler::OpCode::PARSE_TM); + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.4, + FreshMpsocHandler::OpCode::PARSE_TM); thisSequence->addSlot(objects::SCEX, length * 0.6, DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::SCEX, length * 0.6, DeviceHandlerIF::SEND_WRITE); diff --git a/scripts/q7s-cp.py b/scripts/q7s-cp.py index 7a4f7405..76ef2353 100755 --- a/scripts/q7s-cp.py +++ b/scripts/q7s-cp.py @@ -4,6 +4,9 @@ import os import sys +DEFAULT_PORT = 1539 + + def main(): args = handle_args() cmd = build_cmd(args) @@ -20,7 +23,7 @@ def prompt_ssh_key_removal(): do_remove_key = input( "Do you want to remove problematic keys on localhost ([Y]/n)?: " ) - if not do_remove_key.lower() in ["y", "yes", "1", ""]: + if do_remove_key.lower() not in ["y", "yes", "1", ""]: sys.exit(1) port = 0 while True: @@ -54,7 +57,7 @@ def handle_args(): "If files are copied back to host, will be current directory by default", default="", ) - parser.add_argument("-P", "--port", help="Target port", default=1535) + parser.add_argument("-P", "--port", help="Target port", default=DEFAULT_PORT) parser.add_argument( "-i", "--invert", diff --git a/tmtc b/tmtc index a8d0143b..5e1b12fa 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit a8d0143b1ed9a14f7e071ee3344dc4e8f1937c55 +Subproject commit 5e1b12fa527c21131883176cbcb9f8abe4199d91 diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index e9a01891..808a68ef 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -6,5 +6,6 @@ target_sources(${UNITTEST_NAME} PRIVATE testEnvironment.cpp testGenericFilesystem.cpp hdlcEncodingRw.cpp + mpsocTests.cpp printChar.cpp -) \ No newline at end of file +) diff --git a/unittest/mpsocTests.cpp b/unittest/mpsocTests.cpp new file mode 100644 index 00000000..2ab11b21 --- /dev/null +++ b/unittest/mpsocTests.cpp @@ -0,0 +1,14 @@ + +#include + +TEST_CASE("MPSoC helper tests", "[payload]") { + char divStr[16]{}; + uint32_t divParam = 0; + + SECTION("Simple Test") { + divParam = 3; + CHECK(divParam < 999); + sprintf(divStr, "DIV%03u", divParam); + REQUIRE(strcmp(divStr, "DIV003") == 0); + } +} -- 2.34.1 From 65476f4c98bddb6bc6f23ebe0fa8229dc3633641 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 30 Apr 2024 15:18:15 +0200 Subject: [PATCH 2/9] reduce printouts --- linux/payload/MpsocCommunication.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/payload/MpsocCommunication.h b/linux/payload/MpsocCommunication.h index 3e26051e..b46c361c 100644 --- a/linux/payload/MpsocCommunication.h +++ b/linux/payload/MpsocCommunication.h @@ -9,8 +9,8 @@ #include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" #include "linux/payload/SerialCommunicationHelper.h" -static constexpr bool MPSOC_LOW_LEVEL_TX_WIRETAPPING = true; -static constexpr bool MPSOC_LOW_LEVEL_RX_WIRETAPPING = true; +static constexpr bool MPSOC_LOW_LEVEL_TX_WIRETAPPING = false; +static constexpr bool MPSOC_LOW_LEVEL_RX_WIRETAPPING = false; class MpsocCommunication : public SystemObject { public: -- 2.34.1 From 4a0acbf1580a832e8e3e2e4b9fc8651bba92d77f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 30 Apr 2024 15:37:53 +0200 Subject: [PATCH 3/9] further reduce printout --- linux/payload/plocMpsocHelpers.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/payload/plocMpsocHelpers.h b/linux/payload/plocMpsocHelpers.h index 53b9a5a1..f92b43ca 100644 --- a/linux/payload/plocMpsocHelpers.h +++ b/linux/payload/plocMpsocHelpers.h @@ -14,6 +14,9 @@ namespace mpsoc { +static constexpr bool MPSOC_TX_WIRETAPPING = false; +static constexpr bool MPSOC_RX_WIRETAPPING = false; + static constexpr size_t CRC_SIZE = 2; /** @@ -56,9 +59,6 @@ class TcBase : public ploc::SpTcBase { void printRxPacket(const SpacePacketReader& spReader); void printTxPacket(const ploc::SpTcBase& tcBase); -static constexpr bool MPSOC_TX_WIRETAPPING = true; -static constexpr bool MPSOC_RX_WIRETAPPING = true; - static constexpr uint32_t DEFAULT_CMD_TIMEOUT_MS = 5000; static constexpr uint32_t CMD_TIMEOUT_MKFS = 15000; -- 2.34.1 From 744a94704c4c2a89886dfbf16f1a3fa41747b9e3 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 2 May 2024 15:42:14 +0200 Subject: [PATCH 4/9] removed TODOs which are done --- linux/payload/FreshMpsocHandler.cpp | 11 ++--------- linux/payload/plocMpsocHelpers.h | 2 -- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/linux/payload/FreshMpsocHandler.cpp b/linux/payload/FreshMpsocHandler.cpp index 021ebc5a..65c273c2 100644 --- a/linux/payload/FreshMpsocHandler.cpp +++ b/linux/payload/FreshMpsocHandler.cpp @@ -296,8 +296,6 @@ ReturnValue_t FreshMpsocHandler::executeAction(ActionId_t actionId, MessageQueue default: break; } - // For longer commands, do not set these. - // TODO: Do all the stuff the form buildDeviceFromDevice blah did. executeRegularCmd(actionId, commandedBy, data, size); return returnvalue::OK; } @@ -788,7 +786,6 @@ ReturnValue_t FreshMpsocHandler::finishAndSendTc(DeviceCommandId_t cmdId, mpsoc: if (result != returnvalue::OK) { return result; } - // TODO: We should find a way so this works with the old implementation. commandSequenceCount++; mpsoc::printTxPacket(tcBase); @@ -836,8 +833,6 @@ void FreshMpsocHandler::cmdDoneHandler(bool success, ReturnValue_t result) { ReturnValue_t FreshMpsocHandler::handleDeviceReply() { ReturnValue_t result = returnvalue::OK; - // SpacePacketReader spacePacket; - // spacePacket.setReadOnlyData(start, remainingSize); const auto& replyReader = comInterface.getSpReader(); if (replyReader.isNull()) { return returnvalue::FAILED; @@ -889,15 +884,14 @@ ReturnValue_t FreshMpsocHandler::handleDeviceReply() { default: { sif::debug << "FreshMpsocHandler:: Reply has invalid APID 0x" << std::hex << std::setfill('0') << std::setw(2) << apid << std::dec << std::endl; - //*foundLen = remainingSize; return mpsoc::INVALID_APID; } } - // TODO: We should implement some way so this can also be used with the former implementation. uint16_t sequenceCount = replyReader.getSequenceCount(); if (sequenceCount != lastReplySequenceCount + 1) { - // TODO: Trigger event for possible missing reply packet to inform operator. + // We could trigger event for possible missing reply packet to inform operator, but I don't + // think this is properly implemented and used on the MPSoC side anymore. } lastReplySequenceCount = sequenceCount; @@ -952,7 +946,6 @@ ReturnValue_t FreshMpsocHandler::handleAckReport() { switch (replyReader.getApid()) { case mpsoc::apid::ACK_FAILURE: { - // DeviceCommandId_t commandId = getPendingCommand(); uint16_t status = mpsoc::getStatusFromRawData(replyReader.getFullData()); sif::warning << "MPSoC ACK Failure: " << mpsoc::getStatusString(status) << std::endl; triggerEvent(mpsoc::ACK_FAILURE, activeCmdInfo.pendingCmd, status); diff --git a/linux/payload/plocMpsocHelpers.h b/linux/payload/plocMpsocHelpers.h index f92b43ca..60356f56 100644 --- a/linux/payload/plocMpsocHelpers.h +++ b/linux/payload/plocMpsocHelpers.h @@ -215,8 +215,6 @@ static const DeviceCommandId_t OBSW_RESET_SEQ_COUNT_LEGACY = 50; static const uint16_t SIZE_ACK_REPORT = 14; static const uint16_t SIZE_EXE_REPORT = 14; -// static const uint16_t SIZE_TM_MEM_READ_REPORT = 18; -// static const uint16_t SIZE_TM_CAM_CMD_RPT = 18; static constexpr size_t SIZE_TM_HK_REPORT = 369; enum Submode : uint8_t { IDLE_OR_NONE = 0, REPLAY = 1, SNAPSHOT = 2 }; -- 2.34.1 From 4fdec7a74cb4713212df9e29fa55818bf729bf2d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 6 May 2024 13:19:15 +0200 Subject: [PATCH 5/9] impl proper NORMAL mode for MPSoC --- .../fsfwconfig/events/translateEvents.cpp | 7 +++- .../fsfwconfig/objects/translateObjects.cpp | 2 +- bsp_q7s/objectFactory.cpp | 7 ++-- generators/bsp_hosted_events.csv | 1 + generators/bsp_q7s_events.csv | 1 + generators/events/translateEvents.cpp | 7 +++- generators/objects/translateObjects.cpp | 2 +- linux/fsfwconfig/events/translateEvents.cpp | 7 +++- linux/fsfwconfig/objects/translateObjects.cpp | 2 +- linux/payload/FreshMpsocHandler.cpp | 41 +++++++++++++++---- linux/payload/FreshMpsocHandler.h | 9 +++- linux/payload/plocMpsocHelpers.h | 4 ++ tmtc | 2 +- 13 files changed, 69 insertions(+), 23 deletions(-) diff --git a/bsp_hosted/fsfwconfig/events/translateEvents.cpp b/bsp_hosted/fsfwconfig/events/translateEvents.cpp index 8d67f14d..65081593 100644 --- a/bsp_hosted/fsfwconfig/events/translateEvents.cpp +++ b/bsp_hosted/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 324 translations. + * @brief Auto-generated event translation file. Contains 325 translations. * @details - * Generated on: 2024-04-17 11:22:10 + * Generated on: 2024-05-06 13:06:03 */ #include "translateEvents.h" @@ -142,6 +142,7 @@ const char *MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH_STRING = "MPSOC_HANDLER_SEQUEN const char *MPSOC_SHUTDOWN_FAILED_STRING = "MPSOC_SHUTDOWN_FAILED"; const char *SUPV_NOT_ON_STRING = "SUPV_NOT_ON"; const char *SUPV_REPLY_TIMEOUT_STRING = "SUPV_REPLY_TIMEOUT"; +const char *CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING = "CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE"; const char *SELF_TEST_I2C_FAILURE_STRING = "SELF_TEST_I2C_FAILURE"; const char *SELF_TEST_SPI_FAILURE_STRING = "SELF_TEST_SPI_FAILURE"; const char *SELF_TEST_ADC_FAILURE_STRING = "SELF_TEST_ADC_FAILURE"; @@ -606,6 +607,8 @@ const char *translateEvents(Event event) { return SUPV_NOT_ON_STRING; case (11608): return SUPV_REPLY_TIMEOUT_STRING; + case (11609): + return CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING; case (11701): return SELF_TEST_I2C_FAILURE_STRING; case (11702): diff --git a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp index c536b709..ef5a91de 100644 --- a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp +++ b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 176 translations. - * Generated on: 2024-04-17 11:22:10 + * Generated on: 2024-05-06 13:06:03 */ #include "translateObjects.h" diff --git a/bsp_q7s/objectFactory.cpp b/bsp_q7s/objectFactory.cpp index f9ae8dc6..e1ef0816 100644 --- a/bsp_q7s/objectFactory.cpp +++ b/bsp_q7s/objectFactory.cpp @@ -65,6 +65,7 @@ #include "linux/payload/PlocMpsocSpecialComHelper.h" #include "linux/payload/SerialConfig.h" #include "mission/config/configfile.h" +#include "mission/power/defs.h" #include "mission/system/acs/AcsBoardFdir.h" #include "mission/system/acs/AcsSubsystem.h" #include "mission/system/acs/RwAssembly.h" @@ -635,9 +636,9 @@ void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwit auto specialComHelper = new PlocMpsocSpecialComHelper(objects::PLOC_MPSOC_HELPER, *mpsocCommunication); DhbConfig dhbConf(objects::PLOC_MPSOC_HANDLER); - auto* mpsocHandler = new FreshMpsocHandler(dhbConf, *mpsocCommunication, *specialComHelper, - Gpio(gpioIds::ENABLE_MPSOC_UART, gpioComIF), - objects::PLOC_SUPERVISOR_HANDLER); + auto* mpsocHandler = new FreshMpsocHandler( + dhbConf, *mpsocCommunication, *specialComHelper, Gpio(gpioIds::ENABLE_MPSOC_UART, gpioComIF), + objects::PLOC_SUPERVISOR_HANDLER, pwrSwitcher, power::PDU2_CH8_PAYLOAD_CAMERA); mpsocHandler->connectModeTreeParent(satsystem::payload::SUBSYSTEM); #endif /* OBSW_ADD_PLOC_MPSOC == 1 */ #if OBSW_ADD_PLOC_SUPERVISOR == 1 diff --git a/generators/bsp_hosted_events.csv b/generators/bsp_hosted_events.csv index 6f5579c0..6a851c62 100644 --- a/generators/bsp_hosted_events.csv +++ b/generators/bsp_hosted_events.csv @@ -136,6 +136,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/plocMpsocHelpers.h 11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/plocMpsocHelpers.h 11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;No description;linux/payload/plocMpsocHelpers.h +11609;0x2d59;CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE;LOW;Camera must be commanded on first.;linux/payload/plocMpsocHelpers.h 11701;0x2db5;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11702;0x2db6;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11703;0x2db7;SELF_TEST_ADC_FAILURE;LOW;Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv index 6f5579c0..6a851c62 100644 --- a/generators/bsp_q7s_events.csv +++ b/generators/bsp_q7s_events.csv @@ -136,6 +136,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/plocMpsocHelpers.h 11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/plocMpsocHelpers.h 11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;No description;linux/payload/plocMpsocHelpers.h +11609;0x2d59;CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE;LOW;Camera must be commanded on first.;linux/payload/plocMpsocHelpers.h 11701;0x2db5;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11702;0x2db6;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11703;0x2db7;SELF_TEST_ADC_FAILURE;LOW;Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index 8d67f14d..65081593 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 324 translations. + * @brief Auto-generated event translation file. Contains 325 translations. * @details - * Generated on: 2024-04-17 11:22:10 + * Generated on: 2024-05-06 13:06:03 */ #include "translateEvents.h" @@ -142,6 +142,7 @@ const char *MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH_STRING = "MPSOC_HANDLER_SEQUEN const char *MPSOC_SHUTDOWN_FAILED_STRING = "MPSOC_SHUTDOWN_FAILED"; const char *SUPV_NOT_ON_STRING = "SUPV_NOT_ON"; const char *SUPV_REPLY_TIMEOUT_STRING = "SUPV_REPLY_TIMEOUT"; +const char *CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING = "CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE"; const char *SELF_TEST_I2C_FAILURE_STRING = "SELF_TEST_I2C_FAILURE"; const char *SELF_TEST_SPI_FAILURE_STRING = "SELF_TEST_SPI_FAILURE"; const char *SELF_TEST_ADC_FAILURE_STRING = "SELF_TEST_ADC_FAILURE"; @@ -606,6 +607,8 @@ const char *translateEvents(Event event) { return SUPV_NOT_ON_STRING; case (11608): return SUPV_REPLY_TIMEOUT_STRING; + case (11609): + return CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING; case (11701): return SELF_TEST_I2C_FAILURE_STRING; case (11702): diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index 5ef8a2a7..f1fa381c 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 180 translations. - * Generated on: 2024-04-17 11:22:10 + * Generated on: 2024-05-06 13:06:03 */ #include "translateObjects.h" diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index 8d67f14d..65081593 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 324 translations. + * @brief Auto-generated event translation file. Contains 325 translations. * @details - * Generated on: 2024-04-17 11:22:10 + * Generated on: 2024-05-06 13:06:03 */ #include "translateEvents.h" @@ -142,6 +142,7 @@ const char *MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH_STRING = "MPSOC_HANDLER_SEQUEN const char *MPSOC_SHUTDOWN_FAILED_STRING = "MPSOC_SHUTDOWN_FAILED"; const char *SUPV_NOT_ON_STRING = "SUPV_NOT_ON"; const char *SUPV_REPLY_TIMEOUT_STRING = "SUPV_REPLY_TIMEOUT"; +const char *CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING = "CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE"; const char *SELF_TEST_I2C_FAILURE_STRING = "SELF_TEST_I2C_FAILURE"; const char *SELF_TEST_SPI_FAILURE_STRING = "SELF_TEST_SPI_FAILURE"; const char *SELF_TEST_ADC_FAILURE_STRING = "SELF_TEST_ADC_FAILURE"; @@ -606,6 +607,8 @@ const char *translateEvents(Event event) { return SUPV_NOT_ON_STRING; case (11608): return SUPV_REPLY_TIMEOUT_STRING; + case (11609): + return CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING; case (11701): return SELF_TEST_I2C_FAILURE_STRING; case (11702): diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index 5ef8a2a7..f1fa381c 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 180 translations. - * Generated on: 2024-04-17 11:22:10 + * Generated on: 2024-05-06 13:06:03 */ #include "translateObjects.h" diff --git a/linux/payload/FreshMpsocHandler.cpp b/linux/payload/FreshMpsocHandler.cpp index 65c273c2..662bd636 100644 --- a/linux/payload/FreshMpsocHandler.cpp +++ b/linux/payload/FreshMpsocHandler.cpp @@ -8,22 +8,29 @@ #include "fsfw/devicehandlers/FreshDeviceHandlerBase.h" #include "fsfw/ipc/MessageQueueIF.h" #include "fsfw/ipc/QueueFactory.h" +#include "fsfw/ipc/messageQueueDefinitions.h" +#include "fsfw/power/PowerSwitchIF.h" +#include "fsfw/power/definitions.h" #include "fsfw/returnvalues/returnvalue.h" #include "fsfw/serialize/SerializeAdapter.h" #include "linux/payload/MpsocCommunication.h" #include "linux/payload/plocMpsocHelpers.h" #include "linux/payload/plocSupvDefs.h" +#include "mission/power/gsDefs.h" FreshMpsocHandler::FreshMpsocHandler(DhbConfig cfg, MpsocCommunication& comInterface, PlocMpsocSpecialComHelper& specialComHelper, - Gpio uartIsolatorSwitch, object_id_t supervisorHandler) + Gpio uartIsolatorSwitch, object_id_t supervisorHandler, + PowerSwitchIF& powerSwitcher, power::Switch_t camSwitchId) : FreshDeviceHandlerBase(cfg), comInterface(comInterface), specialComHelper(specialComHelper), commandActionHelper(this), uartIsolatorSwitch(uartIsolatorSwitch), hkReport(this), - supervisorHandler(supervisorHandler) { + supervisorHandler(supervisorHandler), + powerSwitcher(powerSwitcher), + camSwitchId(camSwitchId) { commandActionHelperQueue = QueueFactory::instance()->createMessageQueue(10); eventQueue = QueueFactory::instance()->createMessageQueue(10); spParams.maxSize = sizeof(commandBuffer); @@ -77,8 +84,13 @@ void FreshMpsocHandler::performDefaultDeviceOperation() { } } + // We checked the action queue beforehand, so action commands should always be performed + // before normal commands. if (mode == MODE_NORMAL and not activeCmdInfo.pending) { - // TODO: Take care of regular periodic commanding here. + ReturnValue_t result = commandTcGetHkReport(); + if (result == returnvalue::OK) { + commandInitHandling(mpsoc::TC_GET_HK_REPORT, MessageQueueIF::NO_QUEUE); + } } if (activeCmdInfo.pending and activeCmdInfo.cmdCountdown.hasTimedOut()) { @@ -224,6 +236,11 @@ ReturnValue_t FreshMpsocHandler::checkModeCommand(Mode_t mode, Submode_t submode return HasModesIF::INVALID_SUBMODE; } } + if (submode == mpsoc::Submode::SNAPSHOT and + powerSwitcher.getSwitchState(camSwitchId) != PowerSwitchIF::SWITCH_ON) { + triggerEvent(mpsoc::CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE); + return HasModesIF::TRANS_NOT_ALLOWED; + } *msToReachTheMode = MPSOC_MODE_CMD_TIMEOUT_MS; return returnvalue::OK; } @@ -583,16 +600,20 @@ ReturnValue_t FreshMpsocHandler::executeRegularCmd(ActionId_t actionId, } if (result == returnvalue::OK) { - activeCmdInfo.start(actionId, commandedBy); - /** - * Flushing the receive buffer to make sure there are no data left from a faulty reply. - */ - comInterface.getComHelper().flushUartRxBuffer(); + commandInitHandling(actionId, commandedBy); } return result; } +void FreshMpsocHandler::commandInitHandling(ActionId_t actionId, MessageQueueId_t commandedBy) { + activeCmdInfo.start(actionId, commandedBy); + /** + * Flushing the receive buffer to make sure there are no data left from a faulty reply. + */ + comInterface.getComHelper().flushUartRxBuffer(); +} + ReturnValue_t FreshMpsocHandler::commandTcMemWrite(const uint8_t* commandData, size_t commandDataLen) { ReturnValue_t result = returnvalue::OK; @@ -1229,7 +1250,9 @@ bool FreshMpsocHandler::handleHwShutdown() { supvTransitionCd.resetTimer(); powerState = PowerState::PENDING_SHUTDOWN; } else { - triggerEvent(mpsoc::SUPV_NOT_ON, 0); + if ((this->mode != MODE_OFF) and (this->mode != MODE_UNDEFINED)) { + triggerEvent(mpsoc::SUPV_NOT_ON, 0); + } powerState = PowerState::DONE; } } diff --git a/linux/payload/FreshMpsocHandler.h b/linux/payload/FreshMpsocHandler.h index 88460764..f62cd051 100644 --- a/linux/payload/FreshMpsocHandler.h +++ b/linux/payload/FreshMpsocHandler.h @@ -1,3 +1,4 @@ +#include "fsfw/action/ActionMessage.h" #include "fsfw/action/CommandsActionsIF.h" #include "fsfw/devicehandlers/DeviceHandlerIF.h" #include "fsfw/devicehandlers/FreshDeviceHandlerBase.h" @@ -5,6 +6,8 @@ #include "fsfw/ipc/messageQueueDefinitions.h" #include "fsfw/modes/ModeMessage.h" #include "fsfw/objectmanager/SystemObjectIF.h" +#include "fsfw/power/PowerSwitchIF.h" +#include "fsfw/power/definitions.h" #include "fsfw/returnvalues/returnvalue.h" #include "fsfw_hal/linux/gpio/Gpio.h" #include "linux/payload/MpsocCommunication.h" @@ -18,7 +21,8 @@ class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsI FreshMpsocHandler(DhbConfig cfg, MpsocCommunication& comInterface, PlocMpsocSpecialComHelper& specialComHelper, Gpio uartIsolatorSwitch, - object_id_t supervisorHandler); + object_id_t supervisorHandler, PowerSwitchIF& powerSwitcher, + power::Switch_t camSwitchId); /** * Periodic helper executed function, implemented by child class. @@ -128,6 +132,8 @@ class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsI TmMemReadReport tmMemReadReport; uint32_t lastReplySequenceCount = 0; uint8_t skipSupvCommandingToOn = false; + PowerSwitchIF& powerSwitcher; + power::Switch_t camSwitchId; // HK manager abstract functions. LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; @@ -202,4 +208,5 @@ class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsI void commandSubmodeTransition(); void commonSpecialComInit(); void commonSpecialComStop(); + void commandInitHandling(ActionId_t actionId, MessageQueueId_t commandedBy); }; diff --git a/linux/payload/plocMpsocHelpers.h b/linux/payload/plocMpsocHelpers.h index 60356f56..ce055873 100644 --- a/linux/payload/plocMpsocHelpers.h +++ b/linux/payload/plocMpsocHelpers.h @@ -8,6 +8,7 @@ #include "eive/eventSubsystemIds.h" #include "eive/resultClassIds.h" #include "fsfw/action/HasActionsIF.h" +#include "fsfw/events/Event.h" #include "fsfw/returnvalues/returnvalue.h" #include "fsfw/serialize/SerializeAdapter.h" #include "fsfw/serialize/SerializeIF.h" @@ -113,6 +114,9 @@ static const Event MPSOC_SHUTDOWN_FAILED = MAKE_EVENT(6, severity::HIGH); //! ON transition. static constexpr Event SUPV_NOT_ON = event::makeEvent(SUBSYSTEM_ID, 7, severity::LOW); static constexpr Event SUPV_REPLY_TIMEOUT = event::makeEvent(SUBSYSTEM_ID, 8, severity::LOW); +//! [EXPORT] : [COMMENT] Camera must be commanded on first. +static constexpr Event CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE = + event::makeEvent(SUBSYSTEM_ID, 9, severity::LOW); enum ParamId : uint8_t { SKIP_SUPV_ON_COMMANDING = 0x01 }; diff --git a/tmtc b/tmtc index 5e1b12fa..376f94b1 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 5e1b12fa527c21131883176cbcb9f8abe4199d91 +Subproject commit 376f94b1673921ef63f7cb11f4852afd9f8fa818 -- 2.34.1 From b579cd86c1da428f2a08f2977236def53d6731fb Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 6 May 2024 13:30:28 +0200 Subject: [PATCH 6/9] make marius extremely happy --- linux/payload/plocMpsocHelpers.h | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/payload/plocMpsocHelpers.h b/linux/payload/plocMpsocHelpers.h index ce055873..a059a20c 100644 --- a/linux/payload/plocMpsocHelpers.h +++ b/linux/payload/plocMpsocHelpers.h @@ -113,6 +113,7 @@ static const Event MPSOC_SHUTDOWN_FAILED = MAKE_EVENT(6, severity::HIGH); //! [EXPORT] : [COMMENT] SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for //! ON transition. static constexpr Event SUPV_NOT_ON = event::makeEvent(SUBSYSTEM_ID, 7, severity::LOW); +//! [EXPORT] : [COMMENT] SUPV reply timeout. static constexpr Event SUPV_REPLY_TIMEOUT = event::makeEvent(SUBSYSTEM_ID, 8, severity::LOW); //! [EXPORT] : [COMMENT] Camera must be commanded on first. static constexpr Event CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE = -- 2.34.1 From 8103b2fa0d52074edca5c09d9e99bc94ead13daa Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 6 May 2024 13:48:32 +0200 Subject: [PATCH 7/9] events --- bsp_hosted/fsfwconfig/events/translateEvents.cpp | 2 +- bsp_hosted/fsfwconfig/objects/translateObjects.cpp | 2 +- generators/bsp_hosted_events.csv | 2 +- generators/bsp_q7s_events.csv | 2 +- generators/events/translateEvents.cpp | 2 +- generators/objects/translateObjects.cpp | 2 +- linux/fsfwconfig/events/translateEvents.cpp | 2 +- linux/fsfwconfig/objects/translateObjects.cpp | 2 +- tmtc | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bsp_hosted/fsfwconfig/events/translateEvents.cpp b/bsp_hosted/fsfwconfig/events/translateEvents.cpp index 65081593..7a8da305 100644 --- a/bsp_hosted/fsfwconfig/events/translateEvents.cpp +++ b/bsp_hosted/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 325 translations. * @details - * Generated on: 2024-05-06 13:06:03 + * Generated on: 2024-05-06 13:47:38 */ #include "translateEvents.h" diff --git a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp index ef5a91de..53332c1e 100644 --- a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp +++ b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 176 translations. - * Generated on: 2024-05-06 13:06:03 + * Generated on: 2024-05-06 13:47:38 */ #include "translateObjects.h" diff --git a/generators/bsp_hosted_events.csv b/generators/bsp_hosted_events.csv index 6a851c62..7b833ae4 100644 --- a/generators/bsp_hosted_events.csv +++ b/generators/bsp_hosted_events.csv @@ -135,7 +135,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/plocMpsocHelpers.h 11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/plocMpsocHelpers.h 11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/plocMpsocHelpers.h -11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;No description;linux/payload/plocMpsocHelpers.h +11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;SUPV reply timeout.;linux/payload/plocMpsocHelpers.h 11609;0x2d59;CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE;LOW;Camera must be commanded on first.;linux/payload/plocMpsocHelpers.h 11701;0x2db5;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11702;0x2db6;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv index 6a851c62..7b833ae4 100644 --- a/generators/bsp_q7s_events.csv +++ b/generators/bsp_q7s_events.csv @@ -135,7 +135,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/plocMpsocHelpers.h 11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/plocMpsocHelpers.h 11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/plocMpsocHelpers.h -11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;No description;linux/payload/plocMpsocHelpers.h +11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;SUPV reply timeout.;linux/payload/plocMpsocHelpers.h 11609;0x2d59;CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE;LOW;Camera must be commanded on first.;linux/payload/plocMpsocHelpers.h 11701;0x2db5;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11702;0x2db6;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index 65081593..7a8da305 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 325 translations. * @details - * Generated on: 2024-05-06 13:06:03 + * Generated on: 2024-05-06 13:47:38 */ #include "translateEvents.h" diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index f1fa381c..048a77da 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 180 translations. - * Generated on: 2024-05-06 13:06:03 + * Generated on: 2024-05-06 13:47:38 */ #include "translateObjects.h" diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index 65081593..7a8da305 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 325 translations. * @details - * Generated on: 2024-05-06 13:06:03 + * Generated on: 2024-05-06 13:47:38 */ #include "translateEvents.h" diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index f1fa381c..048a77da 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 180 translations. - * Generated on: 2024-05-06 13:06:03 + * Generated on: 2024-05-06 13:47:38 */ #include "translateObjects.h" diff --git a/tmtc b/tmtc index 376f94b1..ada099ca 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 376f94b1673921ef63f7cb11f4852afd9f8fa818 +Subproject commit ada099cab1c1ab842d775ff4b658f97246122b18 -- 2.34.1 From 215f2189a6ad4e5c9d0d4614c6641341bf092566 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 6 May 2024 14:17:25 +0200 Subject: [PATCH 8/9] better name for split file command --- linux/payload/FreshMpsocHandler.cpp | 12 ++++++------ linux/payload/FreshMpsocHandler.h | 2 +- linux/payload/plocMpsocHelpers.h | 6 +++--- tmtc | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/linux/payload/FreshMpsocHandler.cpp b/linux/payload/FreshMpsocHandler.cpp index 662bd636..e0bf75e4 100644 --- a/linux/payload/FreshMpsocHandler.cpp +++ b/linux/payload/FreshMpsocHandler.cpp @@ -584,8 +584,8 @@ ReturnValue_t FreshMpsocHandler::executeRegularCmd(ActionId_t actionId, result = commandTcSimplexStreamFile(commandData, commandDataLen); break; } - case (mpsoc::TC_SIMPLEX_STORE_FILE): { - result = commandTcSimplexStoreFile(commandData, commandDataLen); + case (mpsoc::TC_SPLIT_FILE): { + result = commandTcSplitFile(commandData, commandDataLen); break; } case (mpsoc::TC_DOWNLINK_DATA_MODULATE): { @@ -762,14 +762,14 @@ ReturnValue_t FreshMpsocHandler::commandTcSimplexStreamFile(const uint8_t* comma return returnvalue::OK; } -ReturnValue_t FreshMpsocHandler::commandTcSimplexStoreFile(const uint8_t* commandData, +ReturnValue_t FreshMpsocHandler::commandTcSplitFile(const uint8_t* commandData, size_t commandDataLen) { - mpsoc::TcSimplexStoreFile tcSimplexStoreFile(spParams, commandSequenceCount); - ReturnValue_t result = tcSimplexStoreFile.setPayload(commandData, commandDataLen); + mpsoc::TcSplitFile tcSplitFile(spParams, commandSequenceCount); + ReturnValue_t result = tcSplitFile.setPayload(commandData, commandDataLen); if (result != returnvalue::OK) { return result; } - finishAndSendTc(mpsoc::TC_SIMPLEX_STORE_FILE, tcSimplexStoreFile); + finishAndSendTc(mpsoc::TC_SPLIT_FILE, tcSplitFile); return returnvalue::OK; } diff --git a/linux/payload/FreshMpsocHandler.h b/linux/payload/FreshMpsocHandler.h index f62cd051..fce42dee 100644 --- a/linux/payload/FreshMpsocHandler.h +++ b/linux/payload/FreshMpsocHandler.h @@ -187,7 +187,7 @@ class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsI ReturnValue_t commandTcModeIdle(); ReturnValue_t commandTcCamTakePic(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t commandTcSimplexStreamFile(const uint8_t* commandData, size_t commandDataLen); - ReturnValue_t commandTcSimplexStoreFile(const uint8_t* commandData, size_t commandDataLen); + ReturnValue_t commandTcSplitFile(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t commandTcDownlinkDataModulate(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t commandTcModeSnapshot(); diff --git a/linux/payload/plocMpsocHelpers.h b/linux/payload/plocMpsocHelpers.h index a059a20c..d596ab6c 100644 --- a/linux/payload/plocMpsocHelpers.h +++ b/linux/payload/plocMpsocHelpers.h @@ -210,7 +210,7 @@ static const DeviceCommandId_t TC_FLASH_GET_DIRECTORY_CONTENT = 28; static const DeviceCommandId_t TM_FLASH_DIRECTORY_CONTENT = 29; static constexpr DeviceCommandId_t TC_FLASH_READ_FULL_FILE = 30; // Store file on MPSoC. -static const DeviceCommandId_t TC_SIMPLEX_STORE_FILE = 31; +static const DeviceCommandId_t TC_SPLIT_FILE = 31; static const DeviceCommandId_t TC_VERIFY_BOOT = 32; static const DeviceCommandId_t TC_ENABLE_TC_EXECTION = 33; static const DeviceCommandId_t TC_FLASH_MKFS = 34; @@ -1056,9 +1056,9 @@ class TcSimplexStreamFile : public TcBase { /** * @brief Class to build simplex send file command */ -class TcSimplexStoreFile : public TcBase { +class TcSplitFile : public TcBase { public: - TcSimplexStoreFile(ploc::SpTcParams params, uint16_t sequenceCount) + TcSplitFile(ploc::SpTcParams params, uint16_t sequenceCount) : TcBase(params, apid::TC_SIMPLEX_SEND_FILE, sequenceCount) {} ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { diff --git a/tmtc b/tmtc index ada099ca..9cc4fa70 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit ada099cab1c1ab842d775ff4b658f97246122b18 +Subproject commit 9cc4fa702c23e795160c5d62fd448726b0f30f43 -- 2.34.1 From 7e8d995b52eb65d230b334c899c285d93b96b6d0 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 6 May 2024 14:20:13 +0200 Subject: [PATCH 9/9] changelog and tmtc --- CHANGELOG.md | 4 ++++ tmtc | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21ec3eb5..2dbfe23d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +# [v8.0.0] + +- `eive-tmtc` v7.0.0 + ## Fixed - Fixed calculation for target rotation rate during pointing modes. diff --git a/tmtc b/tmtc index 9cc4fa70..9a06c64d 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 9cc4fa702c23e795160c5d62fd448726b0f30f43 +Subproject commit 9a06c64dfac3f4283c2d5af72a9c095f4726480b -- 2.34.1