Re-work MPSoC handler module
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
This commit is contained in:
@ -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"
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
1224
linux/payload/FreshMpsocHandler.cpp
Normal file
1224
linux/payload/FreshMpsocHandler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
206
linux/payload/FreshMpsocHandler.h
Normal file
206
linux/payload/FreshMpsocHandler.h
Normal file
@ -0,0 +1,206 @@
|
||||
#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"
|
||||
|
||||
static constexpr bool MPSOC_TX_WIRETAPPING = true;
|
||||
static constexpr bool MPSOC_RX_WIRETAPPING = true;
|
||||
|
||||
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<uint32_t> peStatus = PoolEntry<uint32_t>();
|
||||
PoolEntry<uint8_t> peMode = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peDownlinkPwrOn = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peDownlinkReplyActive = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peDownlinkJesdSyncStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peDownlinkDacStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peCameraStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peCameraSdiStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<float> peCameraFpgaTemp = PoolEntry<float>();
|
||||
PoolEntry<float> peCameraSocTemp = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonTemp = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccInt = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccAux = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccBram = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccPaux = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccPint = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccPdro = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonMb12V = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonMb3V3 = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonMb1V8 = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc12V = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc5V = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc3V3 = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc3V3VA = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc2V5DDR = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc1V2DDR = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc0V9 = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc0V6VTT = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonSafeCotsCur = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonNvm4XoCur = PoolEntry<float>();
|
||||
PoolEntry<uint16_t> peSemUncorrectableErrs = PoolEntry<uint16_t>();
|
||||
PoolEntry<uint16_t> peSemCorrectableErrs = PoolEntry<uint16_t>();
|
||||
PoolEntry<uint8_t> peSemStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peRebootMpsocRequired = PoolEntry<uint8_t>();
|
||||
|
||||
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();
|
||||
};
|
@ -1299,7 +1299,7 @@ void FreshSupvHandler::handleExecutionFailureReport(ActiveCmdInfo& info, Executi
|
||||
triggerEvent(SUPV_EXE_FAILURE, info.commandId, static_cast<uint32_t>(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;
|
||||
}
|
||||
|
72
linux/payload/MpsocCommunication.cpp
Normal file
72
linux/payload/MpsocCommunication.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
#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) {
|
||||
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, availableReadData);
|
||||
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; }
|
43
linux/payload/MpsocCommunication.h
Normal file
43
linux/payload/MpsocCommunication.h
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
|
||||
#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_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;
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -1,326 +0,0 @@
|
||||
#ifndef BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_
|
||||
#define BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_
|
||||
|
||||
#include <linux/payload/PlocMpsocSpecialComHelper.h>
|
||||
#include <linux/payload/mpsocRetvals.h>
|
||||
#include <linux/payload/plocMpsocHelpers.h>
|
||||
#include <linux/payload/plocSupvDefs.h>
|
||||
#include <mission/controller/controllerdefinitions/PowerCtrlDefinitions.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#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;
|
||||
|
||||
/**
|
||||
* @brief This is the device handler for the MPSoC of the payload computer.
|
||||
*
|
||||
* @details The PLOC uses the space packet protocol for communication. Each command will be
|
||||
* answered with at least one acknowledgment and one execution report.
|
||||
* Flight manual:
|
||||
* https://egit.irs.uni-stuttgart.de/redmine/projects/eive-flight-manual/wiki/PLOC_MPSoC ICD:
|
||||
* https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_TAS-ILH-IRS/ICD-PLOC/ILH&fileid=1030263
|
||||
*
|
||||
* @note The sequence count in the space packets must be incremented with each received and sent
|
||||
* packet otherwise the MPSoC will reply with an acknowledgment failure report.
|
||||
*
|
||||
* NOTE: This is not an example for a good device handler, DO NOT USE THIS AS A REFERENCE HANDLER.
|
||||
* @author J. Meier, R. Mueller
|
||||
*/
|
||||
class PlocMpsocHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param ojectId Object ID of the MPSoC handler
|
||||
* @param uartcomIFid Object ID of the UART communication interface
|
||||
* @param comCookie UART communication cookie
|
||||
* @param plocMPSoCHelper Pointer to MPSoC helper object
|
||||
* @param uartIsolatorSwitch Gpio object representing the GPIO connected to the UART isolator
|
||||
* module in the programmable logic
|
||||
* @param supervisorHandler Object ID of the supervisor handler
|
||||
*/
|
||||
PlocMpsocHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF* comCookie,
|
||||
PlocMpsocSpecialComHelper* plocMPSoCHelper, Gpio uartIsolatorSwitch,
|
||||
object_id_t supervisorHandler);
|
||||
virtual ~PlocMpsocHandler();
|
||||
virtual ReturnValue_t initialize() override;
|
||||
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) override;
|
||||
void performOperationHook() override;
|
||||
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;
|
||||
|
||||
protected:
|
||||
void doStartUp() override;
|
||||
void doShutDown() override;
|
||||
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t* id) override;
|
||||
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t* id) override;
|
||||
void fillCommandAndReplyMap() override;
|
||||
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t* commandData,
|
||||
size_t commandDataLen) override;
|
||||
ReturnValue_t scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId,
|
||||
size_t* foundLen) override;
|
||||
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) override;
|
||||
void setNormalDatapoolEntriesInvalid() override;
|
||||
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator command,
|
||||
uint8_t expectedReplies = 1, bool useAlternateId = false,
|
||||
DeviceCommandId_t alternateReplyID = 0) override;
|
||||
size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override;
|
||||
ReturnValue_t doSendReadHook() override;
|
||||
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||
bool dontCheckQueue() override;
|
||||
|
||||
private:
|
||||
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);
|
||||
|
||||
static const uint16_t APID_MASK = 0x7FF;
|
||||
static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF;
|
||||
|
||||
mpsoc::HkReport hkReport;
|
||||
Countdown mpsocBootTransitionCd = Countdown(6500);
|
||||
Countdown supvTransitionCd = Countdown(3000);
|
||||
|
||||
MessageQueueIF* eventQueue = nullptr;
|
||||
MessageQueueIF* commandActionHelperQueue = nullptr;
|
||||
|
||||
SourceSequenceCounter sequenceCount = SourceSequenceCounter(0);
|
||||
|
||||
uint8_t commandBuffer[mpsoc::MAX_COMMAND_SIZE];
|
||||
SpacePacketCreator creator;
|
||||
ploc::SpTcParams spParams = ploc::SpTcParams(creator);
|
||||
|
||||
PoolEntry<uint32_t> peStatus = PoolEntry<uint32_t>();
|
||||
PoolEntry<uint8_t> peMode = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peDownlinkPwrOn = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peDownlinkReplyActive = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peDownlinkJesdSyncStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peDownlinkDacStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peCameraStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peCameraSdiStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<float> peCameraFpgaTemp = PoolEntry<float>();
|
||||
PoolEntry<float> peCameraSocTemp = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonTemp = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccInt = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccAux = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccBram = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccPaux = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccPint = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccPdro = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonMb12V = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonMb3V3 = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonMb1V8 = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc12V = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc5V = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc3V3 = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc3V3VA = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc2V5DDR = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc1V2DDR = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc0V9 = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc0V6VTT = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonSafeCotsCur = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonNvm4XoCur = PoolEntry<float>();
|
||||
PoolEntry<uint16_t> peSemUncorrectableErrs = PoolEntry<uint16_t>();
|
||||
PoolEntry<uint16_t> peSemCorrectableErrs = PoolEntry<uint16_t>();
|
||||
PoolEntry<uint8_t> peSemStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peRebootMpsocRequired = PoolEntry<uint8_t>();
|
||||
|
||||
/**
|
||||
* This variable is used to store the id of the next reply to receive. This is necessary
|
||||
* because the PLOC sends as reply to each command at least one acknowledgment and execution
|
||||
* report.
|
||||
*/
|
||||
DeviceCommandId_t nextReplyId = mpsoc::NONE;
|
||||
|
||||
SerialComIF* uartComIf = nullptr;
|
||||
|
||||
PlocMpsocSpecialComHelper* specialComHelper = nullptr;
|
||||
Gpio uartIsolatorSwitch;
|
||||
object_id_t supervisorHandler = 0;
|
||||
CommandActionHelper commandActionHelper;
|
||||
|
||||
// Used to block incoming commands when MPSoC helper class is currently executing a command
|
||||
bool specialComHelperExecuting = false;
|
||||
bool commandIsPending = false;
|
||||
|
||||
struct TmMemReadReport {
|
||||
static const uint8_t FIX_SIZE = 14;
|
||||
size_t rememberRequestedSize = 0;
|
||||
};
|
||||
|
||||
TmMemReadReport tmMemReadReport;
|
||||
Countdown cmdCountdown = Countdown(10000);
|
||||
|
||||
struct TelemetryBuffer {
|
||||
uint16_t length = 0;
|
||||
uint8_t buffer[mpsoc::SP_MAX_SIZE];
|
||||
};
|
||||
|
||||
size_t foundPacketLen = 0;
|
||||
TelemetryBuffer tmBuffer;
|
||||
|
||||
enum class StartupState { IDLE, HW_INIT, DONE } startupState = StartupState::IDLE;
|
||||
enum class PowerState { IDLE, PENDING_STARTUP, PENDING_SHUTDOWN, SUPV_FAILED, DONE };
|
||||
|
||||
PowerState powerState = PowerState::IDLE;
|
||||
|
||||
uint8_t skipSupvCommandingToOn = false;
|
||||
|
||||
/**
|
||||
* @brief Handles events received from the PLOC MPSoC helper
|
||||
*/
|
||||
void handleEvent(EventMessage* eventMessage);
|
||||
|
||||
ReturnValue_t prepareTcMemWrite(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t prepareTcMemRead(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t prepareTcFlashDelete(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t prepareTcReplayStart(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t prepareTcReplayStop();
|
||||
ReturnValue_t prepareTcDownlinkPwrOn(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t prepareTcDownlinkPwrOff();
|
||||
ReturnValue_t prepareTcGetHkReport();
|
||||
ReturnValue_t prepareTcGetDirContent(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t prepareTcReplayWriteSequence(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t prepareTcCamCmdSend(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t prepareTcModeIdle();
|
||||
ReturnValue_t prepareTcCamTakePic(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t prepareTcSimplexSendFile(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t prepareTcDownlinkDataModulate(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t prepareTcModeSnapshot();
|
||||
ReturnValue_t finishTcPrep(mpsoc::TcBase& tcBase);
|
||||
|
||||
/**
|
||||
* @brief This function checks the crc of the received PLOC reply.
|
||||
*
|
||||
* @param start Pointer to the first byte of the reply.
|
||||
* @param foundLen Pointer to the length of the whole packet.
|
||||
*
|
||||
* @return returnvalue::OK if CRC is ok, otherwise CRC_FAILURE.
|
||||
*/
|
||||
ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen);
|
||||
|
||||
/**
|
||||
* @brief This function handles the acknowledgment report.
|
||||
*
|
||||
* @param data Pointer to the data holding the acknowledgment report.
|
||||
*
|
||||
* @return returnvalue::OK if successful, otherwise an error code.
|
||||
*/
|
||||
ReturnValue_t handleAckReport(const uint8_t* data);
|
||||
|
||||
/**
|
||||
* @brief This function handles the data of a execution report.
|
||||
*
|
||||
* @param data Pointer to the received data packet.
|
||||
*
|
||||
* @return returnvalue::OK if successful, otherwise an error code.
|
||||
*/
|
||||
ReturnValue_t handleExecutionReport(const uint8_t* data);
|
||||
|
||||
/**
|
||||
* @brief This function handles the memory read report.
|
||||
*
|
||||
* @param data Pointer to the data buffer holding the memory read report.
|
||||
*
|
||||
* @return returnvalue::OK if successful, otherwise an error code.
|
||||
*/
|
||||
ReturnValue_t handleMemoryReadReport(const uint8_t* data);
|
||||
|
||||
ReturnValue_t handleGetHkReport(const uint8_t* data);
|
||||
ReturnValue_t handleCamCmdRpt(const uint8_t* data);
|
||||
|
||||
/**
|
||||
* @brief Depending on the current active command, this function sets the reply id of the
|
||||
* next reply after a successful acknowledgment report has been received. This is
|
||||
* required by the function getNextReplyLength() to identify the length of the next
|
||||
* reply to read.
|
||||
*/
|
||||
void setNextReplyId();
|
||||
|
||||
/**
|
||||
* @brief This function handles action message replies in case the telemetry has been
|
||||
* requested by another object.
|
||||
*
|
||||
* @param data Pointer to the telemetry data.
|
||||
* @param dataSize Size of telemetry in bytes.
|
||||
* @param replyId Id of the reply. This will be added to the ActionMessage.
|
||||
*/
|
||||
void handleDeviceTm(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId);
|
||||
|
||||
/**
|
||||
* @brief In case an acknowledgment failure reply has been received this function disables
|
||||
* all previously enabled commands and resets the exepected replies variable of an
|
||||
* active command.
|
||||
*/
|
||||
void disableAllReplies();
|
||||
|
||||
/**
|
||||
* @brief This function sends a failure report if the active action was commanded by an other
|
||||
* object.
|
||||
*
|
||||
* @param replyId The id of the reply which signals a failure.
|
||||
* @param status A status byte which gives information about the failure type.
|
||||
*/
|
||||
void sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status);
|
||||
|
||||
/**
|
||||
* @brief This function disables the execution report reply. Within this function also the
|
||||
* the variable expectedReplies of an active command will be set to 0.
|
||||
*/
|
||||
void disableExeReportReply();
|
||||
|
||||
ReturnValue_t prepareTcModeReplay();
|
||||
|
||||
void cmdDoneHandler(bool success, ReturnValue_t result);
|
||||
bool handleHwStartup();
|
||||
bool handleHwShutdown();
|
||||
void stopSpecialComHelper();
|
||||
|
||||
void handleActionCommandFailure(ActionId_t actionId);
|
||||
|
||||
pwrctrl::EnablePl enablePl = pwrctrl::EnablePl(objects::POWER_CONTROLLER);
|
||||
ReturnValue_t checkModeCommand(Mode_t commandedMode, Submode_t commandedSubmode,
|
||||
uint32_t* msToReachTheMode) override;
|
||||
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) override;
|
||||
};
|
||||
|
||||
#endif /* BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_ */
|
@ -6,6 +6,8 @@
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
#include "linux/payload/MpsocCommunication.h"
|
||||
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/fs/FilesystemHelper.h"
|
||||
#endif
|
||||
@ -14,8 +16,9 @@
|
||||
|
||||
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);
|
||||
}
|
||||
@ -72,17 +75,6 @@ ReturnValue_t PlocMpsocSpecialComHelper::performOperation(uint8_t operationCode)
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelper::setComIF(DeviceCommunicationIF* communicationInterface_) {
|
||||
uartComIF = dynamic_cast<SerialComIF*>(communicationInterface_);
|
||||
if (uartComIF == nullptr) {
|
||||
sif::warning << "PlocMPSoCHelper::initialize: Invalid uart com if" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PlocMpsocSpecialComHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; }
|
||||
|
||||
void PlocMpsocSpecialComHelper::setSequenceCount(SourceSequenceCounter* sequenceCount_) {
|
||||
sequenceCount = sequenceCount_;
|
||||
}
|
||||
@ -117,7 +109,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; }
|
||||
@ -311,8 +304,7 @@ 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());
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PlocMPSoCHelper::sendCommand: Failed to send command" << std::endl;
|
||||
triggerEvent(MPSOC_SENDING_COMMAND_FAILED, result, static_cast<uint32_t>(internalState));
|
||||
@ -504,12 +496,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::checkReceivedTm() {
|
||||
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;
|
||||
}
|
||||
// No CRC check, this is already done by the communication interface..
|
||||
uint16_t recvSeqCnt = spReader.getSequenceCount();
|
||||
if (recvSeqCnt != *sequenceCount) {
|
||||
triggerEvent(MPSOC_HELPER_SEQ_CNT_MISMATCH, *sequenceCount, recvSeqCnt);
|
||||
@ -523,22 +510,17 @@ ReturnValue_t PlocMpsocSpecialComHelper::checkReceivedTm() {
|
||||
ReturnValue_t PlocMpsocSpecialComHelper::receive(uint8_t* data, size_t requestBytes,
|
||||
size_t* readBytes) {
|
||||
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<uint32_t>(static_cast<uint32_t>(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<uint32_t>(internalState));
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (*readBytes > 0) {
|
||||
std::memcpy(data, buffer, *readBytes);
|
||||
result = comInterface.parseAndRetrieveNextPacket();
|
||||
if (result == MpsocCommunication::PACKET_RECEIVED) {
|
||||
auto& spReader = comInterface.getSpReader();
|
||||
// Maybe unnecessary copy, but the easiest way to get this done for now..
|
||||
std::memcpy(data, spReader.getFullData(), spReader.getFullPacketLen());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -6,14 +6,12 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#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"
|
||||
#include "linux/payload/MpsocCommunication.h"
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/fs/SdCardManager.h"
|
||||
#endif
|
||||
@ -83,15 +81,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
|
||||
*
|
||||
@ -169,9 +164,10 @@ 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;
|
||||
|
126
linux/payload/SerialCommunicationHelper.cpp
Normal file
126
linux/payload/SerialCommunicationHelper.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
#include "SerialCommunicationHelper.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#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<int>(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;
|
||||
}
|
69
linux/payload/SerialCommunicationHelper.h
Normal file
69
linux/payload/SerialCommunicationHelper.h
Normal file
@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw_hal/linux/serial/SerialCookie.h>
|
||||
#include <fsfw_hal/linux/serial/helper.h>
|
||||
|
||||
#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);
|
||||
};
|
70
linux/payload/SerialConfig.h
Normal file
70
linux/payload/SerialConfig.h
Normal file
@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/devicehandlers/CookieIF.h>
|
||||
#include <fsfw/objectmanager/SystemObjectIF.h>
|
||||
#include <fsfw_hal/linux/serial/helper.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @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;
|
||||
};
|
@ -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_ */
|
@ -5,83 +5,83 @@ uint16_t mpsoc::getStatusFromRawData(const uint8_t* data) {
|
||||
}
|
||||
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::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;
|
||||
}
|
||||
|
@ -3,16 +3,73 @@
|
||||
|
||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
|
||||
#include <linux/payload/mpsocRetvals.h>
|
||||
#include <mission/payload/plocSpBase.h>
|
||||
|
||||
#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 uint32_t DEFAULT_CMD_TIMEOUT_MS = 5000;
|
||||
static constexpr uint32_t CMD_TIMEOUT_MKFS = 15000;
|
||||
|
||||
enum FlashId : uint8_t { FLASH_0 = 0, FLASH_1 = 0 };
|
||||
|
||||
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 +87,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 +151,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 +160,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 +211,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;
|
||||
@ -201,7 +280,7 @@ 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 const uint16_t UNKNOWN_APID = 0x5DD;
|
||||
static const uint16_t INCORRECT_LENGTH = 0x5DE;
|
||||
@ -227,12 +306,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
|
||||
} // namespace statusCode
|
||||
|
||||
/**
|
||||
* @brief Abstract base class for TC space packet of MPSoC.
|
||||
*/
|
||||
class TcBase : public ploc::SpTcBase, public MPSoCReturnValuesIF {
|
||||
class TcBase : public ploc::SpTcBase {
|
||||
public:
|
||||
virtual ~TcBase() = default;
|
||||
|
||||
@ -405,6 +484,32 @@ class FlashFclose : public TcBase {
|
||||
}
|
||||
};
|
||||
|
||||
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) {
|
||||
spParams.setFullPayloadLen(1 + CRC_SIZE);
|
||||
payloadStart[0] = flashId;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class to build flash write space packet.
|
||||
*/
|
||||
@ -710,7 +815,7 @@ 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;
|
||||
@ -832,9 +937,9 @@ class TcCamTakePic : public TcBase {
|
||||
/**
|
||||
* @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) {
|
||||
@ -845,13 +950,67 @@ class TcSimplexSendFile : public TcBase {
|
||||
if (fileName.size() + sizeof(NULL_TERMINATOR) > MAX_FILENAME_SIZE) {
|
||||
return FILENAME_TOO_LONG;
|
||||
}
|
||||
spParams.setFullPayloadLen(commandDataLen + CRC_SIZE);
|
||||
std::memcpy(payloadStart, commandData, commandDataLen);
|
||||
|
||||
std::memcpy(payloadStart, fileName.data(), fileName.length());
|
||||
payloadStart[fileName.length()] = 0;
|
||||
spParams.setFullPayloadLen(fileName.length() + 1);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
private:
|
||||
static const size_t MAX_DATA_LENGTH = 256;
|
||||
static constexpr 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<const char*>(*dataPtr));
|
||||
if (fileName.size() + sizeof(NULL_TERMINATOR) > MAX_FILENAME_SIZE) {
|
||||
return FILENAME_TOO_LONG;
|
||||
}
|
||||
size_t currentCopyIdx = 0;
|
||||
size_t payloadLen = fileName.length() + sizeof(NULL_TERMINATOR) + CRC_SIZE;
|
||||
if (chunkParameter > 1) {
|
||||
char divStr[16]{};
|
||||
sprintf(divStr, "DIV%03u", chunkParameter);
|
||||
std::memcpy(payloadStart, divStr, DIV_STR_LEN);
|
||||
payloadLen += DIV_STR_LEN;
|
||||
currentCopyIdx += DIV_STR_LEN;
|
||||
}
|
||||
|
||||
std::memcpy(payloadStart + currentCopyIdx, *dataPtr, fileName.length());
|
||||
spParams.setFullPayloadLen(payloadLen);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t chunkParameter = 0;
|
||||
static constexpr size_t MAX_DATA_LENGTH = 256;
|
||||
static constexpr size_t MIN_DATA_LENGTH = 4;
|
||||
static constexpr size_t DIV_STR_LEN = 6;
|
||||
};
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user