2021-11-01 12:41:20 +01:00
|
|
|
#ifndef LINUX_OBC_PDECHANDLER_H_
|
|
|
|
#define LINUX_OBC_PDECHANDLER_H_
|
|
|
|
|
2022-10-27 10:51:34 +02:00
|
|
|
#include <fsfw/timemanager/Countdown.h>
|
|
|
|
|
2023-04-14 13:11:11 +02:00
|
|
|
#include <atomic>
|
|
|
|
|
2021-11-08 12:25:12 +01:00
|
|
|
#include "OBSWConfig.h"
|
2021-11-01 12:41:20 +01:00
|
|
|
#include "PdecConfig.h"
|
2023-01-23 11:52:46 +01:00
|
|
|
#include "eive/definitions.h"
|
2022-01-17 15:58:27 +01:00
|
|
|
#include "fsfw/action/ActionHelper.h"
|
|
|
|
#include "fsfw/action/HasActionsIF.h"
|
|
|
|
#include "fsfw/objectmanager/SystemObject.h"
|
2023-02-23 15:27:24 +01:00
|
|
|
#include "fsfw/parameters/ParameterHelper.h"
|
|
|
|
#include "fsfw/parameters/ReceivesParameterMessagesIF.h"
|
2022-08-24 17:27:47 +02:00
|
|
|
#include "fsfw/returnvalues/returnvalue.h"
|
2021-11-01 12:41:20 +01:00
|
|
|
#include "fsfw/storagemanager/StorageManagerIF.h"
|
|
|
|
#include "fsfw/tasks/ExecutableObjectIF.h"
|
2022-01-17 15:58:27 +01:00
|
|
|
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
|
|
|
#include "fsfw_hal/common/gpio/gpioDefinitions.h"
|
|
|
|
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
|
2021-11-01 12:41:20 +01:00
|
|
|
|
2022-10-27 10:49:52 +02:00
|
|
|
struct UioNames {
|
|
|
|
const char* configMemory;
|
|
|
|
const char* ramMemory;
|
|
|
|
const char* registers;
|
|
|
|
const char* irq;
|
|
|
|
};
|
|
|
|
|
2021-11-01 12:41:20 +01:00
|
|
|
/**
|
|
|
|
* @brief This class controls the PDEC IP Core implemented in the programmable logic of the
|
|
|
|
* Zynq-7020. All registers and memories of the PDEC IP Core are accessed via UIO
|
|
|
|
* drivers.
|
|
|
|
*
|
|
|
|
* @details The PDEC IP Core is responsible for processing data received in form of CLTUs from the
|
|
|
|
* S-Band transceiver. This comprises the BCH decoding of the CLTUs and reconstruction of
|
|
|
|
* telecommand transfer frames. Finally the PDEC stores the TC segment transported with
|
|
|
|
* the TC transfer frame in a register. As soon as a new TC has been received a new
|
|
|
|
* frame acceptance report (FAR) will be generated. If the FAR confirms the validity of
|
|
|
|
* a received TC segment, the data can be read out from the associated register.
|
|
|
|
* Currently, the ground software only supports transmissions of CLTUs containing one
|
|
|
|
* space packet.
|
|
|
|
* Link to datasheet of PDEC IP Core: https://eive-cloud.irs.uni-stuttgart.de/index.php/
|
|
|
|
* apps/files/?dir=/EIVE_IRS/Arbeitsdaten/08_Used%20Components/CCSDS_IP_Cores&fileid=1108967
|
|
|
|
*
|
|
|
|
* @author J. Meier
|
|
|
|
*/
|
2023-02-13 11:28:27 +01:00
|
|
|
class PdecHandler : public SystemObject,
|
|
|
|
public ExecutableObjectIF,
|
|
|
|
public HasActionsIF,
|
2023-02-21 15:34:16 +01:00
|
|
|
public ReceivesParameterMessagesIF {
|
2022-01-17 15:58:27 +01:00
|
|
|
public:
|
2022-10-27 10:49:52 +02:00
|
|
|
static constexpr dur_millis_t IRQ_TIMEOUT_MS = 500;
|
|
|
|
|
2022-10-26 14:35:47 +02:00
|
|
|
enum class Modes { POLLED, IRQ };
|
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
/**
|
|
|
|
* @brief Constructor
|
|
|
|
* @param objectId Object ID of PDEC handler system object
|
|
|
|
* @param tcDestinationId Object ID of object responsible for processing TCs.
|
|
|
|
* @param gpioComIF Pointer to GPIO interace responsible for driving GPIOs.
|
|
|
|
* @param pdecReset GPIO ID of GPIO connected to the reset signal of the PDEC.
|
|
|
|
* @param uioConfigMemory String of uio device file same mapped to the PDEC memory space
|
|
|
|
* @param uioregsiters String of uio device file same mapped to the PDEC register space
|
|
|
|
*/
|
|
|
|
PdecHandler(object_id_t objectId, object_id_t tcDestinationId, LinuxLibgpioIF* gpioComIF,
|
2022-10-27 10:49:52 +02:00
|
|
|
gpioId_t pdecReset, UioNames names);
|
2022-01-17 15:58:27 +01:00
|
|
|
|
|
|
|
virtual ~PdecHandler();
|
|
|
|
|
|
|
|
ReturnValue_t performOperation(uint8_t operationCode = 0);
|
|
|
|
|
|
|
|
ReturnValue_t initialize() override;
|
|
|
|
|
|
|
|
MessageQueueId_t getCommandQueue() const;
|
|
|
|
|
|
|
|
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
|
|
|
const uint8_t* data, size_t size) override;
|
|
|
|
|
2023-02-13 11:28:27 +01:00
|
|
|
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
|
|
|
|
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
|
|
|
uint16_t startAtIndex) override;
|
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
private:
|
|
|
|
static const uint8_t INTERFACE_ID = CLASS_ID::PDEC_HANDLER;
|
|
|
|
|
2022-11-02 16:32:00 +01:00
|
|
|
static constexpr Modes OP_MODE = Modes::IRQ;
|
2022-10-26 14:35:47 +02:00
|
|
|
|
2023-02-17 12:19:53 +01:00
|
|
|
static const ReturnValue_t ABANDONED_CLTU_RETVAL = MAKE_RETURN_CODE(0xA0);
|
|
|
|
static const ReturnValue_t FRAME_DIRTY_RETVAL = MAKE_RETURN_CODE(0xA1);
|
2022-01-17 15:58:27 +01:00
|
|
|
static const ReturnValue_t FRAME_ILLEGAL_ONE_REASON = MAKE_RETURN_CODE(0xA2);
|
|
|
|
static const ReturnValue_t FRAME_ILLEGAL_MULTIPLE_REASONS = MAKE_RETURN_CODE(0xA2);
|
2023-02-17 12:19:53 +01:00
|
|
|
static const ReturnValue_t AD_DISCARDED_LOCKOUT_RETVAL = MAKE_RETURN_CODE(0xA3);
|
|
|
|
static const ReturnValue_t AD_DISCARDED_WAIT_RETVAL = MAKE_RETURN_CODE(0xA4);
|
2022-01-17 15:58:27 +01:00
|
|
|
static const ReturnValue_t AD_DISCARDED_NS_VS = MAKE_RETURN_CODE(0xA5);
|
|
|
|
|
|
|
|
//! [EXPORT] : [COMMENT] Received action message with unknown action id
|
|
|
|
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xB0);
|
|
|
|
|
2023-02-17 12:19:53 +01:00
|
|
|
static const ReturnValue_t NO_REPORT_RETVAL = MAKE_RETURN_CODE(0xA6);
|
2022-01-17 15:58:27 +01:00
|
|
|
//! Error in version number and reserved A and B fields
|
2023-02-17 12:19:53 +01:00
|
|
|
static const ReturnValue_t ERROR_VERSION_NUMBER_RETVAL = MAKE_RETURN_CODE(0xA7);
|
2022-01-17 15:58:27 +01:00
|
|
|
//! Illegal combination of bypass and control command flag
|
2023-02-17 12:19:53 +01:00
|
|
|
static const ReturnValue_t ILLEGAL_COMBINATION_RETVAL = MAKE_RETURN_CODE(0xA8);
|
2022-01-17 15:58:27 +01:00
|
|
|
//! Spacecraft identifier did not match
|
2023-02-17 12:19:53 +01:00
|
|
|
static const ReturnValue_t INVALID_SC_ID_RETVAL = MAKE_RETURN_CODE(0xA9);
|
2022-01-17 15:58:27 +01:00
|
|
|
//! VC identifier bits 0 to 4 did not match
|
2023-02-17 12:19:53 +01:00
|
|
|
static const ReturnValue_t INVALID_VC_ID_MSB_RETVAL = MAKE_RETURN_CODE(0xAA);
|
2022-01-17 15:58:27 +01:00
|
|
|
//! VC identifier bit 5 did not match
|
2023-02-17 12:19:53 +01:00
|
|
|
static const ReturnValue_t INVALID_VC_ID_LSB_RETVAL = MAKE_RETURN_CODE(0xAB);
|
2022-01-17 15:58:27 +01:00
|
|
|
//! N(S) of BC or BD frame not set to all zeros
|
2023-02-17 12:19:53 +01:00
|
|
|
static const ReturnValue_t NS_NOT_ZERO_RETVAL = MAKE_RETURN_CODE(0xAC);
|
2022-01-17 15:58:27 +01:00
|
|
|
//! Invalid BC control command
|
|
|
|
static const ReturnValue_t INVALID_BC_CC = MAKE_RETURN_CODE(0xAE);
|
|
|
|
|
2023-01-23 11:52:46 +01:00
|
|
|
static const uint32_t QUEUE_SIZE = config::CCSDS_HANDLER_QUEUE_SIZE;
|
2022-01-17 15:58:27 +01:00
|
|
|
|
2022-03-27 10:56:40 +02:00
|
|
|
#ifdef TE0720_1CFA
|
2022-01-17 15:58:27 +01:00
|
|
|
static const int CONFIG_MEMORY_MAP_SIZE = 0x400;
|
|
|
|
static const int RAM_MAP_SIZE = 0x4000;
|
|
|
|
static const int REGISTER_MAP_SIZE = 0x10000;
|
2021-11-08 12:25:12 +01:00
|
|
|
#else
|
2022-01-17 15:58:27 +01:00
|
|
|
static const int CONFIG_MEMORY_MAP_SIZE = 0x400;
|
|
|
|
static const int RAM_MAP_SIZE = 0x4000;
|
|
|
|
static const int REGISTER_MAP_SIZE = 0x4000;
|
2021-11-08 12:25:12 +01:00
|
|
|
#endif /* BOARD_TE0720 == 1 */
|
2021-11-01 12:41:20 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
static const size_t MAX_TC_SEGMENT_SIZE = 1017;
|
|
|
|
static const uint8_t MAP_ID_MASK = 0x3F;
|
2021-11-01 12:41:20 +01:00
|
|
|
|
2022-03-27 10:56:40 +02:00
|
|
|
#ifdef TE0720_1CFA
|
2022-01-17 15:58:27 +01:00
|
|
|
static const uint32_t PHYSICAL_RAM_BASE_ADDRESS = 0x32000000;
|
2021-11-21 13:58:05 +01:00
|
|
|
#else
|
2022-01-17 15:58:27 +01:00
|
|
|
static const uint32_t PHYSICAL_RAM_BASE_ADDRESS = 0x26000000;
|
2021-11-21 13:58:05 +01:00
|
|
|
#endif
|
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
// Expected value stored in FAR register after reset
|
|
|
|
static const uint32_t FAR_RESET = 0x7FE0;
|
|
|
|
|
|
|
|
static const uint32_t TC_SEGMENT_LEN = 1017;
|
|
|
|
|
|
|
|
static const uint32_t NO_RF_MASK = 0x8000;
|
|
|
|
static const uint32_t NO_BITLOCK_MASK = 0x4000;
|
|
|
|
|
2023-02-23 10:09:04 +01:00
|
|
|
static const uint32_t MAX_INIT_TRIES = 20;
|
|
|
|
|
2023-02-13 11:28:27 +01:00
|
|
|
class ParameterId {
|
2023-02-23 15:27:24 +01:00
|
|
|
public:
|
|
|
|
// ID of the parameter to update the positive window of AD frames
|
|
|
|
static const uint8_t POSITIVE_WINDOW = 0;
|
|
|
|
// ID of the parameter to update the negative window of AD frames
|
|
|
|
static const uint8_t NEGATIVE_WINDOW = 1;
|
2023-02-13 11:28:27 +01:00
|
|
|
};
|
2022-01-17 15:58:27 +01:00
|
|
|
|
2023-02-20 18:17:27 +01:00
|
|
|
static constexpr uint32_t MAX_ALLOWED_IRQS_PER_WINDOW = 800;
|
2023-02-20 18:12:33 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
enum class IReason_t : uint8_t {
|
|
|
|
NO_REPORT,
|
|
|
|
ERROR_VERSION_NUMBER,
|
|
|
|
ILLEGAL_COMBINATION,
|
|
|
|
INVALID_SC_ID,
|
|
|
|
INVALID_VC_ID_LSB,
|
|
|
|
INVALID_VC_ID_MSB,
|
|
|
|
NS_NOT_ZERO,
|
|
|
|
INCORRECT_BC_CC
|
|
|
|
};
|
|
|
|
|
2023-02-23 15:19:48 +01:00
|
|
|
enum class State : uint8_t { INIT, PDEC_RESET, RUNNING, WAIT_FOR_RECOVERY };
|
2022-01-17 15:58:27 +01:00
|
|
|
|
2022-10-27 10:49:52 +02:00
|
|
|
static uint32_t CURRENT_FAR;
|
|
|
|
|
2023-02-20 18:12:33 +01:00
|
|
|
Countdown genericCheckCd = Countdown(IRQ_TIMEOUT_MS);
|
2022-10-27 10:49:52 +02:00
|
|
|
object_id_t tcDestinationId;
|
|
|
|
|
|
|
|
AcceptsTelecommandsIF* tcDestination = nullptr;
|
|
|
|
|
|
|
|
LinuxLibgpioIF* gpioComIF = nullptr;
|
|
|
|
|
2023-02-20 18:12:33 +01:00
|
|
|
uint32_t interruptCounter = 0;
|
|
|
|
Countdown interruptWindowCd = Countdown(1000);
|
|
|
|
|
2022-10-27 10:49:52 +02:00
|
|
|
/**
|
|
|
|
* Reset signal is required to hold PDEC in reset state until the configuration has been
|
|
|
|
* written to the appropriate memory space.
|
|
|
|
* Can also be used to reboot PDEC in case of erros.
|
|
|
|
*/
|
|
|
|
gpioId_t pdecReset = gpio::NO_GPIO;
|
|
|
|
|
|
|
|
uint32_t tcAbortCounter = 0;
|
|
|
|
|
|
|
|
ActionHelper actionHelper;
|
|
|
|
|
|
|
|
StorageManagerIF* tcStore = nullptr;
|
|
|
|
|
|
|
|
MessageQueueIF* commandQueue = nullptr;
|
|
|
|
|
|
|
|
State state = State::INIT;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Pointer pointing to base address of the PDEC memory space.
|
|
|
|
* This address is equivalent with the base address of the section named configuration area in
|
|
|
|
* the PDEC datasheet.
|
|
|
|
*/
|
|
|
|
uint32_t* memoryBaseAddress = nullptr;
|
|
|
|
|
|
|
|
uint32_t* ramBaseAddress = nullptr;
|
|
|
|
|
|
|
|
// Pointer pointing to base address of register space
|
|
|
|
uint32_t* registerBaseAddress = nullptr;
|
|
|
|
|
|
|
|
uint8_t tcSegment[TC_SEGMENT_LEN];
|
|
|
|
|
|
|
|
// Used to check carrier and bit lock changes (default set to no rf and no bitlock)
|
|
|
|
uint32_t lastClcw = 0xC000;
|
|
|
|
|
|
|
|
bool carrierLock = false;
|
|
|
|
bool bitLock = false;
|
|
|
|
|
2023-04-14 13:11:11 +02:00
|
|
|
MessageQueueId_t commandedBy = MessageQueueIF::NO_QUEUE;
|
|
|
|
bool ptmeResetWithReinitializationPending = false;
|
|
|
|
|
2022-10-27 10:49:52 +02:00
|
|
|
UioNames uioNames;
|
|
|
|
|
2023-02-13 11:28:27 +01:00
|
|
|
ParameterHelper paramHelper;
|
|
|
|
|
|
|
|
PdecConfig pdecConfig;
|
|
|
|
|
2023-02-23 10:09:04 +01:00
|
|
|
uint32_t initTries = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Performs initialization stuff which must be performed in first
|
|
|
|
* loop of running task
|
|
|
|
*
|
|
|
|
* @return OK if successful, otherwise FAILED
|
|
|
|
*/
|
|
|
|
ReturnValue_t firstLoop();
|
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
/**
|
|
|
|
* @brief Reads and handles messages stored in the commandQueue
|
|
|
|
*/
|
|
|
|
void readCommandQueue(void);
|
|
|
|
|
2022-10-26 14:35:47 +02:00
|
|
|
ReturnValue_t polledOperation();
|
|
|
|
ReturnValue_t irqOperation();
|
2023-02-27 11:35:43 +01:00
|
|
|
ReturnValue_t handleInitState();
|
|
|
|
void openIrqFile(int* fd);
|
2023-02-20 18:53:56 +01:00
|
|
|
ReturnValue_t checkAndHandleIrqs(int fd, uint32_t& info);
|
2022-10-26 14:35:47 +02:00
|
|
|
|
2022-10-27 10:49:52 +02:00
|
|
|
uint32_t readFar();
|
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
/**
|
|
|
|
* @brief This functions writes the configuration parameters to the configuration
|
|
|
|
* section of the PDEC.
|
|
|
|
*/
|
2022-11-02 18:58:29 +01:00
|
|
|
void writePdecConfigDuringReset(PdecConfig& config);
|
2022-01-17 15:58:27 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Reading the FAR resets the set stat flag which signals a new TC. Without clearing
|
|
|
|
* this flag no new TC will be excepted. After start up the flag is set and needs
|
|
|
|
* to be reset.
|
|
|
|
* Stat flag 0 - new TC received
|
|
|
|
* Stat flag 1 - old TC (ready to receive next TC)
|
|
|
|
*/
|
|
|
|
ReturnValue_t resetFarStatFlag();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Releases the PDEC from reset state. PDEC will start with loading the written
|
|
|
|
* configuration parameters.
|
|
|
|
*/
|
|
|
|
ReturnValue_t releasePdec();
|
|
|
|
|
2023-02-23 15:19:48 +01:00
|
|
|
/**
|
|
|
|
* @brief Will set PDEC in reset state. Use releasePdec() to release PDEC
|
|
|
|
* from reset state
|
|
|
|
*
|
|
|
|
* @return OK if successful, otherwise error return value
|
|
|
|
*/
|
|
|
|
ReturnValue_t pdecToReset();
|
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
/**
|
|
|
|
* @brief Reads the FAR register and checks if a new TC has been received.
|
|
|
|
*/
|
|
|
|
bool newTcReceived();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Checks if carrier lock or bit lock has been detected and triggers appropriate
|
|
|
|
* event.
|
|
|
|
*/
|
2023-04-14 13:11:11 +02:00
|
|
|
void doPeriodicWork();
|
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
void checkLocks();
|
|
|
|
|
2023-02-20 18:41:26 +01:00
|
|
|
void resetIrqLimiters();
|
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
/**
|
|
|
|
* @brief Analyzes the FramAna field (frame analysis data) of a FAR report.
|
|
|
|
*
|
|
|
|
* @return True if frame valid, otherwise false.
|
|
|
|
*/
|
|
|
|
bool checkFrameAna(uint32_t pdecFar);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This function handles the IReason field of the frame analysis report.
|
|
|
|
*
|
|
|
|
* @details In case frame as been declared illegal for multiple reasons, the reason with the
|
|
|
|
* lowest value will be shown.
|
|
|
|
*/
|
|
|
|
void handleIReason(uint32_t pdecFar, ReturnValue_t parameter1);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Handles the reception of new TCs. Reads the pointer to the storage location of the
|
|
|
|
* new TC segment, extracts the PUS packet and forwards the data to the object
|
|
|
|
* responsible for processing the TC.
|
|
|
|
*/
|
|
|
|
void handleNewTc();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Function reads the last received TC segment from the PDEC memory and copies
|
|
|
|
* the data to the tcSegement array.
|
|
|
|
*
|
|
|
|
* @param tcLength The length of the received TC.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
ReturnValue_t readTc(uint32_t& tcLength);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Prints the tc segment data
|
|
|
|
*/
|
|
|
|
void printTC(uint32_t tcLength);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This function calculates the entry for the configuration of the MAP ID routing.
|
|
|
|
*
|
|
|
|
* @param mapAddr The MAP ID to configure
|
|
|
|
* @param moduleId The destination module where all TCs with the map id mapAddr will be routed
|
|
|
|
* to.
|
|
|
|
*
|
|
|
|
* @details The PDEC has different modules where the TCs can be routed to. A lookup table is
|
|
|
|
* used which links the MAP ID field to the destination module. The entry for this
|
|
|
|
* lookup table is created by this function and must be stored in the configuration
|
|
|
|
* memory region of the PDEC. The entry has a specific format
|
|
|
|
*/
|
|
|
|
uint8_t calcMapAddrEntry(uint8_t moduleId);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* brief Returns the 32-bit wide communication link control word (CLCW)
|
|
|
|
*/
|
|
|
|
uint32_t getClcw();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Returns the PDEC monitor register content
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
uint32_t getPdecMon();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Reads and prints the CLCW. Can be useful for debugging.
|
|
|
|
*/
|
|
|
|
void printClcw();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Prints monitor register information to debug console.
|
|
|
|
*/
|
|
|
|
void printPdecMon();
|
|
|
|
|
2023-04-14 13:26:44 +02:00
|
|
|
void pdecResetNoInit();
|
|
|
|
|
2023-04-14 13:11:11 +02:00
|
|
|
void initFailedHandler(ReturnValue_t reason);
|
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
std::string getMonStatusString(uint32_t status);
|
2021-11-01 12:41:20 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* LINUX_OBC_PDECHANDLER_H_ */
|