applied formatting
This commit is contained in:
@ -1,104 +1,98 @@
|
||||
#include <linux/obc/PapbVcInterface.h>
|
||||
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
PapbVcInterface::PapbVcInterface(object_id_t objectId, LinuxLibgpioIF* gpioComIF,
|
||||
gpioId_t papbBusyId, gpioId_t papbEmptyId, uint32_t vcOffset) :
|
||||
SystemObject(objectId), gpioComIF(gpioComIF), papbBusyId(
|
||||
papbBusyId), papbEmptyId(papbEmptyId), vcOffset(vcOffset) {
|
||||
}
|
||||
|
||||
PapbVcInterface::~PapbVcInterface() {
|
||||
}
|
||||
gpioId_t papbBusyId, gpioId_t papbEmptyId, uint32_t vcOffset)
|
||||
: SystemObject(objectId),
|
||||
gpioComIF(gpioComIF),
|
||||
papbBusyId(papbBusyId),
|
||||
papbEmptyId(papbEmptyId),
|
||||
vcOffset(vcOffset) {}
|
||||
|
||||
PapbVcInterface::~PapbVcInterface() {}
|
||||
|
||||
void PapbVcInterface::setRegisterAddress(uint32_t* ptmeBaseAddress) {
|
||||
vcBaseReg = ptmeBaseAddress + vcOffset;
|
||||
vcBaseReg = ptmeBaseAddress + vcOffset;
|
||||
}
|
||||
|
||||
ReturnValue_t PapbVcInterface::write(const uint8_t * data, size_t size) {
|
||||
ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
|
||||
if (pollPapbBusySignal() == RETURN_OK) {
|
||||
startPacketTransfer();
|
||||
}
|
||||
|
||||
if(pollPapbBusySignal() == RETURN_OK) {
|
||||
startPacketTransfer();
|
||||
for (size_t idx = 0; idx < size; idx++) {
|
||||
if (pollPapbBusySignal() == RETURN_OK) {
|
||||
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(*(data + idx));
|
||||
} else {
|
||||
sif::warning << "PapbVcInterface::write: Only written " << idx << " of " << size << " data"
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t idx = 0; idx < size; idx++) {
|
||||
if(pollPapbBusySignal() == RETURN_OK) {
|
||||
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(*(data + idx));
|
||||
}
|
||||
else {
|
||||
sif::warning << "PapbVcInterface::write: Only written " << idx << " of "
|
||||
<< size << " data" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if(pollPapbBusySignal() == RETURN_OK) {
|
||||
endPacketTransfer();
|
||||
}
|
||||
return RETURN_OK;
|
||||
if (pollPapbBusySignal() == RETURN_OK) {
|
||||
endPacketTransfer();
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void PapbVcInterface::startPacketTransfer() {
|
||||
*vcBaseReg = CONFIG_START;
|
||||
}
|
||||
void PapbVcInterface::startPacketTransfer() { *vcBaseReg = CONFIG_START; }
|
||||
|
||||
void PapbVcInterface::endPacketTransfer() {
|
||||
*vcBaseReg = CONFIG_END;
|
||||
}
|
||||
void PapbVcInterface::endPacketTransfer() { *vcBaseReg = CONFIG_END; }
|
||||
|
||||
ReturnValue_t PapbVcInterface::pollPapbBusySignal() {
|
||||
int papbBusyState = 0;
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
int papbBusyState = 0;
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
|
||||
/** Check if PAPB interface is ready to receive data */
|
||||
result = gpioComIF->readGpio(papbBusyId, &papbBusyState);
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PapbVcInterface::pollPapbBusySignal: Failed to read papb busy signal"
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
if (!papbBusyState) {
|
||||
sif::warning << "PapbVcInterface::pollPapbBusySignal: PAPB busy" << std::endl;
|
||||
return PAPB_BUSY;
|
||||
}
|
||||
/** Check if PAPB interface is ready to receive data */
|
||||
result = gpioComIF->readGpio(papbBusyId, &papbBusyState);
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PapbVcInterface::pollPapbBusySignal: Failed to read papb busy signal"
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
if (!papbBusyState) {
|
||||
sif::warning << "PapbVcInterface::pollPapbBusySignal: PAPB busy" << std::endl;
|
||||
return PAPB_BUSY;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void PapbVcInterface::isVcInterfaceBufferEmpty() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
int papbEmptyState = 1;
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
int papbEmptyState = 1;
|
||||
|
||||
result = gpioComIF->readGpio(papbEmptyId, &papbEmptyState);
|
||||
result = gpioComIF->readGpio(papbEmptyId, &papbEmptyState);
|
||||
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal"
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (papbEmptyState == 1) {
|
||||
sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is empty" << std::endl;
|
||||
}
|
||||
else {
|
||||
sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is not empty" << std::endl;
|
||||
}
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal"
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (papbEmptyState == 1) {
|
||||
sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is empty" << std::endl;
|
||||
} else {
|
||||
sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is not empty" << std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ReturnValue_t PapbVcInterface::sendTestFrame() {
|
||||
/** Size of one complete transfer frame data field amounts to 1105 bytes */
|
||||
uint8_t testPacket[1105];
|
||||
/** Size of one complete transfer frame data field amounts to 1105 bytes */
|
||||
uint8_t testPacket[1105];
|
||||
|
||||
/** Fill one test packet */
|
||||
for(int idx = 0; idx < 1105; idx++) {
|
||||
testPacket[idx] = static_cast<uint8_t>(idx & 0xFF);
|
||||
}
|
||||
/** Fill one test packet */
|
||||
for (int idx = 0; idx < 1105; idx++) {
|
||||
testPacket[idx] = static_cast<uint8_t>(idx & 0xFF);
|
||||
}
|
||||
|
||||
ReturnValue_t result = write(testPacket, 1105);
|
||||
if(result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
ReturnValue_t result = write(testPacket, 1105);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
#ifndef LINUX_OBC_PAPBVCINTERFACE_H_
|
||||
#define LINUX_OBC_PAPBVCINTERFACE_H_
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "linux/obc/VcInterfaceIF.h"
|
||||
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
|
||||
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "linux/obc/VcInterfaceIF.h"
|
||||
|
||||
/**
|
||||
* @brief This class handles the transmission of data to a virtual channel of the PTME IP Core
|
||||
@ -14,99 +15,96 @@
|
||||
*
|
||||
* @author J. Meier
|
||||
*/
|
||||
class PapbVcInterface: public SystemObject,
|
||||
public VcInterfaceIF,
|
||||
public HasReturnvaluesIF {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param objectId
|
||||
* @param papbBusyId The ID of the GPIO which is connected to the PAPBBusy_N signal of the
|
||||
* VcInterface IP Core. A low logic level indicates the VcInterface is not
|
||||
* ready to receive more data.
|
||||
* @param papbEmptyId The ID of the GPIO which is connected to the PAPBEmpty signal of the
|
||||
* VcInterface IP Core. The signal is high when there are no packets in the
|
||||
* external buffer memory (BRAM).
|
||||
*/
|
||||
PapbVcInterface(object_id_t objectId, LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId,
|
||||
gpioId_t papbEmptyId, uint32_t vcOffset);
|
||||
virtual ~PapbVcInterface();
|
||||
class PapbVcInterface : public SystemObject, public VcInterfaceIF, public HasReturnvaluesIF {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param objectId
|
||||
* @param papbBusyId The ID of the GPIO which is connected to the PAPBBusy_N signal of the
|
||||
* VcInterface IP Core. A low logic level indicates the VcInterface is not
|
||||
* ready to receive more data.
|
||||
* @param papbEmptyId The ID of the GPIO which is connected to the PAPBEmpty signal of the
|
||||
* VcInterface IP Core. The signal is high when there are no packets in the
|
||||
* external buffer memory (BRAM).
|
||||
*/
|
||||
PapbVcInterface(object_id_t objectId, LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId,
|
||||
gpioId_t papbEmptyId, uint32_t vcOffset);
|
||||
virtual ~PapbVcInterface();
|
||||
|
||||
ReturnValue_t write(const uint8_t* data, size_t size) override;
|
||||
ReturnValue_t write(const uint8_t* data, size_t size) override;
|
||||
|
||||
void setRegisterAddress(uint32_t* ptmeBaseAddress) override;
|
||||
void setRegisterAddress(uint32_t* ptmeBaseAddress) override;
|
||||
|
||||
private:
|
||||
private:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::CCSDS_IP_CORE_BRIDGE;
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::CCSDS_IP_CORE_BRIDGE;
|
||||
static const ReturnValue_t PAPB_BUSY = MAKE_RETURN_CODE(0xA0);
|
||||
|
||||
static const ReturnValue_t PAPB_BUSY = MAKE_RETURN_CODE(0xA0);
|
||||
/**
|
||||
* Configuration bits:
|
||||
* bit[1:0]: Size of data (1,2,3 or 4 bytes). 1 Byte <=> b00
|
||||
* bit[2]: Set this bit to 1 to abort a transfered packet
|
||||
* bit[3]: Signals to VcInterface the start of a new telemetry packet
|
||||
*/
|
||||
static const uint32_t CONFIG_START = 0x8;
|
||||
|
||||
/**
|
||||
* Configuration bits:
|
||||
* bit[1:0]: Size of data (1,2,3 or 4 bytes). 1 Byte <=> b00
|
||||
* bit[2]: Set this bit to 1 to abort a transfered packet
|
||||
* bit[3]: Signals to VcInterface the start of a new telemetry packet
|
||||
*/
|
||||
static const uint32_t CONFIG_START = 0x8;
|
||||
/**
|
||||
* Writing this word to the VcInterface base address signals to the virtual channel interface
|
||||
* that a complete tm packet has been transferred.
|
||||
*/
|
||||
static const uint32_t CONFIG_END = 0x0;
|
||||
|
||||
/**
|
||||
* Writing this word to the VcInterface base address signals to the virtual channel interface
|
||||
* that a complete tm packet has been transferred.
|
||||
*/
|
||||
static const uint32_t CONFIG_END = 0x0;
|
||||
/**
|
||||
* Writing to this offset within the memory space of a virtual channel will insert data for
|
||||
* encoding to the external buffer memory of the PTME IP Core.
|
||||
* The address offset is 0x400 (= 4 * 256)
|
||||
*/
|
||||
static const int DATA_REG_OFFSET = 256;
|
||||
|
||||
/**
|
||||
* Writing to this offset within the memory space of a virtual channel will insert data for
|
||||
* encoding to the external buffer memory of the PTME IP Core.
|
||||
* The address offset is 0x400 (= 4 * 256)
|
||||
*/
|
||||
static const int DATA_REG_OFFSET = 256;
|
||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||
|
||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||
/** Pulled to low when virtual channel not ready to receive data */
|
||||
gpioId_t papbBusyId = gpio::NO_GPIO;
|
||||
/** High when external buffer memory of virtual channel is empty */
|
||||
gpioId_t papbEmptyId = gpio::NO_GPIO;
|
||||
|
||||
/** Pulled to low when virtual channel not ready to receive data */
|
||||
gpioId_t papbBusyId = gpio::NO_GPIO;
|
||||
/** High when external buffer memory of virtual channel is empty */
|
||||
gpioId_t papbEmptyId = gpio::NO_GPIO;
|
||||
uint32_t* vcBaseReg = nullptr;
|
||||
|
||||
uint32_t* vcBaseReg = nullptr;
|
||||
uint32_t vcOffset = 0;
|
||||
|
||||
uint32_t vcOffset = 0;
|
||||
/**
|
||||
* @brief This function sends the config byte to the virtual channel of the PTME IP Core
|
||||
* to initiate a packet transfer.
|
||||
*/
|
||||
void startPacketTransfer();
|
||||
|
||||
/**
|
||||
* @brief This function sends the config byte to the virtual channel of the PTME IP Core
|
||||
* to initiate a packet transfer.
|
||||
*/
|
||||
void startPacketTransfer();
|
||||
/**
|
||||
* @brief This function sends the config byte to the virtual channel interface of the PTME
|
||||
* IP Core to signal the end of a packet transfer.
|
||||
*/
|
||||
void endPacketTransfer();
|
||||
|
||||
/**
|
||||
* @brief This function sends the config byte to the virtual channel interface of the PTME
|
||||
* IP Core to signal the end of a packet transfer.
|
||||
*/
|
||||
void endPacketTransfer();
|
||||
/**
|
||||
* @brief This function reads the papb busy signal indicating whether the virtual channel
|
||||
* interface is ready to receive more data or not. PAPB is ready when
|
||||
* PAPB_Busy_N == '1'.
|
||||
*
|
||||
* @return RETURN_OK when ready to receive data else PAPB_BUSY.
|
||||
*/
|
||||
ReturnValue_t pollPapbBusySignal();
|
||||
|
||||
/**
|
||||
* @brief This function reads the papb busy signal indicating whether the virtual channel
|
||||
* interface is ready to receive more data or not. PAPB is ready when
|
||||
* PAPB_Busy_N == '1'.
|
||||
*
|
||||
* @return RETURN_OK when ready to receive data else PAPB_BUSY.
|
||||
*/
|
||||
ReturnValue_t pollPapbBusySignal();
|
||||
/**
|
||||
* @brief This function can be used for debugging to check whether there are packets in
|
||||
* the packet buffer of the virtual channel or not.
|
||||
*/
|
||||
void isVcInterfaceBufferEmpty();
|
||||
|
||||
/**
|
||||
* @brief This function can be used for debugging to check whether there are packets in
|
||||
* the packet buffer of the virtual channel or not.
|
||||
*/
|
||||
void isVcInterfaceBufferEmpty();
|
||||
|
||||
/**
|
||||
* @brief This function sends a complete telemetry transfer frame data field (1105 bytes)
|
||||
* to the papb interface of the PTME IP Core. Can be used to test the implementation.
|
||||
*/
|
||||
ReturnValue_t sendTestFrame();
|
||||
/**
|
||||
* @brief This function sends a complete telemetry transfer frame data field (1105 bytes)
|
||||
* to the papb interface of the PTME IP Core. Can be used to test the implementation.
|
||||
*/
|
||||
ReturnValue_t sendTestFrame();
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_PAPBVCINTERFACE_H_ */
|
||||
|
@ -1,36 +1,33 @@
|
||||
#include "PdecConfig.h"
|
||||
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
PdecConfig::PdecConfig() {
|
||||
initialize();
|
||||
}
|
||||
PdecConfig::PdecConfig() { initialize(); }
|
||||
|
||||
PdecConfig::~PdecConfig() {
|
||||
|
||||
}
|
||||
PdecConfig::~PdecConfig() {}
|
||||
|
||||
void PdecConfig::initialize() {
|
||||
uint32_t word = 0;
|
||||
word |= (VERSION_ID << 30);
|
||||
word |= (BYPASS_FLAG << 29);
|
||||
word |= (CONTROL_COMMAND_FLAG << 28);
|
||||
word |= (RESERVED_FIELD_A << 26);
|
||||
word |= (SPACECRAFT_ID << 16);
|
||||
word |= (VIRTUAL_CHANNEL << 10);
|
||||
word |= (DUMMY_BITS << 8);
|
||||
word |= POSITIVE_WINDOW;
|
||||
configWords[0] = word;
|
||||
word = 0;
|
||||
word |= (NEGATIVE_WINDOW << 24);
|
||||
word |= (HIGH_AU_MAP_ID << 16);
|
||||
word |= (ENABLE_DERANDOMIZER << 8);
|
||||
configWords[1] = word;
|
||||
uint32_t word = 0;
|
||||
word |= (VERSION_ID << 30);
|
||||
word |= (BYPASS_FLAG << 29);
|
||||
word |= (CONTROL_COMMAND_FLAG << 28);
|
||||
word |= (RESERVED_FIELD_A << 26);
|
||||
word |= (SPACECRAFT_ID << 16);
|
||||
word |= (VIRTUAL_CHANNEL << 10);
|
||||
word |= (DUMMY_BITS << 8);
|
||||
word |= POSITIVE_WINDOW;
|
||||
configWords[0] = word;
|
||||
word = 0;
|
||||
word |= (NEGATIVE_WINDOW << 24);
|
||||
word |= (HIGH_AU_MAP_ID << 16);
|
||||
word |= (ENABLE_DERANDOMIZER << 8);
|
||||
configWords[1] = word;
|
||||
}
|
||||
|
||||
uint32_t PdecConfig::getConfigWord(uint8_t wordNo) {
|
||||
if (wordNo >= CONFIG_WORDS_NUM) {
|
||||
sif::error << "PdecConfig::getConfigWord: Invalid word number" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
return configWords[wordNo];
|
||||
if (wordNo >= CONFIG_WORDS_NUM) {
|
||||
sif::error << "PdecConfig::getConfigWord: Invalid word number" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
return configWords[wordNo];
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
#ifndef LINUX_OBC_PDECCONFIG_H_
|
||||
#define LINUX_OBC_PDECCONFIG_H_
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include <cstring>
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
/**
|
||||
* @brief This class generates the configuration words for the configuration memory of the PDEC
|
||||
* IP Cores.
|
||||
@ -14,39 +15,38 @@
|
||||
* @author J. Meier
|
||||
*/
|
||||
class PdecConfig {
|
||||
public:
|
||||
PdecConfig();
|
||||
virtual ~PdecConfig();
|
||||
|
||||
public:
|
||||
PdecConfig();
|
||||
virtual ~PdecConfig();
|
||||
/**
|
||||
* @brief Returns the configuration word by specifying the position.
|
||||
*/
|
||||
uint32_t getConfigWord(uint8_t wordNo);
|
||||
|
||||
/**
|
||||
* @brief Returns the configuration word by specifying the position.
|
||||
*/
|
||||
uint32_t getConfigWord(uint8_t wordNo);
|
||||
private:
|
||||
// TC transfer frame configuration parameters
|
||||
static const uint8_t VERSION_ID = 0;
|
||||
// BD Frames
|
||||
static const uint8_t BYPASS_FLAG = 1;
|
||||
static const uint8_t CONTROL_COMMAND_FLAG = 0;
|
||||
|
||||
private:
|
||||
// TC transfer frame configuration parameters
|
||||
static const uint8_t VERSION_ID = 0;
|
||||
// BD Frames
|
||||
static const uint8_t BYPASS_FLAG = 1;
|
||||
static const uint8_t CONTROL_COMMAND_FLAG = 0;
|
||||
static const uint8_t VIRTUAL_CHANNEL = 0;
|
||||
static const uint8_t RESERVED_FIELD_A = 0;
|
||||
static const uint16_t SPACECRAFT_ID = 0x274;
|
||||
static const uint16_t DUMMY_BITS = 0;
|
||||
// Parameters to control the FARM for AD frames
|
||||
// Set here for future use
|
||||
static const uint8_t POSITIVE_WINDOW = 10;
|
||||
static const uint8_t NEGATIVE_WINDOW = 151;
|
||||
static const uint8_t HIGH_AU_MAP_ID = 0xF;
|
||||
static const uint8_t ENABLE_DERANDOMIZER = 1;
|
||||
|
||||
static const uint8_t VIRTUAL_CHANNEL = 0;
|
||||
static const uint8_t RESERVED_FIELD_A = 0;
|
||||
static const uint16_t SPACECRAFT_ID = 0x274;
|
||||
static const uint16_t DUMMY_BITS = 0;
|
||||
// Parameters to control the FARM for AD frames
|
||||
// Set here for future use
|
||||
static const uint8_t POSITIVE_WINDOW = 10;
|
||||
static const uint8_t NEGATIVE_WINDOW = 151;
|
||||
static const uint8_t HIGH_AU_MAP_ID = 0xF;
|
||||
static const uint8_t ENABLE_DERANDOMIZER = 1;
|
||||
static const uint8_t CONFIG_WORDS_NUM = 2;
|
||||
|
||||
static const uint8_t CONFIG_WORDS_NUM = 2;
|
||||
uint32_t configWords[CONFIG_WORDS_NUM];
|
||||
|
||||
uint32_t configWords[CONFIG_WORDS_NUM];
|
||||
|
||||
void initialize();
|
||||
void initialize();
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_PDECCONFIG_H_ */
|
||||
|
@ -1,578 +1,568 @@
|
||||
#include "PdecHandler.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "PdecHandler.h"
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
|
||||
|
||||
PdecHandler::PdecHandler(object_id_t objectId, object_id_t tcDestinationId,
|
||||
LinuxLibgpioIF* gpioComIF, gpioId_t pdecReset, std::string uioConfigMemory,
|
||||
std::string uioRamMemory, std::string uioRegisters) :
|
||||
SystemObject(objectId), tcDestinationId(tcDestinationId), gpioComIF(gpioComIF), pdecReset(
|
||||
pdecReset), uioConfigMemory(uioConfigMemory), uioRamMemory(uioRamMemory), uioRegisters(
|
||||
uioRegisters), actionHelper(this, nullptr) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(QUEUE_SIZE);
|
||||
LinuxLibgpioIF* gpioComIF, gpioId_t pdecReset, std::string uioConfigMemory,
|
||||
std::string uioRamMemory, std::string uioRegisters)
|
||||
: SystemObject(objectId),
|
||||
tcDestinationId(tcDestinationId),
|
||||
gpioComIF(gpioComIF),
|
||||
pdecReset(pdecReset),
|
||||
uioConfigMemory(uioConfigMemory),
|
||||
uioRamMemory(uioRamMemory),
|
||||
uioRegisters(uioRegisters),
|
||||
actionHelper(this, nullptr) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(QUEUE_SIZE);
|
||||
}
|
||||
|
||||
PdecHandler::~PdecHandler() {
|
||||
}
|
||||
PdecHandler::~PdecHandler() {}
|
||||
|
||||
ReturnValue_t PdecHandler::initialize() {
|
||||
tcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
|
||||
if (tcStore == nullptr) {
|
||||
sif::error << "PdecHandler::initialize: Invalid TC store" << std::endl;
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
tcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
|
||||
if (tcStore == nullptr) {
|
||||
sif::error << "PdecHandler::initialize: Invalid TC store" << std::endl;
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
tcDestination = ObjectManager::instance()->get<AcceptsTelecommandsIF>(tcDestinationId);
|
||||
|
||||
tcDestination = ObjectManager::instance()->get<AcceptsTelecommandsIF>(
|
||||
tcDestinationId);
|
||||
if (tcDestination == nullptr) {
|
||||
sif::error << "PdecHandler::initialize: Invalid tc destination specified" << std::endl;
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
if (tcDestination == nullptr) {
|
||||
sif::error << "PdecHandler::initialize: Invalid tc destination specified" << std::endl;
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
result = getRegisterAddress();
|
||||
if (result != RETURN_OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
result = getRegisterAddress();
|
||||
if (result != RETURN_OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
result = getConfigMemoryBaseAddress();
|
||||
if (result != RETURN_OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
result = getConfigMemoryBaseAddress();
|
||||
if (result != RETURN_OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
result = getRamBaseAddress();
|
||||
if (result != RETURN_OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
result = getRamBaseAddress();
|
||||
if (result != RETURN_OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
writePdecConfig();
|
||||
|
||||
writePdecConfig();
|
||||
result = releasePdec();
|
||||
if (result != RETURN_OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
result = releasePdec();
|
||||
if (result != RETURN_OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
result = actionHelper.initialize(commandQueue);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = actionHelper.initialize(commandQueue);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
MessageQueueId_t PdecHandler::getCommandQueue() const {
|
||||
return commandQueue->getId();
|
||||
}
|
||||
MessageQueueId_t PdecHandler::getCommandQueue() const { return commandQueue->getId(); }
|
||||
|
||||
ReturnValue_t PdecHandler::getRegisterAddress() {
|
||||
int fd = open(uioRegisters.c_str(), O_RDWR);
|
||||
if (fd < 1) {
|
||||
sif::warning << "PdecHandler::getRegisterAddress: Invalid UIO device file" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
int fd = open(uioRegisters.c_str(), O_RDWR);
|
||||
if (fd < 1) {
|
||||
sif::warning << "PdecHandler::getRegisterAddress: Invalid UIO device file" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
registerBaseAddress = static_cast<uint32_t*>(mmap(NULL, REGISTER_MAP_SIZE,
|
||||
PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0));
|
||||
registerBaseAddress = static_cast<uint32_t*>(
|
||||
mmap(NULL, REGISTER_MAP_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0));
|
||||
|
||||
if (registerBaseAddress == MAP_FAILED) {
|
||||
sif::error << "PdecHandler::getRegisterAddress: Failed to map uio address" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
if (registerBaseAddress == MAP_FAILED) {
|
||||
sif::error << "PdecHandler::getRegisterAddress: Failed to map uio address" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::getConfigMemoryBaseAddress() {
|
||||
int fd = open(uioConfigMemory.c_str(), O_RDWR);
|
||||
if (fd < 1) {
|
||||
sif::warning << "PdecHandler::getConfigMemoryBaseAddress: Invalid UIO device file" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
int fd = open(uioConfigMemory.c_str(), O_RDWR);
|
||||
if (fd < 1) {
|
||||
sif::warning << "PdecHandler::getConfigMemoryBaseAddress: Invalid UIO device file" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
memoryBaseAddress = static_cast<uint32_t*>(mmap(NULL, CONFIG_MEMORY_MAP_SIZE, PROT_WRITE | PROT_READ,
|
||||
MAP_SHARED, fd, 0));
|
||||
memoryBaseAddress = static_cast<uint32_t*>(
|
||||
mmap(NULL, CONFIG_MEMORY_MAP_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0));
|
||||
|
||||
if (memoryBaseAddress == MAP_FAILED) {
|
||||
sif::error << "PdecHandler::getConfigMemoryBaseAddress: Failed to map uio address" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
if (memoryBaseAddress == MAP_FAILED) {
|
||||
sif::error << "PdecHandler::getConfigMemoryBaseAddress: Failed to map uio address" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::getRamBaseAddress() {
|
||||
int fd = open(uioRamMemory.c_str(), O_RDWR);
|
||||
int fd = open(uioRamMemory.c_str(), O_RDWR);
|
||||
|
||||
ramBaseAddress = static_cast<uint32_t*>(mmap(NULL, RAM_MAP_SIZE, PROT_WRITE | PROT_READ,
|
||||
MAP_SHARED, fd, 0));
|
||||
ramBaseAddress =
|
||||
static_cast<uint32_t*>(mmap(NULL, RAM_MAP_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0));
|
||||
|
||||
if (ramBaseAddress == MAP_FAILED) {
|
||||
sif::error << "PdecHandler::getRamBaseAddress: Failed to map RAM base address" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
if (ramBaseAddress == MAP_FAILED) {
|
||||
sif::error << "PdecHandler::getRamBaseAddress: Failed to map RAM base address" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void PdecHandler::writePdecConfig() {
|
||||
void PdecHandler::writePdecConfig() {
|
||||
PdecConfig pdecConfig;
|
||||
|
||||
PdecConfig pdecConfig;
|
||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET) = pdecConfig.getConfigWord(0);
|
||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET + 1) = pdecConfig.getConfigWord(1);
|
||||
|
||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET)= pdecConfig.getConfigWord(0);
|
||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET + 1) = pdecConfig.getConfigWord(1);
|
||||
// Configure all MAP IDs as invalid
|
||||
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
|
||||
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + idx + 1 / 4) =
|
||||
NO_DESTINATION << 24 | NO_DESTINATION << 16 | NO_DESTINATION << 8 | NO_DESTINATION;
|
||||
}
|
||||
|
||||
// Configure all MAP IDs as invalid
|
||||
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
|
||||
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + idx + 1 / 4) = NO_DESTINATION << 24
|
||||
| NO_DESTINATION << 16 | NO_DESTINATION << 8 | NO_DESTINATION;
|
||||
// All TCs with MAP ID 7 will be routed to the PM module (can then be read from memory)
|
||||
uint8_t routeToPm = calcMapAddrEntry(PM_BUFFER);
|
||||
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + 1) =
|
||||
(NO_DESTINATION << 24) | (NO_DESTINATION << 16) | (NO_DESTINATION << 8) | routeToPm;
|
||||
|
||||
}
|
||||
|
||||
// All TCs with MAP ID 7 will be routed to the PM module (can then be read from memory)
|
||||
uint8_t routeToPm = calcMapAddrEntry(PM_BUFFER);
|
||||
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + 1) = (NO_DESTINATION << 24) | (NO_DESTINATION << 16) | (NO_DESTINATION << 8)
|
||||
| routeToPm;
|
||||
|
||||
// Write map id clock frequencies
|
||||
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
|
||||
*(memoryBaseAddress + MAP_CLK_FREQ_OFFSET + idx / 4) = MAP_CLK_FREQ << 24
|
||||
| MAP_CLK_FREQ << 16 | MAP_CLK_FREQ << 8 | MAP_CLK_FREQ;
|
||||
|
||||
}
|
||||
// Write map id clock frequencies
|
||||
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
|
||||
*(memoryBaseAddress + MAP_CLK_FREQ_OFFSET + idx / 4) =
|
||||
MAP_CLK_FREQ << 24 | MAP_CLK_FREQ << 16 | MAP_CLK_FREQ << 8 | MAP_CLK_FREQ;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::resetFarStatFlag() {
|
||||
uint32_t pdecFar = *(registerBaseAddress + PDEC_FAR_OFFSET);
|
||||
if (pdecFar != FAR_RESET) {
|
||||
sif::warning << "PdecHandler::resetFarStatFlag: FAR register did not match expected value."
|
||||
<< " Read value: 0x" << std::hex << static_cast<unsigned int>(pdecFar) << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
uint32_t pdecFar = *(registerBaseAddress + PDEC_FAR_OFFSET);
|
||||
if (pdecFar != FAR_RESET) {
|
||||
sif::warning << "PdecHandler::resetFarStatFlag: FAR register did not match expected value."
|
||||
<< " Read value: 0x" << std::hex << static_cast<unsigned int>(pdecFar)
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
#if OBSW_DEBUG_PDEC_HANDLER == 1
|
||||
sif::debug << "PdecHandler::resetFarStatFlag: read FAR with value: 0x" << std::hex << pdecFar
|
||||
<< std::endl;
|
||||
sif::debug << "PdecHandler::resetFarStatFlag: read FAR with value: 0x" << std::hex << pdecFar
|
||||
<< std::endl;
|
||||
#endif /* OBSW_DEBUG_PDEC_HANDLER == 1 */
|
||||
return RETURN_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::releasePdec() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
result = gpioComIF->pullHigh(pdecReset);
|
||||
if (result != RETURN_OK) {
|
||||
sif::error << "PdecHandler::releasePdec: Failed to release PDEC reset signal" << std::endl;
|
||||
}
|
||||
return result;
|
||||
ReturnValue_t PdecHandler::releasePdec() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
result = gpioComIF->pullHigh(pdecReset);
|
||||
if (result != RETURN_OK) {
|
||||
sif::error << "PdecHandler::releasePdec: Failed to release PDEC reset signal" << std::endl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::performOperation(uint8_t operationCode) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
readCommandQueue();
|
||||
|
||||
readCommandQueue();
|
||||
|
||||
switch(state) {
|
||||
switch (state) {
|
||||
case State::INIT:
|
||||
resetFarStatFlag();
|
||||
if (result != RETURN_OK) {
|
||||
// Requires reconfiguration and reinitialization of PDEC
|
||||
triggerEvent(INVALID_FAR);
|
||||
state = State::WAIT_FOR_RECOVERY;
|
||||
return result;
|
||||
}
|
||||
state = State::RUNNING;
|
||||
break;
|
||||
resetFarStatFlag();
|
||||
if (result != RETURN_OK) {
|
||||
// Requires reconfiguration and reinitialization of PDEC
|
||||
triggerEvent(INVALID_FAR);
|
||||
state = State::WAIT_FOR_RECOVERY;
|
||||
return result;
|
||||
}
|
||||
state = State::RUNNING;
|
||||
break;
|
||||
case State::RUNNING:
|
||||
if (newTcReceived()) {
|
||||
handleNewTc();
|
||||
}
|
||||
checkLocks();
|
||||
break;
|
||||
if (newTcReceived()) {
|
||||
handleNewTc();
|
||||
}
|
||||
checkLocks();
|
||||
break;
|
||||
case State::WAIT_FOR_RECOVERY:
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
sif::debug << "PdecHandler::performOperation: Invalid state" << std::endl;
|
||||
break;
|
||||
}
|
||||
sif::debug << "PdecHandler::performOperation: Invalid state" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void PdecHandler::readCommandQueue(void) {
|
||||
CommandMessage commandMessage;
|
||||
ReturnValue_t result = RETURN_FAILED;
|
||||
CommandMessage commandMessage;
|
||||
ReturnValue_t result = RETURN_FAILED;
|
||||
|
||||
result = commandQueue->receiveMessage(&commandMessage);
|
||||
result = commandQueue->receiveMessage(&commandMessage);
|
||||
if (result == RETURN_OK) {
|
||||
result = actionHelper.handleActionMessage(&commandMessage);
|
||||
if (result == RETURN_OK) {
|
||||
result = actionHelper.handleActionMessage(&commandMessage);
|
||||
if (result == RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
CommandMessage reply;
|
||||
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND,
|
||||
commandMessage.getCommand());
|
||||
commandQueue->reply(&reply);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
CommandMessage reply;
|
||||
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, commandMessage.getCommand());
|
||||
commandQueue->reply(&reply);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool PdecHandler::newTcReceived() {
|
||||
uint32_t pdecFar = *(registerBaseAddress + PDEC_FAR_OFFSET);
|
||||
uint32_t pdecFar = *(registerBaseAddress + PDEC_FAR_OFFSET);
|
||||
|
||||
if (pdecFar >> STAT_POSITION != NEW_FAR_RECEIVED) {
|
||||
return false;
|
||||
}
|
||||
if (!checkFrameAna(pdecFar)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (pdecFar >> STAT_POSITION != NEW_FAR_RECEIVED) {
|
||||
return false;
|
||||
}
|
||||
if (!checkFrameAna(pdecFar)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PdecHandler::checkLocks() {
|
||||
uint32_t clcw = getClcw();
|
||||
if (!(clcw & NO_RF_MASK) && (lastClcw & NO_RF_MASK)) {
|
||||
// Rf available changed from 0 to 1
|
||||
triggerEvent(CARRIER_LOCK);
|
||||
}
|
||||
if (!(clcw & NO_BITLOCK_MASK) && (lastClcw & NO_BITLOCK_MASK)) {
|
||||
// Bit lock changed from 0 to 1
|
||||
triggerEvent(BIT_LOCK_PDEC);
|
||||
}
|
||||
lastClcw = clcw;
|
||||
uint32_t clcw = getClcw();
|
||||
if (!(clcw & NO_RF_MASK) && (lastClcw & NO_RF_MASK)) {
|
||||
// Rf available changed from 0 to 1
|
||||
triggerEvent(CARRIER_LOCK);
|
||||
}
|
||||
if (!(clcw & NO_BITLOCK_MASK) && (lastClcw & NO_BITLOCK_MASK)) {
|
||||
// Bit lock changed from 0 to 1
|
||||
triggerEvent(BIT_LOCK_PDEC);
|
||||
}
|
||||
lastClcw = clcw;
|
||||
}
|
||||
|
||||
bool PdecHandler::checkFrameAna(uint32_t pdecFar) {
|
||||
bool frameValid = false;
|
||||
FrameAna_t frameAna = static_cast<FrameAna_t>((pdecFar & FRAME_ANA_MASK) >> FRAME_ANA_POSITION);
|
||||
switch(frameAna) {
|
||||
case(FrameAna_t::ABANDONED_CLTU): {
|
||||
triggerEvent(INVALID_TC_FRAME, ABANDONED_CLTU);
|
||||
sif::warning << "PdecHandler::checkFrameAna: Abondoned CLTU" << std::endl;
|
||||
break;
|
||||
bool frameValid = false;
|
||||
FrameAna_t frameAna = static_cast<FrameAna_t>((pdecFar & FRAME_ANA_MASK) >> FRAME_ANA_POSITION);
|
||||
switch (frameAna) {
|
||||
case (FrameAna_t::ABANDONED_CLTU): {
|
||||
triggerEvent(INVALID_TC_FRAME, ABANDONED_CLTU);
|
||||
sif::warning << "PdecHandler::checkFrameAna: Abondoned CLTU" << std::endl;
|
||||
break;
|
||||
}
|
||||
case(FrameAna_t::FRAME_DIRTY): {
|
||||
triggerEvent(INVALID_TC_FRAME, FRAME_DIRTY);
|
||||
sif::warning << "PdecHandler::checkFrameAna: Frame dirty" << std::endl;
|
||||
break;
|
||||
case (FrameAna_t::FRAME_DIRTY): {
|
||||
triggerEvent(INVALID_TC_FRAME, FRAME_DIRTY);
|
||||
sif::warning << "PdecHandler::checkFrameAna: Frame dirty" << std::endl;
|
||||
break;
|
||||
}
|
||||
case(FrameAna_t::FRAME_ILLEGAL): {
|
||||
sif::warning << "PdecHandler::checkFrameAna: Frame illegal for one reason" << std::endl;
|
||||
handleIReason(pdecFar, FRAME_ILLEGAL_ONE_REASON);
|
||||
break;
|
||||
case (FrameAna_t::FRAME_ILLEGAL): {
|
||||
sif::warning << "PdecHandler::checkFrameAna: Frame illegal for one reason" << std::endl;
|
||||
handleIReason(pdecFar, FRAME_ILLEGAL_ONE_REASON);
|
||||
break;
|
||||
}
|
||||
case(FrameAna_t::FRAME_ILLEGAL_MULTI_REASON): {
|
||||
sif::warning << "PdecHandler::checkFrameAna: Frame illegal for multiple reasons"
|
||||
<< std::endl;
|
||||
handleIReason(pdecFar, FRAME_ILLEGAL_MULTIPLE_REASONS);
|
||||
break;
|
||||
case (FrameAna_t::FRAME_ILLEGAL_MULTI_REASON): {
|
||||
sif::warning << "PdecHandler::checkFrameAna: Frame illegal for multiple reasons" << std::endl;
|
||||
handleIReason(pdecFar, FRAME_ILLEGAL_MULTIPLE_REASONS);
|
||||
break;
|
||||
}
|
||||
case(FrameAna_t::AD_DISCARDED_LOCKOUT): {
|
||||
triggerEvent(INVALID_TC_FRAME, AD_DISCARDED_LOCKOUT);
|
||||
sif::warning << "PdecHandler::checkFrameAna: AD frame discarded because of lockout"
|
||||
<< std::endl;
|
||||
break;
|
||||
case (FrameAna_t::AD_DISCARDED_LOCKOUT): {
|
||||
triggerEvent(INVALID_TC_FRAME, AD_DISCARDED_LOCKOUT);
|
||||
sif::warning << "PdecHandler::checkFrameAna: AD frame discarded because of lockout"
|
||||
<< std::endl;
|
||||
break;
|
||||
}
|
||||
case(FrameAna_t::AD_DISCARDED_WAIT): {
|
||||
triggerEvent(INVALID_TC_FRAME, AD_DISCARDED_LOCKOUT);
|
||||
sif::warning << "PdecHandler::checkFrameAna: AD frame discarded because of wait"
|
||||
<< std::endl;
|
||||
break;
|
||||
case (FrameAna_t::AD_DISCARDED_WAIT): {
|
||||
triggerEvent(INVALID_TC_FRAME, AD_DISCARDED_LOCKOUT);
|
||||
sif::warning << "PdecHandler::checkFrameAna: AD frame discarded because of wait" << std::endl;
|
||||
break;
|
||||
}
|
||||
case(FrameAna_t::AD_DISCARDED_NS_VR): {
|
||||
triggerEvent(INVALID_TC_FRAME, AD_DISCARDED_NS_VS);
|
||||
sif::warning << "PdecHandler::checkFrameAna: AD frame discarded because N(S) or V(R)"
|
||||
<< std::endl;
|
||||
break;
|
||||
case (FrameAna_t::AD_DISCARDED_NS_VR): {
|
||||
triggerEvent(INVALID_TC_FRAME, AD_DISCARDED_NS_VS);
|
||||
sif::warning << "PdecHandler::checkFrameAna: AD frame discarded because N(S) or V(R)"
|
||||
<< std::endl;
|
||||
break;
|
||||
}
|
||||
case(FrameAna_t::FRAME_ACCEPTED): {
|
||||
case (FrameAna_t::FRAME_ACCEPTED): {
|
||||
#if OBSW_DEBUG_PDEC_HANDLER == 1
|
||||
sif::info << "PdecHandler::checkFrameAna: Accepted TC frame" << std::endl;
|
||||
sif::info << "PdecHandler::checkFrameAna: Accepted TC frame" << std::endl;
|
||||
#endif
|
||||
frameValid = true;
|
||||
break;
|
||||
frameValid = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sif::debug << "PdecHandler::checkFrameAna: Invalid frame analysis report" << std::endl;
|
||||
break;
|
||||
sif::debug << "PdecHandler::checkFrameAna: Invalid frame analysis report" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return frameValid;
|
||||
}
|
||||
return frameValid;
|
||||
}
|
||||
|
||||
void PdecHandler::handleIReason(uint32_t pdecFar, ReturnValue_t parameter1) {
|
||||
IReason_t ireason = static_cast<IReason_t>((pdecFar & IREASON_MASK) >> IREASON_POSITION);
|
||||
switch(ireason) {
|
||||
case(IReason_t::NO_REPORT): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, NO_REPORT);
|
||||
sif::info << "PdecHandler::handleIReason: No illegal report" << std::endl;
|
||||
break;
|
||||
IReason_t ireason = static_cast<IReason_t>((pdecFar & IREASON_MASK) >> IREASON_POSITION);
|
||||
switch (ireason) {
|
||||
case (IReason_t::NO_REPORT): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, NO_REPORT);
|
||||
sif::info << "PdecHandler::handleIReason: No illegal report" << std::endl;
|
||||
break;
|
||||
}
|
||||
case(IReason_t::ERROR_VERSION_NUMBER): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, ERROR_VERSION_NUMBER);
|
||||
sif::info << "PdecHandler::handleIReason: Error in version number and reserved A and B "
|
||||
case (IReason_t::ERROR_VERSION_NUMBER): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, ERROR_VERSION_NUMBER);
|
||||
sif::info << "PdecHandler::handleIReason: Error in version number and reserved A and B "
|
||||
<< "fields" << std::endl;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case(IReason_t::ILLEGAL_COMBINATION): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, ILLEGAL_COMBINATION);
|
||||
sif::info << "PdecHandler::handleIReason: Illegal combination (AC) of bypass and control "
|
||||
case (IReason_t::ILLEGAL_COMBINATION): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, ILLEGAL_COMBINATION);
|
||||
sif::info << "PdecHandler::handleIReason: Illegal combination (AC) of bypass and control "
|
||||
<< "command flags" << std::endl;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case(IReason_t::INVALID_SC_ID): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_SC_ID);
|
||||
sif::info << "PdecHandler::handleIReason: Invalid spacecraft identifier " << std::endl;
|
||||
break;
|
||||
case (IReason_t::INVALID_SC_ID): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_SC_ID);
|
||||
sif::info << "PdecHandler::handleIReason: Invalid spacecraft identifier " << std::endl;
|
||||
break;
|
||||
}
|
||||
case(IReason_t::INVALID_VC_ID_MSB): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_VC_ID_MSB);
|
||||
sif::info << "PdecHandler::handleIReason: VC identifier bit 0 to 4 did not match "
|
||||
case (IReason_t::INVALID_VC_ID_MSB): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_VC_ID_MSB);
|
||||
sif::info << "PdecHandler::handleIReason: VC identifier bit 0 to 4 did not match "
|
||||
<< std::endl;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case(IReason_t::INVALID_VC_ID_LSB): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_VC_ID_LSB);
|
||||
sif::info << "PdecHandler::handleIReason: VC identifier bit 5 did not match " << std::endl;
|
||||
break;
|
||||
case (IReason_t::INVALID_VC_ID_LSB): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_VC_ID_LSB);
|
||||
sif::info << "PdecHandler::handleIReason: VC identifier bit 5 did not match " << std::endl;
|
||||
break;
|
||||
}
|
||||
case(IReason_t::NS_NOT_ZERO): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, NS_NOT_ZERO);
|
||||
sif::info << "PdecHandler::handleIReason: N(S) of BC or BD frame not set to all zeros"
|
||||
case (IReason_t::NS_NOT_ZERO): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, NS_NOT_ZERO);
|
||||
sif::info << "PdecHandler::handleIReason: N(S) of BC or BD frame not set to all zeros"
|
||||
<< std::endl;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case(IReason_t::INCORRECT_BC_CC): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_BC_CC);
|
||||
sif::info << "PdecHandler::handleIReason: Invalid BC control command format" << std::endl;
|
||||
break;
|
||||
case (IReason_t::INCORRECT_BC_CC): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_BC_CC);
|
||||
sif::info << "PdecHandler::handleIReason: Invalid BC control command format" << std::endl;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sif::info << "PdecHandler::handleIReason: Invalid reason id" << std::endl;
|
||||
break;
|
||||
}
|
||||
sif::info << "PdecHandler::handleIReason: Invalid reason id" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PdecHandler::handleNewTc() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
|
||||
uint32_t tcLength = 0;
|
||||
result = readTc(tcLength);
|
||||
if (result != RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
uint32_t tcLength = 0;
|
||||
result = readTc(tcLength);
|
||||
if (result != RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
#if OBSW_DEBUG_PDEC_HANDLER == 1
|
||||
unsigned int mapId = tcSegment[0] & MAP_ID_MASK;
|
||||
sif::info << "PdecHandler::handleNewTc: Received TC segment with map ID " << mapId
|
||||
<< std::endl;
|
||||
printTC(tcLength);
|
||||
unsigned int mapId = tcSegment[0] & MAP_ID_MASK;
|
||||
sif::info << "PdecHandler::handleNewTc: Received TC segment with map ID " << mapId << std::endl;
|
||||
printTC(tcLength);
|
||||
#endif /* OBSW_DEBUG_PDEC_HANDLER */
|
||||
|
||||
store_address_t storeId;
|
||||
result = tcStore->addData(&storeId, tcSegment + 1, tcLength - 1);
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PdecHandler::handleNewTc: Failed to add received space packet to store"
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
TmTcMessage message(storeId);
|
||||
|
||||
result = MessageQueueSenderIF::sendMessage(tcDestination->getRequestQueue(), &message);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::warning << "PdecHandler::handleNewTc: Failed to send message to TC destination"
|
||||
<< std::endl;
|
||||
tcStore->deleteData(storeId);
|
||||
return;
|
||||
}
|
||||
|
||||
store_address_t storeId;
|
||||
result = tcStore->addData(&storeId, tcSegment + 1, tcLength - 1);
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PdecHandler::handleNewTc: Failed to add received space packet to store"
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
TmTcMessage message(storeId);
|
||||
|
||||
result = MessageQueueSenderIF::sendMessage(tcDestination->getRequestQueue(), &message);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::warning << "PdecHandler::handleNewTc: Failed to send message to TC destination"
|
||||
<< std::endl;
|
||||
tcStore->deleteData(storeId);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::readTc(uint32_t& tcLength) {
|
||||
uint32_t tcOffset = (*(registerBaseAddress + PDEC_BPTR_OFFSET) - PHYSICAL_RAM_BASE_ADDRESS) / 4;
|
||||
uint32_t tcOffset = (*(registerBaseAddress + PDEC_BPTR_OFFSET) - PHYSICAL_RAM_BASE_ADDRESS) / 4;
|
||||
|
||||
#if OBSW_DEBUG_PDEC_HANDLER == 1
|
||||
sif::debug << "PdecHandler::readTc: TC offset: 0x" << std::hex << tcOffset << std::endl;
|
||||
sif::debug << "PdecHandler::readTc: TC offset: 0x" << std::hex << tcOffset << std::endl;
|
||||
#endif /* OBSW_DEBUG_PDEC_HANDLER */
|
||||
|
||||
tcLength = *(registerBaseAddress + PDEC_SLEN_OFFSET);
|
||||
tcLength = *(registerBaseAddress + PDEC_SLEN_OFFSET);
|
||||
|
||||
#if OBSW_DEBUG_PDEC_HANDLER == 1
|
||||
sif::debug << "PdecHandler::readTc: TC segment length: " << std::dec << tcLength << std::endl;
|
||||
sif::debug << "PdecHandler::readTc: TC segment length: " << std::dec << tcLength << std::endl;
|
||||
#endif /* OBSW_DEBUG_PDEC_HANDLER */
|
||||
|
||||
if (tcLength > MAX_TC_SEGMENT_SIZE) {
|
||||
sif::warning << "PdecHandler::handleNewTc: Read invalid TC length from PDEC register"
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
if (tcLength > MAX_TC_SEGMENT_SIZE) {
|
||||
sif::warning << "PdecHandler::handleNewTc: Read invalid TC length from PDEC register"
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
uint32_t idx = 0;
|
||||
uint32_t tcData = 0;
|
||||
for (idx = 0; idx <= tcLength; idx = idx + 4) {
|
||||
tcData = *(ramBaseAddress + tcOffset + idx / 4);
|
||||
if (idx == 0) {
|
||||
tcSegment[idx] = static_cast<uint8_t>((tcData >> 16) & 0xFF);
|
||||
tcSegment[idx + 1] = static_cast<uint8_t>((tcData >> 8) & 0xFF);
|
||||
tcSegment[idx + 2] = static_cast<uint8_t>(tcData & 0xFF);
|
||||
} else if (tcLength - idx + 1 == 3) {
|
||||
tcSegment[idx - 1] = static_cast<uint8_t>((tcData >> 24) & 0xFF);
|
||||
tcSegment[idx] = static_cast<uint8_t>((tcData >> 16) & 0xFF);
|
||||
tcSegment[idx + 1] = static_cast<uint8_t>((tcData >> 8) & 0xFF);
|
||||
} else if (tcLength - idx + 1 == 2) {
|
||||
tcSegment[idx - 1] = static_cast<uint8_t>((tcData >> 24) & 0xFF);
|
||||
tcSegment[idx] = static_cast<uint8_t>((tcData >> 16) & 0xFF);
|
||||
} else if (tcLength - idx + 1 == 1) {
|
||||
tcSegment[idx - 1] = static_cast<uint8_t>((tcData >> 24) & 0xFF);
|
||||
} else {
|
||||
tcSegment[idx - 1] = static_cast<uint8_t>((tcData >> 24) & 0xFF);
|
||||
tcSegment[idx] = static_cast<uint8_t>((tcData >> 16) & 0xFF);
|
||||
tcSegment[idx + 1] = static_cast<uint8_t>((tcData >> 8) & 0xFF);
|
||||
tcSegment[idx + 2] = static_cast<uint8_t>(tcData & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t idx = 0;
|
||||
uint32_t tcData = 0;
|
||||
for (idx = 0; idx <= tcLength; idx = idx + 4) {
|
||||
tcData = *(ramBaseAddress + tcOffset + idx / 4);
|
||||
if (idx == 0) {
|
||||
tcSegment[idx] = static_cast<uint8_t>((tcData >> 16) & 0xFF);
|
||||
tcSegment[idx + 1] = static_cast<uint8_t>((tcData >> 8) & 0xFF);
|
||||
tcSegment[idx + 2] = static_cast<uint8_t>(tcData & 0xFF);
|
||||
}
|
||||
else if (tcLength - idx + 1 == 3) {
|
||||
tcSegment[idx - 1] = static_cast<uint8_t>((tcData >> 24) & 0xFF);
|
||||
tcSegment[idx] = static_cast<uint8_t>((tcData >> 16) & 0xFF);
|
||||
tcSegment[idx + 1] = static_cast<uint8_t>((tcData >> 8) & 0xFF);
|
||||
}
|
||||
else if (tcLength - idx + 1 == 2) {
|
||||
tcSegment[idx - 1] = static_cast<uint8_t>((tcData >> 24) & 0xFF);
|
||||
tcSegment[idx] = static_cast<uint8_t>((tcData >> 16) & 0xFF);
|
||||
}
|
||||
else if (tcLength - idx + 1 == 1) {
|
||||
tcSegment[idx - 1] = static_cast<uint8_t>((tcData >> 24) & 0xFF);
|
||||
}
|
||||
else {
|
||||
tcSegment[idx - 1] = static_cast<uint8_t>((tcData >> 24) & 0xFF);
|
||||
tcSegment[idx] = static_cast<uint8_t>((tcData >> 16) & 0xFF);
|
||||
tcSegment[idx + 1] = static_cast<uint8_t>((tcData >> 8) & 0xFF);
|
||||
tcSegment[idx + 2] = static_cast<uint8_t>(tcData & 0xFF);
|
||||
}
|
||||
}
|
||||
// Backend buffer is handled back to PDEC3
|
||||
*(registerBaseAddress + PDEC_BFREE_OFFSET) = 0;
|
||||
|
||||
// Backend buffer is handled back to PDEC3
|
||||
*(registerBaseAddress + PDEC_BFREE_OFFSET) = 0;
|
||||
|
||||
return RETURN_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void PdecHandler::printTC(uint32_t tcLength) {
|
||||
std::stringstream tcSegmentStream;
|
||||
tcSegmentStream << "TC segment data: 0x";
|
||||
for (uint32_t idx = 0; idx < tcLength; idx++) {
|
||||
tcSegmentStream << std::setfill('0') << std::setw(2) << std::hex
|
||||
<< static_cast<unsigned int>(tcSegment[idx]);
|
||||
}
|
||||
sif::info << tcSegmentStream.str() << std::endl;
|
||||
std::stringstream tcSegmentStream;
|
||||
tcSegmentStream << "TC segment data: 0x";
|
||||
for (uint32_t idx = 0; idx < tcLength; idx++) {
|
||||
tcSegmentStream << std::setfill('0') << std::setw(2) << std::hex
|
||||
<< static_cast<unsigned int>(tcSegment[idx]);
|
||||
}
|
||||
sif::info << tcSegmentStream.str() << std::endl;
|
||||
}
|
||||
|
||||
uint8_t PdecHandler::calcMapAddrEntry(uint8_t moduleId) {
|
||||
uint8_t lutEntry = 0;
|
||||
uint8_t parity = getOddParity(moduleId | (1 << VALID_POSITION));
|
||||
lutEntry = (parity << PARITY_POSITION) | (1 << VALID_POSITION) | moduleId;
|
||||
return lutEntry;
|
||||
uint8_t lutEntry = 0;
|
||||
uint8_t parity = getOddParity(moduleId | (1 << VALID_POSITION));
|
||||
lutEntry = (parity << PARITY_POSITION) | (1 << VALID_POSITION) | moduleId;
|
||||
return lutEntry;
|
||||
}
|
||||
|
||||
uint8_t PdecHandler::getOddParity(uint8_t number) {
|
||||
uint8_t parityBit = 0;
|
||||
uint8_t countBits = 0;
|
||||
for (unsigned int idx = 0; idx < sizeof(number) * 8; idx++) {
|
||||
countBits += (number >> idx) & 0x1;
|
||||
}
|
||||
parityBit = ~(countBits & 0x1) & 0x1;
|
||||
return parityBit;
|
||||
uint8_t parityBit = 0;
|
||||
uint8_t countBits = 0;
|
||||
for (unsigned int idx = 0; idx < sizeof(number) * 8; idx++) {
|
||||
countBits += (number >> idx) & 0x1;
|
||||
}
|
||||
parityBit = ~(countBits & 0x1) & 0x1;
|
||||
return parityBit;
|
||||
}
|
||||
|
||||
uint32_t PdecHandler::getClcw() {
|
||||
return *(registerBaseAddress + PDEC_CLCW_OFFSET);
|
||||
}
|
||||
uint32_t PdecHandler::getClcw() { return *(registerBaseAddress + PDEC_CLCW_OFFSET); }
|
||||
|
||||
uint32_t PdecHandler::getPdecMon() {
|
||||
return *(registerBaseAddress + PDEC_MON_OFFSET);
|
||||
}
|
||||
uint32_t PdecHandler::getPdecMon() { return *(registerBaseAddress + PDEC_MON_OFFSET); }
|
||||
|
||||
void PdecHandler::printClcw() {
|
||||
uint32_t clcw = getClcw();
|
||||
uint8_t type = static_cast<uint8_t>((clcw >> 31) & 0x1);
|
||||
uint8_t versionNo = static_cast<uint8_t>((clcw >> 29) & 0x3);
|
||||
uint8_t status = static_cast<uint8_t>((clcw >> 26) & 0x7);
|
||||
uint8_t cop = static_cast<uint8_t>((clcw >> 24) & 0x3);
|
||||
uint8_t vcId = static_cast<uint8_t>((clcw >> 18) & 0x3F);
|
||||
uint8_t noRf = static_cast<uint8_t>((clcw >> 15) & 0x1);
|
||||
uint8_t noBitLock = static_cast<uint8_t>((clcw >> 14) & 0x1);
|
||||
uint8_t lockoutFlag = static_cast<uint8_t>((clcw >> 13) & 0x1);
|
||||
uint8_t waitFlag = static_cast<uint8_t>((clcw >> 12) & 0x1);
|
||||
uint8_t retransmitFlag = static_cast<uint8_t>((clcw >> 11) & 0x1);
|
||||
uint8_t farmBcnt = static_cast<uint8_t>((clcw >> 9) & 0x3);
|
||||
// Expected frame sequence number in te next AD frame
|
||||
uint8_t repValue = static_cast<uint8_t>(clcw & 0xFF);
|
||||
sif::info << std::setw(30) << std::left << "CLCW type: " << std::hex
|
||||
<< "0x" << static_cast<unsigned int>(type) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW version no: " << std::hex
|
||||
<< "0x" << static_cast<unsigned int>(versionNo) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW status: " << std::hex
|
||||
<< "0x" << static_cast<unsigned int>(status) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW COP: " << std::hex
|
||||
<< "0x" << static_cast<unsigned int>(cop) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW virtual channel ID: " << std::hex
|
||||
<< "0x" << static_cast<unsigned int>(vcId) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW no RF: " << std::hex
|
||||
<< "0x" << static_cast<unsigned int>(noRf) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW no bit lock: " << std::hex
|
||||
<< "0x" << static_cast<unsigned int>(noBitLock) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW lockout flag: " << std::hex
|
||||
<< "0x" << static_cast<unsigned int>(lockoutFlag) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW wait flag: " << std::hex
|
||||
<< "0x" << static_cast<unsigned int>(waitFlag) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW retransmit flag: " << std::hex
|
||||
<< "0x" << static_cast<unsigned int>(retransmitFlag) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW FARM B count: " << std::hex
|
||||
<< "0x" << static_cast<unsigned int>(farmBcnt) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW rep value: " << std::hex
|
||||
<< "0x" << static_cast<unsigned int>(repValue) << std::endl;
|
||||
uint32_t clcw = getClcw();
|
||||
uint8_t type = static_cast<uint8_t>((clcw >> 31) & 0x1);
|
||||
uint8_t versionNo = static_cast<uint8_t>((clcw >> 29) & 0x3);
|
||||
uint8_t status = static_cast<uint8_t>((clcw >> 26) & 0x7);
|
||||
uint8_t cop = static_cast<uint8_t>((clcw >> 24) & 0x3);
|
||||
uint8_t vcId = static_cast<uint8_t>((clcw >> 18) & 0x3F);
|
||||
uint8_t noRf = static_cast<uint8_t>((clcw >> 15) & 0x1);
|
||||
uint8_t noBitLock = static_cast<uint8_t>((clcw >> 14) & 0x1);
|
||||
uint8_t lockoutFlag = static_cast<uint8_t>((clcw >> 13) & 0x1);
|
||||
uint8_t waitFlag = static_cast<uint8_t>((clcw >> 12) & 0x1);
|
||||
uint8_t retransmitFlag = static_cast<uint8_t>((clcw >> 11) & 0x1);
|
||||
uint8_t farmBcnt = static_cast<uint8_t>((clcw >> 9) & 0x3);
|
||||
// Expected frame sequence number in te next AD frame
|
||||
uint8_t repValue = static_cast<uint8_t>(clcw & 0xFF);
|
||||
sif::info << std::setw(30) << std::left << "CLCW type: " << std::hex << "0x"
|
||||
<< static_cast<unsigned int>(type) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW version no: " << std::hex << "0x"
|
||||
<< static_cast<unsigned int>(versionNo) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW status: " << std::hex << "0x"
|
||||
<< static_cast<unsigned int>(status) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW COP: " << std::hex << "0x"
|
||||
<< static_cast<unsigned int>(cop) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW virtual channel ID: " << std::hex << "0x"
|
||||
<< static_cast<unsigned int>(vcId) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW no RF: " << std::hex << "0x"
|
||||
<< static_cast<unsigned int>(noRf) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW no bit lock: " << std::hex << "0x"
|
||||
<< static_cast<unsigned int>(noBitLock) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW lockout flag: " << std::hex << "0x"
|
||||
<< static_cast<unsigned int>(lockoutFlag) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW wait flag: " << std::hex << "0x"
|
||||
<< static_cast<unsigned int>(waitFlag) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW retransmit flag: " << std::hex << "0x"
|
||||
<< static_cast<unsigned int>(retransmitFlag) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW FARM B count: " << std::hex << "0x"
|
||||
<< static_cast<unsigned int>(farmBcnt) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "CLCW rep value: " << std::hex << "0x"
|
||||
<< static_cast<unsigned int>(repValue) << std::endl;
|
||||
}
|
||||
|
||||
void PdecHandler::printPdecMon() {
|
||||
uint32_t pdecMon = getPdecMon();
|
||||
uint32_t tc0ChannelStatus = (pdecMon & TC0_STATUS_MASK) >> TC0_STATUS_POS;
|
||||
uint32_t tc1ChannelStatus = (pdecMon & TC1_STATUS_MASK) >> TC1_STATUS_POS;
|
||||
uint32_t tc2ChannelStatus = (pdecMon & TC2_STATUS_MASK) >> TC2_STATUS_POS;
|
||||
uint32_t tc3ChannelStatus = (pdecMon & TC3_STATUS_MASK) >> TC3_STATUS_POS;
|
||||
uint32_t tc4ChannelStatus = (pdecMon & TC4_STATUS_MASK) >> TC4_STATUS_POS;
|
||||
uint32_t tc5ChannelStatus = (pdecMon & TC5_STATUS_MASK) >> TC5_STATUS_POS;
|
||||
uint32_t lock = (pdecMon & LOCK_MASK) >> LOCK_POS;
|
||||
sif::info << std::setw(30) << std::left << "TC0 status: " << getMonStatusString(tc0ChannelStatus) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "TC1 status: " << getMonStatusString(tc1ChannelStatus) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "TC2 status: " << getMonStatusString(tc2ChannelStatus) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "TC3 status: " << getMonStatusString(tc3ChannelStatus) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "TC4 status: " << getMonStatusString(tc4ChannelStatus) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "TC5 status: " << getMonStatusString(tc5ChannelStatus) << std::endl;
|
||||
sif::info << std::setw(30) << std::left << "Start sequence lock: " << lock << std::endl;
|
||||
uint32_t pdecMon = getPdecMon();
|
||||
uint32_t tc0ChannelStatus = (pdecMon & TC0_STATUS_MASK) >> TC0_STATUS_POS;
|
||||
uint32_t tc1ChannelStatus = (pdecMon & TC1_STATUS_MASK) >> TC1_STATUS_POS;
|
||||
uint32_t tc2ChannelStatus = (pdecMon & TC2_STATUS_MASK) >> TC2_STATUS_POS;
|
||||
uint32_t tc3ChannelStatus = (pdecMon & TC3_STATUS_MASK) >> TC3_STATUS_POS;
|
||||
uint32_t tc4ChannelStatus = (pdecMon & TC4_STATUS_MASK) >> TC4_STATUS_POS;
|
||||
uint32_t tc5ChannelStatus = (pdecMon & TC5_STATUS_MASK) >> TC5_STATUS_POS;
|
||||
uint32_t lock = (pdecMon & LOCK_MASK) >> LOCK_POS;
|
||||
sif::info << std::setw(30) << std::left << "TC0 status: " << getMonStatusString(tc0ChannelStatus)
|
||||
<< std::endl;
|
||||
sif::info << std::setw(30) << std::left << "TC1 status: " << getMonStatusString(tc1ChannelStatus)
|
||||
<< std::endl;
|
||||
sif::info << std::setw(30) << std::left << "TC2 status: " << getMonStatusString(tc2ChannelStatus)
|
||||
<< std::endl;
|
||||
sif::info << std::setw(30) << std::left << "TC3 status: " << getMonStatusString(tc3ChannelStatus)
|
||||
<< std::endl;
|
||||
sif::info << std::setw(30) << std::left << "TC4 status: " << getMonStatusString(tc4ChannelStatus)
|
||||
<< std::endl;
|
||||
sif::info << std::setw(30) << std::left << "TC5 status: " << getMonStatusString(tc5ChannelStatus)
|
||||
<< std::endl;
|
||||
sif::info << std::setw(30) << std::left << "Start sequence lock: " << lock << std::endl;
|
||||
}
|
||||
|
||||
std::string PdecHandler::getMonStatusString(uint32_t status) {
|
||||
switch(status) {
|
||||
case TC_CHANNEL_INACTIVE:
|
||||
return std::string("inactive");
|
||||
case TC_CHANNEL_ACTIVE:
|
||||
return std::string("active");
|
||||
case TC_CHANNEL_TIMEDOUT:
|
||||
return std::string("timed out");
|
||||
default:
|
||||
sif::warning << "PdecHandler::getMonStatusString: Invalid status" << std::endl;
|
||||
return std::string();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t PdecHandler::executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
|
||||
switch(actionId) {
|
||||
case PRINT_CLCW:
|
||||
printClcw();
|
||||
return EXECUTION_FINISHED;
|
||||
case PRINT_PDEC_MON:
|
||||
printPdecMon();
|
||||
return EXECUTION_FINISHED;
|
||||
switch (status) {
|
||||
case TC_CHANNEL_INACTIVE:
|
||||
return std::string("inactive");
|
||||
case TC_CHANNEL_ACTIVE:
|
||||
return std::string("active");
|
||||
case TC_CHANNEL_TIMEDOUT:
|
||||
return std::string("timed out");
|
||||
default:
|
||||
return COMMAND_NOT_IMPLEMENTED;
|
||||
}
|
||||
sif::warning << "PdecHandler::getMonStatusString: Invalid status" << std::endl;
|
||||
return std::string();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) {
|
||||
switch (actionId) {
|
||||
case PRINT_CLCW:
|
||||
printClcw();
|
||||
return EXECUTION_FINISHED;
|
||||
case PRINT_PDEC_MON:
|
||||
printPdecMon();
|
||||
return EXECUTION_FINISHED;
|
||||
default:
|
||||
return COMMAND_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
|
@ -3,15 +3,15 @@
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "PdecConfig.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw_hal/common/gpio/gpioDefinitions.h"
|
||||
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
|
||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw/action/ActionHelper.h"
|
||||
#include "fsfw/action/HasActionsIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
||||
#include "fsfw_hal/common/gpio/gpioDefinitions.h"
|
||||
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
|
||||
|
||||
/**
|
||||
* @brief This class controls the PDEC IP Core implemented in the programmable logic of the
|
||||
@ -35,386 +35,381 @@ class PdecHandler : public SystemObject,
|
||||
public ExecutableObjectIF,
|
||||
public HasReturnvaluesIF,
|
||||
public HasActionsIF {
|
||||
public:
|
||||
/**
|
||||
* @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,
|
||||
gpioId_t pdecReset, std::string uioConfigMemory, std::string uioRamMemory,
|
||||
std::string uioRegisters);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @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,
|
||||
gpioId_t pdecReset, std::string uioConfigMemory, std::string uioRamMemory,
|
||||
std::string uioRegisters);
|
||||
virtual ~PdecHandler();
|
||||
|
||||
virtual ~PdecHandler();
|
||||
ReturnValue_t performOperation(uint8_t operationCode = 0);
|
||||
|
||||
ReturnValue_t performOperation(uint8_t operationCode = 0);
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
MessageQueueId_t getCommandQueue() const;
|
||||
|
||||
MessageQueueId_t getCommandQueue() const;
|
||||
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) override;
|
||||
|
||||
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) override;
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PDEC_HANDLER;
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PDEC_HANDLER;
|
||||
//! [EXPORT] : [COMMENT] Frame acceptance report signals an invalid frame
|
||||
//! P1: The frame analysis information (FrameAna field of PDEC_FAR register)
|
||||
//! P2: When frame declared illegal this parameter this parameter gives information about the
|
||||
//! reason (IReason field of the PDEC_FAR register)
|
||||
static const Event INVALID_TC_FRAME = MAKE_EVENT(1, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Read invalid FAR from PDEC after startup
|
||||
static const Event INVALID_FAR = MAKE_EVENT(2, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Carrier lock detected
|
||||
static const Event CARRIER_LOCK = MAKE_EVENT(3, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Bit lock detected (data valid)
|
||||
static const Event BIT_LOCK_PDEC = MAKE_EVENT(4, severity::INFO);
|
||||
|
||||
//! [EXPORT] : [COMMENT] Frame acceptance report signals an invalid frame
|
||||
//! P1: The frame analysis information (FrameAna field of PDEC_FAR register)
|
||||
//! P2: When frame declared illegal this parameter this parameter gives information about the reason (IReason field of the PDEC_FAR register)
|
||||
static const Event INVALID_TC_FRAME = MAKE_EVENT(1, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Read invalid FAR from PDEC after startup
|
||||
static const Event INVALID_FAR = MAKE_EVENT(2, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Carrier lock detected
|
||||
static const Event CARRIER_LOCK = MAKE_EVENT(3, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Bit lock detected (data valid)
|
||||
static const Event BIT_LOCK_PDEC = MAKE_EVENT(4, severity::INFO);
|
||||
private:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::PDEC_HANDLER;
|
||||
|
||||
private:
|
||||
static const ReturnValue_t ABANDONED_CLTU = MAKE_RETURN_CODE(0xA0);
|
||||
static const ReturnValue_t FRAME_DIRTY = MAKE_RETURN_CODE(0xA1);
|
||||
static const ReturnValue_t FRAME_ILLEGAL_ONE_REASON = MAKE_RETURN_CODE(0xA2);
|
||||
static const ReturnValue_t FRAME_ILLEGAL_MULTIPLE_REASONS = MAKE_RETURN_CODE(0xA2);
|
||||
static const ReturnValue_t AD_DISCARDED_LOCKOUT = MAKE_RETURN_CODE(0xA3);
|
||||
static const ReturnValue_t AD_DISCARDED_WAIT = MAKE_RETURN_CODE(0xA4);
|
||||
static const ReturnValue_t AD_DISCARDED_NS_VS = MAKE_RETURN_CODE(0xA5);
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::PDEC_HANDLER;
|
||||
//! [EXPORT] : [COMMENT] Received action message with unknown action id
|
||||
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xB0);
|
||||
|
||||
static const ReturnValue_t ABANDONED_CLTU = MAKE_RETURN_CODE(0xA0);
|
||||
static const ReturnValue_t FRAME_DIRTY = MAKE_RETURN_CODE(0xA1);
|
||||
static const ReturnValue_t FRAME_ILLEGAL_ONE_REASON = MAKE_RETURN_CODE(0xA2);
|
||||
static const ReturnValue_t FRAME_ILLEGAL_MULTIPLE_REASONS = MAKE_RETURN_CODE(0xA2);
|
||||
static const ReturnValue_t AD_DISCARDED_LOCKOUT = MAKE_RETURN_CODE(0xA3);
|
||||
static const ReturnValue_t AD_DISCARDED_WAIT = MAKE_RETURN_CODE(0xA4);
|
||||
static const ReturnValue_t AD_DISCARDED_NS_VS = MAKE_RETURN_CODE(0xA5);
|
||||
static const ReturnValue_t NO_REPORT = MAKE_RETURN_CODE(0xA6);
|
||||
//! Error in version number and reserved A and B fields
|
||||
static const ReturnValue_t ERROR_VERSION_NUMBER = MAKE_RETURN_CODE(0xA7);
|
||||
//! Illegal combination of bypass and control command flag
|
||||
static const ReturnValue_t ILLEGAL_COMBINATION = MAKE_RETURN_CODE(0xA8);
|
||||
//! Spacecraft identifier did not match
|
||||
static const ReturnValue_t INVALID_SC_ID = MAKE_RETURN_CODE(0xA9);
|
||||
//! VC identifier bits 0 to 4 did not match
|
||||
static const ReturnValue_t INVALID_VC_ID_MSB = MAKE_RETURN_CODE(0xAA);
|
||||
//! VC identifier bit 5 did not match
|
||||
static const ReturnValue_t INVALID_VC_ID_LSB = MAKE_RETURN_CODE(0xAB);
|
||||
//! N(S) of BC or BD frame not set to all zeros
|
||||
static const ReturnValue_t NS_NOT_ZERO = MAKE_RETURN_CODE(0xAC);
|
||||
//! Invalid BC control command
|
||||
static const ReturnValue_t INVALID_BC_CC = MAKE_RETURN_CODE(0xAE);
|
||||
|
||||
//! [EXPORT] : [COMMENT] Received action message with unknown action id
|
||||
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xB0);
|
||||
static const uint32_t QUEUE_SIZE = common::CCSDS_HANDLER_QUEUE_SIZE;
|
||||
|
||||
static const ReturnValue_t NO_REPORT = MAKE_RETURN_CODE(0xA6);
|
||||
//! Error in version number and reserved A and B fields
|
||||
static const ReturnValue_t ERROR_VERSION_NUMBER = MAKE_RETURN_CODE(0xA7);
|
||||
//! Illegal combination of bypass and control command flag
|
||||
static const ReturnValue_t ILLEGAL_COMBINATION = MAKE_RETURN_CODE(0xA8);
|
||||
//! Spacecraft identifier did not match
|
||||
static const ReturnValue_t INVALID_SC_ID = MAKE_RETURN_CODE(0xA9);
|
||||
//! VC identifier bits 0 to 4 did not match
|
||||
static const ReturnValue_t INVALID_VC_ID_MSB = MAKE_RETURN_CODE(0xAA);
|
||||
//! VC identifier bit 5 did not match
|
||||
static const ReturnValue_t INVALID_VC_ID_LSB = MAKE_RETURN_CODE(0xAB);
|
||||
//! N(S) of BC or BD frame not set to all zeros
|
||||
static const ReturnValue_t NS_NOT_ZERO = MAKE_RETURN_CODE(0xAC);
|
||||
//! Invalid BC control command
|
||||
static const ReturnValue_t INVALID_BC_CC = MAKE_RETURN_CODE(0xAE);
|
||||
// Action IDs
|
||||
static const ActionId_t PRINT_CLCW = 0;
|
||||
// Print PDEC monitor register
|
||||
static const ActionId_t PRINT_PDEC_MON = 1;
|
||||
|
||||
static const uint32_t QUEUE_SIZE = common::CCSDS_HANDLER_QUEUE_SIZE;
|
||||
static const uint8_t STAT_POSITION = 31;
|
||||
static const uint8_t FRAME_ANA_POSITION = 28;
|
||||
static const uint8_t IREASON_POSITION = 25;
|
||||
|
||||
// Action IDs
|
||||
static const ActionId_t PRINT_CLCW = 0;
|
||||
// Print PDEC monitor register
|
||||
static const ActionId_t PRINT_PDEC_MON = 1;
|
||||
static const uint8_t NEW_FAR_RECEIVED = 0;
|
||||
|
||||
static const uint8_t STAT_POSITION = 31;
|
||||
static const uint8_t FRAME_ANA_POSITION = 28;
|
||||
static const uint8_t IREASON_POSITION = 25;
|
||||
static const uint32_t FRAME_ANA_MASK = 0x70000000;
|
||||
static const uint32_t IREASON_MASK = 0x0E000000;
|
||||
|
||||
static const uint8_t NEW_FAR_RECEIVED = 0;
|
||||
static const uint32_t TC_CHANNEL_INACTIVE = 0x0;
|
||||
static const uint32_t TC_CHANNEL_ACTIVE = 0x1;
|
||||
static const uint32_t TC_CHANNEL_TIMEDOUT = 0x2;
|
||||
|
||||
static const uint32_t FRAME_ANA_MASK = 0x70000000;
|
||||
static const uint32_t IREASON_MASK = 0x0E000000;
|
||||
static const uint32_t TC0_STATUS_MASK = 0x3;
|
||||
static const uint32_t TC1_STATUS_MASK = 0xC;
|
||||
static const uint32_t TC2_STATUS_MASK = 0x300;
|
||||
static const uint32_t TC3_STATUS_MASK = 0xC00;
|
||||
static const uint32_t TC4_STATUS_MASK = 0x30000;
|
||||
static const uint32_t TC5_STATUS_MASK = 0xc00000;
|
||||
// Lock register set to 1 when start sequence has been found (CLTU is beeing processed)
|
||||
static const uint32_t LOCK_MASK = 0xc00000;
|
||||
|
||||
static const uint32_t TC_CHANNEL_INACTIVE = 0x0;
|
||||
static const uint32_t TC_CHANNEL_ACTIVE = 0x1;
|
||||
static const uint32_t TC_CHANNEL_TIMEDOUT = 0x2;
|
||||
static const uint32_t TC0_STATUS_POS = 0;
|
||||
static const uint32_t TC1_STATUS_POS = 2;
|
||||
static const uint32_t TC2_STATUS_POS = 4;
|
||||
static const uint32_t TC3_STATUS_POS = 6;
|
||||
static const uint32_t TC4_STATUS_POS = 8;
|
||||
static const uint32_t TC5_STATUS_POS = 10;
|
||||
// Lock register set to 1 when start sequence has been found (CLTU is beeing processed)
|
||||
static const uint32_t LOCK_POS = 12;
|
||||
|
||||
static const uint32_t TC0_STATUS_MASK = 0x3;
|
||||
static const uint32_t TC1_STATUS_MASK = 0xC;
|
||||
static const uint32_t TC2_STATUS_MASK = 0x300;
|
||||
static const uint32_t TC3_STATUS_MASK = 0xC00;
|
||||
static const uint32_t TC4_STATUS_MASK = 0x30000;
|
||||
static const uint32_t TC5_STATUS_MASK = 0xc00000;
|
||||
// Lock register set to 1 when start sequence has been found (CLTU is beeing processed)
|
||||
static const uint32_t LOCK_MASK = 0xc00000;
|
||||
|
||||
static const uint32_t TC0_STATUS_POS = 0;
|
||||
static const uint32_t TC1_STATUS_POS = 2;
|
||||
static const uint32_t TC2_STATUS_POS = 4;
|
||||
static const uint32_t TC3_STATUS_POS = 6;
|
||||
static const uint32_t TC4_STATUS_POS = 8;
|
||||
static const uint32_t TC5_STATUS_POS = 10;
|
||||
// Lock register set to 1 when start sequence has been found (CLTU is beeing processed)
|
||||
static const uint32_t LOCK_POS = 12;
|
||||
|
||||
/**
|
||||
* UIO is 4 byte aligned. Thus offset is calculated with "true offset" / 4
|
||||
* Example: PDEC_FAR = 0x2840 => Offset in virtual address space is 0xA10
|
||||
*/
|
||||
static const uint32_t PDEC_FAR_OFFSET = 0xA10;
|
||||
static const uint32_t PDEC_CLCW_OFFSET = 0xA12;
|
||||
static const uint32_t PDEC_BFREE_OFFSET = 0xA24;
|
||||
static const uint32_t PDEC_BPTR_OFFSET = 0xA25;
|
||||
static const uint32_t PDEC_SLEN_OFFSET = 0xA26;
|
||||
static const uint32_t PDEC_MON_OFFSET = 0xA27;
|
||||
/**
|
||||
* UIO is 4 byte aligned. Thus offset is calculated with "true offset" / 4
|
||||
* Example: PDEC_FAR = 0x2840 => Offset in virtual address space is 0xA10
|
||||
*/
|
||||
static const uint32_t PDEC_FAR_OFFSET = 0xA10;
|
||||
static const uint32_t PDEC_CLCW_OFFSET = 0xA12;
|
||||
static const uint32_t PDEC_BFREE_OFFSET = 0xA24;
|
||||
static const uint32_t PDEC_BPTR_OFFSET = 0xA25;
|
||||
static const uint32_t PDEC_SLEN_OFFSET = 0xA26;
|
||||
static const uint32_t PDEC_MON_OFFSET = 0xA27;
|
||||
|
||||
#if BOARD_TE0720 == 1
|
||||
static const int CONFIG_MEMORY_MAP_SIZE = 0x400;
|
||||
static const int RAM_MAP_SIZE = 0x4000;
|
||||
static const int REGISTER_MAP_SIZE = 0x10000;
|
||||
static const int CONFIG_MEMORY_MAP_SIZE = 0x400;
|
||||
static const int RAM_MAP_SIZE = 0x4000;
|
||||
static const int REGISTER_MAP_SIZE = 0x10000;
|
||||
#else
|
||||
static const int CONFIG_MEMORY_MAP_SIZE = 0x400;
|
||||
static const int RAM_MAP_SIZE = 0x4000;
|
||||
static const int REGISTER_MAP_SIZE = 0x4000;
|
||||
static const int CONFIG_MEMORY_MAP_SIZE = 0x400;
|
||||
static const int RAM_MAP_SIZE = 0x4000;
|
||||
static const int REGISTER_MAP_SIZE = 0x4000;
|
||||
#endif /* BOARD_TE0720 == 1 */
|
||||
|
||||
// 0x200 / 4 = 0x80
|
||||
static const uint32_t FRAME_HEADER_OFFSET = 0x80;
|
||||
// 0x200 / 4 = 0x80
|
||||
static const uint32_t FRAME_HEADER_OFFSET = 0x80;
|
||||
|
||||
static const size_t MAX_TC_SEGMENT_SIZE = 1017;
|
||||
static const uint8_t MAP_ID_MASK = 0x3F;
|
||||
static const size_t MAX_TC_SEGMENT_SIZE = 1017;
|
||||
static const uint8_t MAP_ID_MASK = 0x3F;
|
||||
|
||||
#if BOARD_TE0720 == 1
|
||||
static const uint32_t PHYSICAL_RAM_BASE_ADDRESS = 0x32000000;
|
||||
static const uint32_t PHYSICAL_RAM_BASE_ADDRESS = 0x32000000;
|
||||
#else
|
||||
static const uint32_t PHYSICAL_RAM_BASE_ADDRESS = 0x26000000;
|
||||
static const uint32_t PHYSICAL_RAM_BASE_ADDRESS = 0x26000000;
|
||||
#endif
|
||||
|
||||
static const uint32_t MAP_ADDR_LUT_OFFSET = 0xA0;
|
||||
static const uint32_t MAP_CLK_FREQ_OFFSET = 0x90;
|
||||
static const uint32_t MAP_ADDR_LUT_OFFSET = 0xA0;
|
||||
static const uint32_t MAP_CLK_FREQ_OFFSET = 0x90;
|
||||
|
||||
static const uint8_t MAX_MAP_ADDR = 63;
|
||||
// Writing this to the map address in the look up table will invalidate a MAP ID.
|
||||
static const uint8_t NO_DESTINATION = 0;
|
||||
static const uint8_t VALID_POSITION = 6;
|
||||
static const uint8_t PARITY_POSITION = 7;
|
||||
static const uint8_t MAX_MAP_ADDR = 63;
|
||||
// Writing this to the map address in the look up table will invalidate a MAP ID.
|
||||
static const uint8_t NO_DESTINATION = 0;
|
||||
static const uint8_t VALID_POSITION = 6;
|
||||
static const uint8_t PARITY_POSITION = 7;
|
||||
|
||||
// Expected value stored in FAR register after reset
|
||||
static const uint32_t FAR_RESET = 0x7FE0;
|
||||
// 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 TC_SEGMENT_LEN = 1017;
|
||||
|
||||
static const uint32_t NO_RF_MASK = 0x8000;
|
||||
static const uint32_t NO_BITLOCK_MASK = 0x4000;
|
||||
static const uint32_t NO_RF_MASK = 0x8000;
|
||||
static const uint32_t NO_BITLOCK_MASK = 0x4000;
|
||||
|
||||
/**
|
||||
* TCs with map addresses (also know as Map IDs) assigned to this channel will be stored in
|
||||
* the PDEC memory.
|
||||
*/
|
||||
static const uint8_t PM_BUFFER = 7;
|
||||
/**
|
||||
* TCs with map addresses (also know as Map IDs) assigned to this channel will be stored in
|
||||
* the PDEC memory.
|
||||
*/
|
||||
static const uint8_t PM_BUFFER = 7;
|
||||
|
||||
// MAP clock frequency. Must be a value between 1 and 13 otherwise the TC segment will be
|
||||
// discarded
|
||||
static const uint8_t MAP_CLK_FREQ = 2;
|
||||
// MAP clock frequency. Must be a value between 1 and 13 otherwise the TC segment will be
|
||||
// discarded
|
||||
static const uint8_t MAP_CLK_FREQ = 2;
|
||||
|
||||
enum class FrameAna_t: uint8_t {
|
||||
ABANDONED_CLTU,
|
||||
FRAME_DIRTY,
|
||||
FRAME_ILLEGAL,
|
||||
FRAME_ILLEGAL_MULTI_REASON,
|
||||
AD_DISCARDED_LOCKOUT,
|
||||
AD_DISCARDED_WAIT,
|
||||
AD_DISCARDED_NS_VR,
|
||||
FRAME_ACCEPTED
|
||||
};
|
||||
enum class FrameAna_t : uint8_t {
|
||||
ABANDONED_CLTU,
|
||||
FRAME_DIRTY,
|
||||
FRAME_ILLEGAL,
|
||||
FRAME_ILLEGAL_MULTI_REASON,
|
||||
AD_DISCARDED_LOCKOUT,
|
||||
AD_DISCARDED_WAIT,
|
||||
AD_DISCARDED_NS_VR,
|
||||
FRAME_ACCEPTED
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
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
|
||||
};
|
||||
|
||||
enum class State: uint8_t {
|
||||
INIT,
|
||||
RUNNING,
|
||||
WAIT_FOR_RECOVERY
|
||||
};
|
||||
enum class State : uint8_t { INIT, RUNNING, WAIT_FOR_RECOVERY };
|
||||
|
||||
/**
|
||||
* @brief Reads and handles messages stored in the commandQueue
|
||||
*/
|
||||
void readCommandQueue(void);
|
||||
/**
|
||||
* @brief Reads and handles messages stored in the commandQueue
|
||||
*/
|
||||
void readCommandQueue(void);
|
||||
|
||||
/**
|
||||
* @brief Opens UIO device assigned to AXI to AHB converter giving access to the PDEC
|
||||
* registers. The register base address will be mapped into the virtual address space.
|
||||
*/
|
||||
ReturnValue_t getRegisterAddress();
|
||||
/**
|
||||
* @brief Opens UIO device assigned to AXI to AHB converter giving access to the PDEC
|
||||
* registers. The register base address will be mapped into the virtual address space.
|
||||
*/
|
||||
ReturnValue_t getRegisterAddress();
|
||||
|
||||
/**
|
||||
* @brief Opens UIO device assigned to the base address of the PDEC memory space and maps the
|
||||
* physical address into the virtual address space.
|
||||
*/
|
||||
ReturnValue_t getConfigMemoryBaseAddress();
|
||||
/**
|
||||
* @brief Opens UIO device assigned to the base address of the PDEC memory space and maps the
|
||||
* physical address into the virtual address space.
|
||||
*/
|
||||
ReturnValue_t getConfigMemoryBaseAddress();
|
||||
|
||||
/**
|
||||
* @brief Opens UIO device assigned to the RAM section of the PDEC IP core memory map.
|
||||
*
|
||||
* @details A received TC segment will be written to this memory area.
|
||||
*/
|
||||
ReturnValue_t getRamBaseAddress();
|
||||
/**
|
||||
* @brief Opens UIO device assigned to the RAM section of the PDEC IP core memory map.
|
||||
*
|
||||
* @details A received TC segment will be written to this memory area.
|
||||
*/
|
||||
ReturnValue_t getRamBaseAddress();
|
||||
|
||||
/**
|
||||
* @brief This functions writes the configuration parameters to the configuration
|
||||
* section of the PDEC.
|
||||
*/
|
||||
void writePdecConfig();
|
||||
/**
|
||||
* @brief This functions writes the configuration parameters to the configuration
|
||||
* section of the PDEC.
|
||||
*/
|
||||
void writePdecConfig();
|
||||
|
||||
/**
|
||||
* @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 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();
|
||||
/**
|
||||
* @brief Releases the PDEC from reset state. PDEC will start with loading the written
|
||||
* configuration parameters.
|
||||
*/
|
||||
ReturnValue_t releasePdec();
|
||||
|
||||
/**
|
||||
* @brief Reads the FAR register and checks if a new TC has been received.
|
||||
*/
|
||||
bool newTcReceived();
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
void checkLocks();
|
||||
/**
|
||||
* @brief Checks if carrier lock or bit lock has been detected and triggers appropriate
|
||||
* event.
|
||||
*/
|
||||
void checkLocks();
|
||||
|
||||
/**
|
||||
* @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 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 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 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 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 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 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 This functions calculates the odd parity of the bits in number.
|
||||
*
|
||||
* @param number The number from which to calculate the odd parity.
|
||||
*/
|
||||
uint8_t getOddParity(uint8_t number);
|
||||
/**
|
||||
* @brief This functions calculates the odd parity of the bits in number.
|
||||
*
|
||||
* @param number The number from which to calculate the odd parity.
|
||||
*/
|
||||
uint8_t getOddParity(uint8_t number);
|
||||
|
||||
/**
|
||||
* brief Returns the 32-bit wide communication link control word (CLCW)
|
||||
*/
|
||||
uint32_t getClcw();
|
||||
/**
|
||||
* 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 Returns the PDEC monitor register content
|
||||
*
|
||||
*/
|
||||
uint32_t getPdecMon();
|
||||
|
||||
/**
|
||||
* @brief Reads and prints the CLCW. Can be useful for debugging.
|
||||
*/
|
||||
void printClcw();
|
||||
/**
|
||||
* @brief Reads and prints the CLCW. Can be useful for debugging.
|
||||
*/
|
||||
void printClcw();
|
||||
|
||||
/**
|
||||
* @brief Prints monitor register information to debug console.
|
||||
*/
|
||||
void printPdecMon();
|
||||
/**
|
||||
* @brief Prints monitor register information to debug console.
|
||||
*/
|
||||
void printPdecMon();
|
||||
|
||||
std::string getMonStatusString(uint32_t status);
|
||||
std::string getMonStatusString(uint32_t status);
|
||||
|
||||
object_id_t tcDestinationId;
|
||||
object_id_t tcDestinationId;
|
||||
|
||||
AcceptsTelecommandsIF* tcDestination = nullptr;
|
||||
AcceptsTelecommandsIF* tcDestination = nullptr;
|
||||
|
||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* 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;
|
||||
|
||||
// UIO device file giving access to the PDEC configuration memory section
|
||||
std::string uioConfigMemory;
|
||||
// UIO device file giving access to the PDEC configuration memory section
|
||||
std::string uioConfigMemory;
|
||||
|
||||
// UIO device file giving access to the PDEC RAM section
|
||||
std::string uioRamMemory;
|
||||
// UIO device file giving access to the PDEC RAM section
|
||||
std::string uioRamMemory;
|
||||
|
||||
// UIO device file giving access to the PDEC register space
|
||||
std::string uioRegisters;
|
||||
// UIO device file giving access to the PDEC register space
|
||||
std::string uioRegisters;
|
||||
|
||||
ActionHelper actionHelper;
|
||||
ActionHelper actionHelper;
|
||||
|
||||
StorageManagerIF* tcStore = nullptr;
|
||||
StorageManagerIF* tcStore = nullptr;
|
||||
|
||||
MessageQueueIF* commandQueue = nullptr;
|
||||
MessageQueueIF* commandQueue = nullptr;
|
||||
|
||||
State state = State::INIT;
|
||||
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;
|
||||
/**
|
||||
* 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;
|
||||
uint32_t* ramBaseAddress = nullptr;
|
||||
|
||||
// Pointer pointing to base address of register space
|
||||
uint32_t* registerBaseAddress = nullptr;
|
||||
// Pointer pointing to base address of register space
|
||||
uint32_t* registerBaseAddress = nullptr;
|
||||
|
||||
uint32_t pdecFar = 0;
|
||||
uint32_t pdecFar = 0;
|
||||
|
||||
uint8_t tcSegment[TC_SEGMENT_LEN];
|
||||
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;
|
||||
// Used to check carrier and bit lock changes (default set to no rf and no bitlock)
|
||||
uint32_t lastClcw = 0xC000;
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_PDECHANDLER_H_ */
|
||||
|
@ -1,72 +1,69 @@
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <linux/obc/Ptme.h>
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "PtmeConfig.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
Ptme::Ptme(object_id_t objectId): SystemObject(objectId) {
|
||||
}
|
||||
Ptme::Ptme(object_id_t objectId) : SystemObject(objectId) {}
|
||||
|
||||
Ptme::~Ptme() {
|
||||
}
|
||||
Ptme::~Ptme() {}
|
||||
|
||||
ReturnValue_t Ptme::initialize() {
|
||||
int fd = open(PtmeConfig::UIO_DEVICE_FILE, O_RDWR);
|
||||
if (fd < 1) {
|
||||
sif::warning << "Ptme::initialize: Invalid UIO device file" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
int fd = open(PtmeConfig::UIO_DEVICE_FILE, O_RDWR);
|
||||
if (fd < 1) {
|
||||
sif::warning << "Ptme::initialize: Invalid UIO device file" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
/**
|
||||
* Map uio device in virtual address space
|
||||
* PROT_WRITE: Map uio device in writable only mode
|
||||
*/
|
||||
ptmeBaseAddress = static_cast<uint32_t*>(mmap(NULL, MAP_SIZE, PROT_WRITE, MAP_SHARED, fd, 0));
|
||||
|
||||
/**
|
||||
* Map uio device in virtual address space
|
||||
* PROT_WRITE: Map uio device in writable only mode
|
||||
*/
|
||||
ptmeBaseAddress = static_cast<uint32_t*>(mmap(NULL, MAP_SIZE, PROT_WRITE,
|
||||
MAP_SHARED, fd, 0));
|
||||
if (ptmeBaseAddress == MAP_FAILED) {
|
||||
sif::error << "Ptme::initialize: Failed to map uio address" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
if (ptmeBaseAddress == MAP_FAILED) {
|
||||
sif::error << "Ptme::initialize: Failed to map uio address" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
VcInterfaceMapIter iter;
|
||||
for (iter = vcInterfaceMap.begin(); iter != vcInterfaceMap.end(); iter++) {
|
||||
iter->second->setRegisterAddress(ptmeBaseAddress);
|
||||
}
|
||||
|
||||
VcInterfaceMapIter iter;
|
||||
for (iter = vcInterfaceMap.begin(); iter != vcInterfaceMap.end(); iter++) {
|
||||
iter->second->setRegisterAddress(ptmeBaseAddress);
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t * data, size_t size) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId);
|
||||
if (vcInterfaceMapIter == vcInterfaceMap.end()) {
|
||||
sif::warning << "Ptme::writeToVc: No virtual channel interface found for the virtual "
|
||||
"channel with id " << static_cast<unsigned int>(vcId) << std::endl;
|
||||
return UNKNOWN_VC_ID;
|
||||
}
|
||||
result = vcInterfaceMapIter->second->write(data, size);
|
||||
return result;
|
||||
ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t* data, size_t size) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId);
|
||||
if (vcInterfaceMapIter == vcInterfaceMap.end()) {
|
||||
sif::warning << "Ptme::writeToVc: No virtual channel interface found for the virtual "
|
||||
"channel with id "
|
||||
<< static_cast<unsigned int>(vcId) << std::endl;
|
||||
return UNKNOWN_VC_ID;
|
||||
}
|
||||
result = vcInterfaceMapIter->second->write(data, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Ptme::addVcInterface(VcId_t vcId, VcInterfaceIF* vc) {
|
||||
if (vcId > common::NUMBER_OF_VIRTUAL_CHANNELS) {
|
||||
sif::warning << "Ptme::addVcInterface: Invalid virtual channel ID" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (vcId > common::NUMBER_OF_VIRTUAL_CHANNELS) {
|
||||
sif::warning << "Ptme::addVcInterface: Invalid virtual channel ID" << std::endl;
|
||||
return;
|
||||
}
|
||||
if (vc == nullptr) {
|
||||
sif::warning << "Ptme::addVcInterface: Invalid virtual channel interface" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (vc == nullptr) {
|
||||
sif::warning << "Ptme::addVcInterface: Invalid virtual channel interface" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
auto status = vcInterfaceMap.emplace(vcId, vc);
|
||||
if (status.second == false) {
|
||||
sif::warning << "Ptme::addVcInterface: Failed to add virtual channel interface to "
|
||||
"virtual channel map" << std::endl;
|
||||
return;
|
||||
}
|
||||
auto status = vcInterfaceMap.emplace(vcId, vc);
|
||||
if (status.second == false) {
|
||||
sif::warning << "Ptme::addVcInterface: Failed to add virtual channel interface to "
|
||||
"virtual channel map"
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
116
linux/obc/Ptme.h
116
linux/obc/Ptme.h
@ -1,91 +1,87 @@
|
||||
#ifndef LINUX_OBC_PTME_H_
|
||||
#define LINUX_OBC_PTME_H_
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "linux/obc/PtmeIF.h"
|
||||
#include "linux/obc/VcInterfaceIF.h"
|
||||
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
|
||||
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "linux/obc/PtmeIF.h"
|
||||
#include "linux/obc/VcInterfaceIF.h"
|
||||
|
||||
/**
|
||||
* @brief This class handles the interfacing to the telemetry (PTME) IP core responsible for the
|
||||
* encoding of telemetry packets according to the CCSDS standards CCSDS 131.0-B-3 (TM Synchro-
|
||||
* nization and channel coding) and CCSDS 132.0-B-2 (TM Space Data Link Protocoll).
|
||||
* The IP cores are implemented on the programmable logic and are accessible through the
|
||||
* linux UIO driver.
|
||||
* encoding of telemetry packets according to the CCSDS standards CCSDS 131.0-B-3 (TM
|
||||
* Synchro- nization and channel coding) and CCSDS 132.0-B-2 (TM Space Data Link Protocoll). The IP
|
||||
* cores are implemented on the programmable logic and are accessible through the linux UIO driver.
|
||||
*/
|
||||
class Ptme : public PtmeIF,
|
||||
public SystemObject,
|
||||
public HasReturnvaluesIF {
|
||||
public:
|
||||
class Ptme : public PtmeIF, public SystemObject, public HasReturnvaluesIF {
|
||||
public:
|
||||
using VcId_t = uint8_t;
|
||||
|
||||
using VcId_t = uint8_t;
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param objectId
|
||||
*/
|
||||
Ptme(object_id_t objectId);
|
||||
virtual ~Ptme();
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param objectId
|
||||
*/
|
||||
Ptme(object_id_t objectId);
|
||||
virtual ~Ptme();
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) override;
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) override;
|
||||
/**
|
||||
* @brief This function adds the reference to a virtual channel interface to the vcInterface
|
||||
* map.
|
||||
*/
|
||||
void addVcInterface(VcId_t vcId, VcInterfaceIF* vc);
|
||||
|
||||
/**
|
||||
* @brief This function adds the reference to a virtual channel interface to the vcInterface
|
||||
* map.
|
||||
*/
|
||||
void addVcInterface(VcId_t vcId, VcInterfaceIF* vc);
|
||||
private:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::PTME;
|
||||
|
||||
private:
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::PTME;
|
||||
|
||||
static const ReturnValue_t UNKNOWN_VC_ID = MAKE_RETURN_CODE(0xA0);
|
||||
static const ReturnValue_t UNKNOWN_VC_ID = MAKE_RETURN_CODE(0xA0);
|
||||
|
||||
#if BOARD_TE0720 == 1
|
||||
/** Size of mapped address space */
|
||||
static const int MAP_SIZE = 0x40000;
|
||||
/** Size of mapped address space */
|
||||
static const int MAP_SIZE = 0x40000;
|
||||
#else
|
||||
/** Size of mapped address space */
|
||||
static const int MAP_SIZE = 0x40000;
|
||||
/** Size of mapped address space */
|
||||
static const int MAP_SIZE = 0x40000;
|
||||
#endif /* BOARD_TE0720 == 1 */
|
||||
|
||||
/**
|
||||
* Configuration bits:
|
||||
* bit[1:0]: Size of data (1,2,3 or 4 bytes). 1 Byte <=> b00
|
||||
* bit[2]: Set this bit to 1 to abort a transfered packet
|
||||
* bit[3]: Signals to PTME the start of a new telemetry packet
|
||||
*/
|
||||
static const uint32_t PTME_CONFIG_START = 0x8;
|
||||
/**
|
||||
* Configuration bits:
|
||||
* bit[1:0]: Size of data (1,2,3 or 4 bytes). 1 Byte <=> b00
|
||||
* bit[2]: Set this bit to 1 to abort a transfered packet
|
||||
* bit[3]: Signals to PTME the start of a new telemetry packet
|
||||
*/
|
||||
static const uint32_t PTME_CONFIG_START = 0x8;
|
||||
|
||||
/**
|
||||
* Writing this word to the ptme base address signals to the PTME that a complete tm packet has
|
||||
* been transferred.
|
||||
*/
|
||||
static const uint32_t PTME_CONFIG_END = 0x0;
|
||||
/**
|
||||
* Writing this word to the ptme base address signals to the PTME that a complete tm packet has
|
||||
* been transferred.
|
||||
*/
|
||||
static const uint32_t PTME_CONFIG_END = 0x0;
|
||||
|
||||
/**
|
||||
* Writing to this offset within the PTME memory space will insert data for encoding to the
|
||||
* PTME IP core.
|
||||
* The address offset is 0x400 (= 4 * 256)
|
||||
*/
|
||||
static const int PTME_DATA_REG_OFFSET = 256;
|
||||
/**
|
||||
* Writing to this offset within the PTME memory space will insert data for encoding to the
|
||||
* PTME IP core.
|
||||
* The address offset is 0x400 (= 4 * 256)
|
||||
*/
|
||||
static const int PTME_DATA_REG_OFFSET = 256;
|
||||
|
||||
/** The file descriptor of the UIO driver */
|
||||
int fd = 0;
|
||||
/** The file descriptor of the UIO driver */
|
||||
int fd = 0;
|
||||
|
||||
uint32_t* ptmeBaseAddress = nullptr;
|
||||
uint32_t* ptmeBaseAddress = nullptr;
|
||||
|
||||
using VcInterfaceMap = std::unordered_map<VcId_t, VcInterfaceIF*>;
|
||||
using VcInterfaceMapIter = VcInterfaceMap::iterator;
|
||||
using VcInterfaceMap = std::unordered_map<VcId_t, VcInterfaceIF*>;
|
||||
using VcInterfaceMapIter = VcInterfaceMap::iterator;
|
||||
|
||||
VcInterfaceMap vcInterfaceMap;
|
||||
VcInterfaceMap vcInterfaceMap;
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_PTME_H_ */
|
||||
|
@ -1,9 +1,10 @@
|
||||
#ifndef LINUX_OBC_PTMECONFIG_H_
|
||||
#define LINUX_OBC_PTMECONFIG_H_
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include <cstring>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
/**
|
||||
* @brief PTME specific configuration parameters derived from FPGA design and device tree.
|
||||
@ -11,20 +12,20 @@
|
||||
* @author J. Meier
|
||||
*/
|
||||
namespace PtmeConfig {
|
||||
/**
|
||||
* Offset of virtual channels mapped into address space
|
||||
* 0x10000 = (0x4000 * 4)
|
||||
*/
|
||||
static const uint32_t VC0_OFFSETT = 0;
|
||||
static const uint32_t VC1_OFFSETT = 0x4000;
|
||||
static const uint32_t VC2_OFFSETT = 0x8000;
|
||||
static const uint32_t VC3_OFFSETT = 0xC000;
|
||||
/**
|
||||
* Offset of virtual channels mapped into address space
|
||||
* 0x10000 = (0x4000 * 4)
|
||||
*/
|
||||
static const uint32_t VC0_OFFSETT = 0;
|
||||
static const uint32_t VC1_OFFSETT = 0x4000;
|
||||
static const uint32_t VC2_OFFSETT = 0x8000;
|
||||
static const uint32_t VC3_OFFSETT = 0xC000;
|
||||
#if BOARD_TE0720 == 0
|
||||
static const char UIO_DEVICE_FILE[] = "/dev/uio1";
|
||||
static const char UIO_DEVICE_FILE[] = "/dev/uio1";
|
||||
#else
|
||||
static const char UIO_DEVICE_FILE[] = "/dev/uio1";
|
||||
static const char UIO_DEVICE_FILE[] = "/dev/uio1";
|
||||
#endif
|
||||
|
||||
};
|
||||
}; // namespace PtmeConfig
|
||||
|
||||
#endif /* LINUX_OBC_PTMECONFIG_H_ */
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief Interface class for managing the PTME IP Core implemented in the programmable logic.
|
||||
*
|
||||
@ -12,17 +11,17 @@
|
||||
* @author J. Meier
|
||||
*/
|
||||
class PtmeIF {
|
||||
public:
|
||||
virtual ~PtmeIF(){};
|
||||
public:
|
||||
virtual ~PtmeIF(){};
|
||||
|
||||
/**
|
||||
* @brief Implements to function to write to a specific virtual channel.
|
||||
*
|
||||
* @param vcId Virtual channel to write to
|
||||
* @param data Pointer to buffer holding the data to write
|
||||
* @param size Number of bytes to write
|
||||
*/
|
||||
virtual ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) = 0;
|
||||
/**
|
||||
* @brief Implements to function to write to a specific virtual channel.
|
||||
*
|
||||
* @param vcId Virtual channel to write to
|
||||
* @param data Pointer to buffer holding the data to write
|
||||
* @param size Number of bytes to write
|
||||
*/
|
||||
virtual ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) = 0;
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_PTMEIF_H_ */
|
||||
|
@ -1,27 +1,25 @@
|
||||
#include "PtmeRateSetter.h"
|
||||
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
PtmeRateSetter::PtmeRateSetter(gpioId_t bitrateSel, GpioIF* gpioif) :
|
||||
bitrateSel(bitrateSel), gpioif(gpioif) {
|
||||
}
|
||||
PtmeRateSetter::PtmeRateSetter(gpioId_t bitrateSel, GpioIF* gpioif)
|
||||
: bitrateSel(bitrateSel), gpioif(gpioif) {}
|
||||
|
||||
PtmeRateSetter::~PtmeRateSetter() {
|
||||
}
|
||||
PtmeRateSetter::~PtmeRateSetter() {}
|
||||
|
||||
ReturnValue_t PtmeRateSetter::setRate(BitRates rate) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
switch(rate) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
switch (rate) {
|
||||
case RATE_2000KHZ:
|
||||
result = gpioif->pullHigh(bitrateSel);
|
||||
break;
|
||||
result = gpioif->pullHigh(bitrateSel);
|
||||
break;
|
||||
case RATE_400KHZ:
|
||||
result = gpioif->pullLow(bitrateSel);
|
||||
break;
|
||||
result = gpioif->pullLow(bitrateSel);
|
||||
break;
|
||||
default:
|
||||
sif::debug << "PtmeRateSetter::setRate: Invalid rate" << std::endl;
|
||||
result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
sif::debug << "PtmeRateSetter::setRate: Invalid rate" << std::endl;
|
||||
result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
#define LINUX_OBC_PTMERATESETTER_H_
|
||||
|
||||
#include "TxRateSetterIF.h"
|
||||
#include "fsfw_hal/common/gpio/gpioDefinitions.h"
|
||||
#include "fsfw_hal/common/gpio/GpioIF.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw_hal/common/gpio/GpioIF.h"
|
||||
#include "fsfw_hal/common/gpio/gpioDefinitions.h"
|
||||
|
||||
/**
|
||||
* @brief Class to set the downlink bit rate by using the cadu_rate_switcher implemented in
|
||||
@ -15,26 +15,24 @@
|
||||
*
|
||||
* @author J. Meier
|
||||
*/
|
||||
class PtmeRateSetter: public TxRateSetterIF {
|
||||
public:
|
||||
class PtmeRateSetter : public TxRateSetterIF {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param bitrateSel GPIO ID of the GPIO connected to the bitrate_sel input of the
|
||||
* cadu_rate_switcher.
|
||||
* @param gpioif GPIO interface to drive the bitrateSel GPIO
|
||||
*/
|
||||
PtmeRateSetter(gpioId_t bitrateSel, GpioIF* gpioif);
|
||||
virtual ~PtmeRateSetter();
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param bitrateSel GPIO ID of the GPIO connected to the bitrate_sel input of the
|
||||
* cadu_rate_switcher.
|
||||
* @param gpioif GPIO interface to drive the bitrateSel GPIO
|
||||
*/
|
||||
PtmeRateSetter(gpioId_t bitrateSel, GpioIF* gpioif);
|
||||
virtual ~PtmeRateSetter();
|
||||
virtual ReturnValue_t setRate(BitRates rate);
|
||||
|
||||
virtual ReturnValue_t setRate(BitRates rate);
|
||||
private:
|
||||
gpioId_t bitrateSel = gpio::NO_GPIO;
|
||||
|
||||
private:
|
||||
|
||||
gpioId_t bitrateSel = gpio::NO_GPIO;
|
||||
|
||||
GpioIF* gpioif = nullptr;
|
||||
GpioIF* gpioif = nullptr;
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_PTMERATESETTER_H_ */
|
||||
|
@ -3,10 +3,7 @@
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
enum BitRates : uint32_t {
|
||||
RATE_2000KHZ,
|
||||
RATE_400KHZ
|
||||
};
|
||||
enum BitRates : uint32_t { RATE_2000KHZ, RATE_400KHZ };
|
||||
|
||||
/**
|
||||
* @brief Abstract class for objects implementing the functionality to switch the
|
||||
@ -15,11 +12,11 @@ enum BitRates : uint32_t {
|
||||
* @author J. Meier
|
||||
*/
|
||||
class TxRateSetterIF {
|
||||
public:
|
||||
TxRateSetterIF() {};
|
||||
virtual ~TxRateSetterIF() {};
|
||||
public:
|
||||
TxRateSetterIF(){};
|
||||
virtual ~TxRateSetterIF(){};
|
||||
|
||||
virtual ReturnValue_t setRate(BitRates bitRate) = 0;
|
||||
virtual ReturnValue_t setRate(BitRates bitRate) = 0;
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_TXRATESETTERIF_H_ */
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define LINUX_OBC_VCINTERFACEIF_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
/**
|
||||
@ -11,19 +12,19 @@
|
||||
* @author J. Meier
|
||||
*/
|
||||
class VcInterfaceIF {
|
||||
public:
|
||||
virtual ~VcInterfaceIF(){};
|
||||
public:
|
||||
virtual ~VcInterfaceIF(){};
|
||||
|
||||
/**
|
||||
* @brief Implememts the functionality to write data in the virtual channel of the PTME IP
|
||||
* Core.
|
||||
*
|
||||
* @param data Pointer to buffer holding the data to write
|
||||
* @param size Number of bytes to write
|
||||
*/
|
||||
virtual ReturnValue_t write(const uint8_t* data, size_t size) = 0;
|
||||
/**
|
||||
* @brief Implememts the functionality to write data in the virtual channel of the PTME IP
|
||||
* Core.
|
||||
*
|
||||
* @param data Pointer to buffer holding the data to write
|
||||
* @param size Number of bytes to write
|
||||
*/
|
||||
virtual ReturnValue_t write(const uint8_t* data, size_t size) = 0;
|
||||
|
||||
virtual void setRegisterAddress(uint32_t* ptmeBaseAddress) = 0;
|
||||
virtual void setRegisterAddress(uint32_t* ptmeBaseAddress) = 0;
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_VCINTERFACEIF_H_ */
|
||||
|
Reference in New Issue
Block a user