diff --git a/README.md b/README.md
index 6ad16a87..7d27b092 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,7 @@
13. [Eclipse](#eclipse)
14. [Running the OBSW on a Raspberry Pi](#rpi)
15. [FSFW](#fsfw)
+16. [Coding Style](#coding-style)
# General information
@@ -1151,3 +1152,15 @@ git merge upstream/master
Alternatively, changes from other upstreams (forks) and branches can be merged like that
in the same way.
+
+# Coding Style
+* the formatting is based on the clang-format tools
+## Setting up eclipse auto-fromatter with clang-format
+1. Help → Install New Software → Add
+2. In location insert the link http://www.cppstyle.com/luna
+3. The software package CppStyle should now be available for installation
+4. On windows download the clang-formatting tools from https://llvm.org/builds/. On linux clang-format can be installed with the package manager.
+5. Navigate to Preferences → C/C++ → CppStyle
+6. Insert the path to the clang-format executable
+7. Under C/C++ → Code Style → Formatter, change the formatter to CppStyle (clang-format)
+8. Code can now be formatted with the clang tool by using the key combination Ctrl + Shift + f
\ No newline at end of file
diff --git a/bsp_q7s/boardconfig/busConf.h b/bsp_q7s/boardconfig/busConf.h
index e41ed093..3e8a4b49 100644
--- a/bsp_q7s/boardconfig/busConf.h
+++ b/bsp_q7s/boardconfig/busConf.h
@@ -17,6 +17,16 @@ static constexpr char UART_STAR_TRACKER_DEV[] = "/dev/ttyUL7";
static constexpr char UIO_PDEC_REGISTERS[] = "/dev/uio0";
static constexpr char UIO_PDEC_CONFIG_MEMORY[] = "/dev/uio2";
static constexpr char UIO_PDEC_RAM[] = "/dev/uio3";
+static constexpr char UIO_PTME[] = "/dev/uio1";
+static constexpr int MAP_ID_PTME_CONFIG = 3;
+
+namespace uiomapids {
+ static const int PTME_VC0 = 0;
+ static const int PTME_VC1 = 1;
+ static const int PTME_VC2 = 2;
+ static const int PTME_VC3 = 3;
+ static const int PTME_CONFIG = 4;
+}
namespace gpioNames {
static constexpr char GYRO_0_ADIS_CS[] = "gyro_0_adis_chip_select";
@@ -69,7 +79,6 @@ static constexpr char RS485_EN_TX_DATA[] = "tx_data_enable_ltc2872";
static constexpr char RS485_EN_RX_CLOCK[] = "rx_clock_enable_ltc2872";
static constexpr char RS485_EN_RX_DATA[] = "rx_data_enable_ltc2872";
static constexpr char PDEC_RESET[] = "pdec_reset";
-static constexpr char BIT_RATE_SEL[] = "bit_rate_sel";
} // namespace gpioNames
} // namespace q7s
diff --git a/bsp_q7s/core/InitMission.cpp b/bsp_q7s/core/InitMission.cpp
index a5b2b548..c7ae801c 100644
--- a/bsp_q7s/core/InitMission.cpp
+++ b/bsp_q7s/core/InitMission.cpp
@@ -115,12 +115,14 @@ void initmission::initTasks() {
}
#endif /* OBSW_USE_CCSDS_IP_CORE == 1 */
+#if OBSW_ADD_ACS_HANDLERS == 1
PeriodicTaskIF* acsCtrl = factory->createPeriodicTask(
"ACS_CTRL", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc);
result = acsCtrl->addComponent(objects::GPS_CONTROLLER);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("ACS_CTRL", objects::GPS_CONTROLLER);
}
+#endif /* OBSW_ADD_ACS_HANDLERS */
#if BOARD_TE0720 == 0
// FS task, task interval does not matter because it runs in permanent loop, priority low
diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp
index 6931b4df..1b82d206 100644
--- a/bsp_q7s/core/ObjectFactory.cpp
+++ b/bsp_q7s/core/ObjectFactory.cpp
@@ -81,6 +81,7 @@
#include
#include
#include
+#include
ResetArgs resetArgsGnss0;
ResetArgs resetArgsGnss1;
@@ -899,49 +900,50 @@ void ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF) {
GpioCookie* gpioCookiePtmeIp = new GpioCookie;
GpiodRegularByLineName* gpio = nullptr;
std::stringstream consumer;
- consumer << "0x" << std::hex << objects::PAPB_VC0;
+ consumer.str("PAPB VC0");
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC0, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_BUSY, gpio);
- consumer.str("");
- consumer << "0x" << std::hex << objects::PAPB_VC0;
+ consumer.str("PAPB VC0");
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC0, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_EMPTY, gpio);
- consumer.str("");
- consumer << "0x" << std::hex << objects::PAPB_VC1;
+ consumer.str("PAPB VC 1");
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC1, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_BUSY, gpio);
consumer.str("");
- consumer << "0x" << std::hex << objects::PAPB_VC1;
- gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC1, consumer.str());
+ consumer.str("PAPB VC 1");
gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_EMPTY, gpio);
consumer.str("");
- consumer << "0x" << std::hex << objects::PAPB_VC2;
+ consumer.str("PAPB VC 2");
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC2, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_BUSY, gpio);
consumer.str("");
- consumer << "0x" << std::hex << objects::PAPB_VC2;
+ consumer.str("PAPB VC 2");
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC2, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_EMPTY, gpio);
consumer.str("");
- consumer << "0x" << std::hex << objects::PAPB_VC3;
+ consumer.str("PAPB VC 3");
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC3, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_BUSY, gpio);
consumer.str("");
- consumer << "0x" << std::hex << objects::PAPB_VC3;
+ consumer.str("PAPB VC 3");
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC3, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_EMPTY, gpio);
gpioComIF->addGpios(gpioCookiePtmeIp);
// Creating virtual channel interfaces
- VcInterfaceIF* vc0 = new PapbVcInterface(objects::PAPB_VC0, gpioComIF, gpioIds::VC0_PAPB_BUSY,
- gpioIds::VC0_PAPB_EMPTY, PtmeConfig::VC0_OFFSETT);
- VcInterfaceIF* vc1 = new PapbVcInterface(objects::PAPB_VC1, gpioComIF, gpioIds::VC1_PAPB_BUSY,
- gpioIds::VC1_PAPB_EMPTY, PtmeConfig::VC1_OFFSETT);
- VcInterfaceIF* vc2 = new PapbVcInterface(objects::PAPB_VC2, gpioComIF, gpioIds::VC2_PAPB_BUSY,
- gpioIds::VC2_PAPB_EMPTY, PtmeConfig::VC2_OFFSETT);
- VcInterfaceIF* vc3 = new PapbVcInterface(objects::PAPB_VC3, gpioComIF, gpioIds::VC3_PAPB_BUSY,
- gpioIds::VC3_PAPB_EMPTY, PtmeConfig::VC3_OFFSETT);
+ VcInterfaceIF* vc0 =
+ new PapbVcInterface(gpioComIF, gpioIds::VC0_PAPB_BUSY, gpioIds::VC0_PAPB_EMPTY, q7s::UIO_PTME,
+ q7s::uiomapids::PTME_VC0);
+ VcInterfaceIF* vc1 =
+ new PapbVcInterface(gpioComIF, gpioIds::VC1_PAPB_BUSY, gpioIds::VC1_PAPB_EMPTY, q7s::UIO_PTME,
+ q7s::uiomapids::PTME_VC1);
+ VcInterfaceIF* vc2 =
+ new PapbVcInterface(gpioComIF, gpioIds::VC2_PAPB_BUSY, gpioIds::VC2_PAPB_EMPTY, q7s::UIO_PTME,
+ q7s::uiomapids::PTME_VC2);
+ VcInterfaceIF* vc3 =
+ new PapbVcInterface(gpioComIF, gpioIds::VC3_PAPB_BUSY, gpioIds::VC3_PAPB_EMPTY, q7s::UIO_PTME,
+ q7s::uiomapids::PTME_VC3);
// Creating ptme object and adding virtual channel interfaces
Ptme* ptme = new Ptme(objects::PTME);
@@ -950,17 +952,9 @@ void ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF) {
ptme->addVcInterface(ccsds::VC2, vc2);
ptme->addVcInterface(ccsds::VC3, vc3);
- GpioCookie* gpioCookieRateSetter = new GpioCookie;
- consumer.str("");
- consumer << "ptme rate setter";
- // Init to low -> default bit rate is low bit rate (200 kbps in downlink with syrlinks)
- gpio = new GpiodRegularByLineName(q7s::gpioNames::BIT_RATE_SEL, consumer.str(), gpio::DIR_OUT,
- gpio::LOW);
- gpioCookieRateSetter->addGpio(gpioIds::BIT_RATE_SEL, gpio);
- gpioComIF->addGpios(gpioCookieRateSetter);
-
- TxRateSetterIF* txRateSetterIF = new PtmeRateSetter(gpioIds::BIT_RATE_SEL, gpioComIF);
-
+ PtmeAxiConfig* ptmeAxiConfig =
+ new PtmeAxiConfig(objects::PTME_AXI_CONFIG, q7s::UIO_PTME, q7s::uiomapids::PTME_CONFIG);
+ TxRateSetterIF* txRateSetterIF = new PtmeRateSetter(objects::TX_RATE_SETTER, ptmeAxiConfig);
CCSDSHandler* ccsdsHandler = new CCSDSHandler(
objects::CCSDS_HANDLER, objects::PTME, objects::CCSDS_PACKET_DISTRIBUTOR, txRateSetterIF,
gpioComIF, gpioIds::RS485_EN_TX_CLOCK, gpioIds::RS485_EN_TX_DATA);
@@ -986,8 +980,7 @@ void ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF) {
gpioComIF->addGpios(gpioCookiePdec);
new PdecHandler(objects::PDEC_HANDLER, objects::CCSDS_HANDLER, gpioComIF, gpioIds::PDEC_RESET,
- std::string(q7s::UIO_PDEC_CONFIG_MEMORY), std::string(q7s::UIO_PDEC_RAM),
- std::string(q7s::UIO_PDEC_REGISTERS));
+ q7s::UIO_PDEC_CONFIG_MEMORY, q7s::UIO_PDEC_RAM, q7s::UIO_PDEC_REGISTERS);
#if BOARD_TE0720 == 0
GpioCookie* gpioRS485Chip = new GpioCookie;
diff --git a/common/config/commonClassIds.h b/common/config/commonClassIds.h
index cd90272d..ab8e06d5 100644
--- a/common/config/commonClassIds.h
+++ b/common/config/commonClassIds.h
@@ -24,6 +24,7 @@ enum commonClassIds: uint8_t {
PLOC_MEMORY_DUMPER, //PLMEMDUMP
PDEC_HANDLER, //PDEC
CCSDS_HANDLER, //CCSDS
+ RATE_SETTER, //RS
ARCSEC_JSON_BASE, //JSONBASE
NVM_PARAM_BASE, //NVMB
COMMON_CLASS_ID_END // [EXPORT] : [END]
diff --git a/common/config/commonObjects.h b/common/config/commonObjects.h
index 135259d6..99096ba4 100644
--- a/common/config/commonObjects.h
+++ b/common/config/commonObjects.h
@@ -12,11 +12,7 @@ enum commonObjects: uint32_t {
TMTC_POLLING_TASK = 0x50000400,
FILE_SYSTEM_HANDLER = 0x50000500,
PTME = 0x50000600,
- PAPB_VC0 = 0x50000700,
- PAPB_VC1 = 0x50000701,
- PAPB_VC2 = 0x50000702,
- PAPB_VC3 = 0x50000703,
- PDEC_HANDLER = 0x50000704,
+ PDEC_HANDLER = 0x50000700,
CCSDS_HANDLER = 0x50000800,
/* 0x43 ('C') for Controllers */
@@ -90,7 +86,9 @@ enum commonObjects: uint32_t {
PLOC_UPDATER = 0x44330000,
PLOC_MEMORY_DUMPER = 0x44330001,
- STR_HELPER = 0x44330002
+ STR_HELPER = 0x44330002,
+ PTME_AXI_CONFIG = 44330003,
+ TX_RATE_SETTER = 44330004
};
}
diff --git a/linux/obc/CMakeLists.txt b/linux/obc/CMakeLists.txt
index 4119624c..d59a1a5f 100644
--- a/linux/obc/CMakeLists.txt
+++ b/linux/obc/CMakeLists.txt
@@ -4,6 +4,7 @@ target_sources(${TARGET_NAME} PUBLIC
PdecHandler.cpp
PdecConfig.cpp
PtmeRateSetter.cpp
+ PtmeAxiConfig.cpp
)
diff --git a/linux/obc/PapbVcInterface.cpp b/linux/obc/PapbVcInterface.cpp
index f144306c..45358ee1 100644
--- a/linux/obc/PapbVcInterface.cpp
+++ b/linux/obc/PapbVcInterface.cpp
@@ -1,26 +1,26 @@
+#include
#include
-
#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),
+PapbVcInterface::PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId,
+ gpioId_t papbEmptyId, std::string uioFile, int mapNum)
+ : gpioComIF(gpioComIF),
papbBusyId(papbBusyId),
papbEmptyId(papbEmptyId),
- vcOffset(vcOffset) {}
+ uioFile(uioFile),
+ mapNum(mapNum) {}
PapbVcInterface::~PapbVcInterface() {}
-void PapbVcInterface::setRegisterAddress(uint32_t* ptmeBaseAddress) {
- vcBaseReg = ptmeBaseAddress + vcOffset;
+ReturnValue_t PapbVcInterface::initialize() {
+ UioMapper uioMapper(uioFile, mapNum);
+ return uioMapper.getMappedAdress(&vcBaseReg, UioMapper::Permissions::WRITE_ONLY);
}
ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
if (pollPapbBusySignal() == RETURN_OK) {
startPacketTransfer();
}
-
for (size_t idx = 0; idx < size; idx++) {
if (pollPapbBusySignal() == RETURN_OK) {
*(vcBaseReg + DATA_REG_OFFSET) = static_cast(*(data + idx));
@@ -30,7 +30,6 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
return RETURN_FAILED;
}
}
-
if (pollPapbBusySignal() == RETURN_OK) {
endPacketTransfer();
}
diff --git a/linux/obc/PapbVcInterface.h b/linux/obc/PapbVcInterface.h
index e7d03a70..d4df659e 100644
--- a/linux/obc/PapbVcInterface.h
+++ b/linux/obc/PapbVcInterface.h
@@ -3,9 +3,7 @@
#include
#include
-
#include "OBSWConfig.h"
-#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "linux/obc/VcInterfaceIF.h"
@@ -15,26 +13,27 @@
*
* @author J. Meier
*/
-class PapbVcInterface : public SystemObject, public VcInterfaceIF, public HasReturnvaluesIF {
+class PapbVcInterface : 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).
+ * @param uioFile UIO file providing access to the PAPB bus
+ * @param mapNum Map number of UIO map associated with this virtual channel
*/
- PapbVcInterface(object_id_t objectId, LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId,
- gpioId_t papbEmptyId, uint32_t vcOffset);
+ PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId, gpioId_t papbEmptyId,
+ std::string uioFile, int mapNum);
virtual ~PapbVcInterface();
ReturnValue_t write(const uint8_t* data, size_t size) override;
- void setRegisterAddress(uint32_t* ptmeBaseAddress) override;
+ ReturnValue_t initialize() override;
private:
static const uint8_t INTERFACE_ID = CLASS_ID::CCSDS_IP_CORE_BRIDGE;
@@ -69,6 +68,9 @@ class PapbVcInterface : public SystemObject, public VcInterfaceIF, public HasRet
/** High when external buffer memory of virtual channel is empty */
gpioId_t papbEmptyId = gpio::NO_GPIO;
+ std::string uioFile;
+ int mapNum = 0;
+
uint32_t* vcBaseReg = nullptr;
uint32_t vcOffset = 0;
diff --git a/linux/obc/PdecHandler.cpp b/linux/obc/PdecHandler.cpp
index a5ee98d6..7dfcfd66 100644
--- a/linux/obc/PdecHandler.cpp
+++ b/linux/obc/PdecHandler.cpp
@@ -1,16 +1,14 @@
-#include "PdecHandler.h"
-
#include
#include
-
#include
#include
-
#include "OBSWConfig.h"
+#include "PdecHandler.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
+#include "fsfw_hal/linux/uio/UioMapper.h"
PdecHandler::PdecHandler(object_id_t objectId, object_id_t tcDestinationId,
LinuxLibgpioIF* gpioComIF, gpioId_t pdecReset, std::string uioConfigMemory,
@@ -44,17 +42,18 @@ ReturnValue_t PdecHandler::initialize() {
ReturnValue_t result = RETURN_OK;
- result = getRegisterAddress();
+ UioMapper regMapper(uioRegisters);
+ result = regMapper.getMappedAdress(®isterBaseAddress, UioMapper::Permissions::READ_WRITE);
if (result != RETURN_OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
-
- result = getConfigMemoryBaseAddress();
+ UioMapper configMemMapper(uioConfigMemory);
+ result = configMemMapper.getMappedAdress(&memoryBaseAddress, UioMapper::Permissions::READ_WRITE);
if (result != RETURN_OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
-
- result = getRamBaseAddress();
+ UioMapper ramMapper(uioRamMemory);
+ result = ramMapper.getMappedAdress(&ramBaseAddress, UioMapper::Permissions::READ_WRITE);
if (result != RETURN_OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
@@ -76,55 +75,6 @@ ReturnValue_t PdecHandler::initialize() {
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;
- }
-
- registerBaseAddress = static_cast(
- 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;
- }
-
- 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;
- }
-
- memoryBaseAddress = static_cast(
- 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;
- }
-
- return RETURN_OK;
-}
-
-ReturnValue_t PdecHandler::getRamBaseAddress() {
- int fd = open(uioRamMemory.c_str(), O_RDWR);
-
- ramBaseAddress =
- static_cast(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;
-}
-
void PdecHandler::writePdecConfig() {
PdecConfig pdecConfig;
diff --git a/linux/obc/PdecHandler.h b/linux/obc/PdecHandler.h
index 2125800f..16a9abd4 100644
--- a/linux/obc/PdecHandler.h
+++ b/linux/obc/PdecHandler.h
@@ -231,25 +231,6 @@ class PdecHandler : public SystemObject,
*/
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 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 This functions writes the configuration parameters to the configuration
* section of the PDEC.
diff --git a/linux/obc/Ptme.cpp b/linux/obc/Ptme.cpp
index 237e66ab..8258fea0 100644
--- a/linux/obc/Ptme.cpp
+++ b/linux/obc/Ptme.cpp
@@ -1,7 +1,7 @@
#include
#include
#include
-
+#include
#include "PtmeConfig.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
@@ -10,28 +10,10 @@ Ptme::Ptme(object_id_t objectId) : SystemObject(objectId) {}
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;
- }
-
- /**
- * Map uio device in virtual address space
- * PROT_WRITE: Map uio device in writable only mode
- */
- ptmeBaseAddress = static_cast(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;
- }
-
VcInterfaceMapIter iter;
for (iter = vcInterfaceMap.begin(); iter != vcInterfaceMap.end(); iter++) {
- iter->second->setRegisterAddress(ptmeBaseAddress);
+ iter->second->initialize();
}
-
return RETURN_OK;
}
diff --git a/linux/obc/Ptme.h b/linux/obc/Ptme.h
index d85885bc..cdb2d6c6 100644
--- a/linux/obc/Ptme.h
+++ b/linux/obc/Ptme.h
@@ -44,14 +44,6 @@ class Ptme : public PtmeIF, public SystemObject, public HasReturnvaluesIF {
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;
-#else
- /** 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
diff --git a/linux/obc/PtmeAxiConfig.cpp b/linux/obc/PtmeAxiConfig.cpp
new file mode 100644
index 00000000..3750b831
--- /dev/null
+++ b/linux/obc/PtmeAxiConfig.cpp
@@ -0,0 +1,41 @@
+#include "PtmeAxiConfig.h"
+#include "fsfw/serviceinterface/ServiceInterface.h"
+#include "fsfw_hal/linux/uio/UioMapper.h"
+
+PtmeAxiConfig::PtmeAxiConfig(object_id_t objectId, std::string configAxiUio, int mapNum) :
+ SystemObject(objectId), configAxiUio(configAxiUio), mapNum(mapNum) {
+ mutex = MutexFactory::instance()->createMutex();
+ if (mutex == nullptr) {
+ sif::warning << "Failed to create mutex" << std::endl;
+ }
+}
+
+PtmeAxiConfig::~PtmeAxiConfig() {
+}
+
+ReturnValue_t PtmeAxiConfig::initialize() {
+ ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
+ UioMapper uioMapper(configAxiUio, mapNum);
+ result = uioMapper.getMappedAdress(&baseAddress, UioMapper::Permissions::READ_WRITE);
+ if (result != HasReturnvaluesIF::RETURN_OK) {
+ return result;
+ }
+ return HasReturnvaluesIF::RETURN_OK;
+}
+
+ReturnValue_t PtmeAxiConfig::writeCaduRateReg(uint8_t rateVal) {
+ ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
+ result = mutex->lockMutex(timeoutType, mutexTimeout);
+ if (result != HasReturnvaluesIF::RETURN_OK) {
+ sif::warning << "PtmeAxiConfig::writeCaduRateReg: Failed to lock mutex" << std::endl;
+ return HasReturnvaluesIF::RETURN_FAILED;
+ }
+ *(baseAddress + CADU_BITRATE_REG) = static_cast(rateVal);
+ result = mutex->unlockMutex();
+ if (result != HasReturnvaluesIF::RETURN_OK) {
+ sif::warning << "PtmeAxiConfig::writeCaduRateReg: Failed to unlock mutex" << std::endl;
+ return HasReturnvaluesIF::RETURN_FAILED;
+ }
+ return HasReturnvaluesIF::RETURN_OK;
+}
+
diff --git a/linux/obc/PtmeAxiConfig.h b/linux/obc/PtmeAxiConfig.h
new file mode 100644
index 00000000..1ea6c295
--- /dev/null
+++ b/linux/obc/PtmeAxiConfig.h
@@ -0,0 +1,42 @@
+#ifndef LINUX_OBC_PTMEAXICONFIG_H_
+#define LINUX_OBC_PTMEAXICONFIG_H_
+
+#include
+#include "fsfw/ipc/MutexIF.h"
+#include "fsfw/returnvalues/HasReturnvaluesIF.h"
+#include "fsfw/objectmanager/SystemObject.h"
+
+/**
+ * @brief Class providing low level access to the configuration interface of the PTME.
+ *
+ * @author J. Meier
+ */
+class PtmeAxiConfig : public SystemObject {
+public:
+ /**
+ * @brief Constructor
+ * @param configAxiUio Device file of UIO belonging to the AXI configuration interface.
+ * @param mapNum Number of map belonging to axi configuration interface.
+ */
+ PtmeAxiConfig(object_id_t objectId, std::string configAxiUio, int mapNum);
+ virtual ~PtmeAxiConfig();
+
+ virtual ReturnValue_t initialize() override;
+ ReturnValue_t writeCaduRateReg(uint8_t rateVal);
+
+private:
+ // Address of register storing the bitrate configuration parameter
+ static const uint32_t CADU_BITRATE_REG = 0x0;
+
+ std::string configAxiUio;
+ std::string uioMap;
+ int mapNum = 0;
+ MutexIF* mutex = nullptr;
+ MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
+ uint32_t mutexTimeout = 20;
+
+ uint32_t* baseAddress = nullptr;
+
+};
+
+#endif /* LINUX_OBC_PTMEAXICONFIG_H_ */
diff --git a/linux/obc/PtmeConfig.h b/linux/obc/PtmeConfig.h
index b5b722ac..2dd7b7b2 100644
--- a/linux/obc/PtmeConfig.h
+++ b/linux/obc/PtmeConfig.h
@@ -25,7 +25,8 @@ static const char UIO_DEVICE_FILE[] = "/dev/uio1";
#else
static const char UIO_DEVICE_FILE[] = "/dev/uio1";
#endif
-
+// Bit clock frequency of PMTE IP core in Hz
+static const uint32_t BIT_CLK_FREQ = 20000000;
}; // namespace PtmeConfig
#endif /* LINUX_OBC_PTMECONFIG_H_ */
diff --git a/linux/obc/PtmeRateSetter.cpp b/linux/obc/PtmeRateSetter.cpp
index b5a6ee1c..cace128b 100644
--- a/linux/obc/PtmeRateSetter.cpp
+++ b/linux/obc/PtmeRateSetter.cpp
@@ -2,24 +2,26 @@
#include "fsfw/serviceinterface/ServiceInterface.h"
-PtmeRateSetter::PtmeRateSetter(gpioId_t bitrateSel, GpioIF* gpioif)
- : bitrateSel(bitrateSel), gpioif(gpioif) {}
+PtmeRateSetter::PtmeRateSetter(object_id_t objectId, PtmeAxiConfig* ptmeAxiConfig)
+ : SystemObject(objectId), ptmeAxiConfig(ptmeAxiConfig) {}
PtmeRateSetter::~PtmeRateSetter() {}
-ReturnValue_t PtmeRateSetter::setRate(BitRates rate) {
- ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
- switch (rate) {
- case RATE_2000KHZ:
- result = gpioif->pullHigh(bitrateSel);
- break;
- case RATE_400KHZ:
- result = gpioif->pullLow(bitrateSel);
- break;
- default:
- sif::debug << "PtmeRateSetter::setRate: Invalid rate" << std::endl;
- result = HasReturnvaluesIF::RETURN_FAILED;
- break;
+ReturnValue_t PtmeRateSetter::initialize() {
+ if (ptmeAxiConfig == nullptr) {
+ sif::warning << "PtmeRateSetter::initialize: Invalid PtmeAxiConfig object" << std::endl;
+ return HasReturnvaluesIF::RETURN_FAILED;
}
- return result;
+ return HasReturnvaluesIF::RETURN_OK;
+}
+
+ReturnValue_t PtmeRateSetter::setRate(uint32_t bitRate) {
+ if (bitRate == 0) {
+ return BAD_BIT_RATE;
+ }
+ uint32_t rateVal = PtmeConfig::BIT_CLK_FREQ / bitRate - 1;
+ if (rateVal > 0xFF) {
+ return RATE_NOT_SUPPORTED;
+ }
+ return ptmeAxiConfig->writeCaduRateReg(static_cast(rateVal));
}
diff --git a/linux/obc/PtmeRateSetter.h b/linux/obc/PtmeRateSetter.h
index 14dfec4b..a5b1a8db 100644
--- a/linux/obc/PtmeRateSetter.h
+++ b/linux/obc/PtmeRateSetter.h
@@ -3,36 +3,46 @@
#include "TxRateSetterIF.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
-#include "fsfw_hal/common/gpio/GpioIF.h"
-#include "fsfw_hal/common/gpio/gpioDefinitions.h"
+#include "linux/obc/PtmeAxiConfig.h"
+#include "linux/obc/PtmeConfig.h"
+#include "fsfw/objectmanager/SystemObject.h"
/**
- * @brief Class to set the downlink bit rate by using the cadu_rate_switcher implemented in
- * the programmable logic.
+ * @brief Class to set the downlink bit rate by writing to the AXI configuration interface of the
+ * PTME IP core.
*
- * @details The cadu_rate_switcher module sets the input rate to the syrlinks transceiver either
- * to 2000 kHz (bitrateSel = 1) or 400 kHz (bitrate = 0).
+ * @details This is the bitrate of the CADU clock and not the downlink which has twice the bitrate
+ * of the CADU clock due to the convolutional code added by the s-Band transceiver.
*
* @author J. Meier
*/
-class PtmeRateSetter : public TxRateSetterIF {
+class PtmeRateSetter : public TxRateSetterIF, public SystemObject, public HasReturnvaluesIF {
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
+ * objectId Object id of system object
+ * ptmeAxiConfig Pointer to object providing access to PTME configuration registers.
*/
- PtmeRateSetter(gpioId_t bitrateSel, GpioIF* gpioif);
+ PtmeRateSetter(object_id_t objectId, PtmeAxiConfig* ptmeAxiConfig);
virtual ~PtmeRateSetter();
- virtual ReturnValue_t setRate(BitRates rate);
+ virtual ReturnValue_t initialize() override;
+ virtual ReturnValue_t setRate(uint32_t bitRate);
private:
- gpioId_t bitrateSel = gpio::NO_GPIO;
- GpioIF* gpioif = nullptr;
+ static const uint8_t INTERFACE_ID = CLASS_ID::RATE_SETTER;
+
+ //! [EXPORT] : [COMMENT] The commanded rate is not supported by the current FPGA design
+ static const ReturnValue_t RATE_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA0);
+ //! [EXPORT] : [COMMENT] Bad bitrate has been commanded (e.g. 0)
+ static const ReturnValue_t BAD_BIT_RATE = MAKE_RETURN_CODE(0xA1);
+
+ // Bitrate register field is only 8 bit wide
+ static const uint32_t MAX_BITRATE = 0xFF;
+
+ PtmeAxiConfig* ptmeAxiConfig = nullptr;
};
#endif /* LINUX_OBC_PTMERATESETTER_H_ */
diff --git a/linux/obc/TxRateSetterIF.h b/linux/obc/TxRateSetterIF.h
index 1eaded33..e8682551 100644
--- a/linux/obc/TxRateSetterIF.h
+++ b/linux/obc/TxRateSetterIF.h
@@ -3,8 +3,6 @@
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
-enum BitRates : uint32_t { RATE_2000KHZ, RATE_400KHZ };
-
/**
* @brief Abstract class for objects implementing the functionality to switch the
* downlink bit rate.
@@ -16,7 +14,7 @@ class TxRateSetterIF {
TxRateSetterIF(){};
virtual ~TxRateSetterIF(){};
- virtual ReturnValue_t setRate(BitRates bitRate) = 0;
+ virtual ReturnValue_t setRate(uint32_t bitRate) = 0;
};
#endif /* LINUX_OBC_TXRATESETTERIF_H_ */
diff --git a/linux/obc/VcInterfaceIF.h b/linux/obc/VcInterfaceIF.h
index 0aa95691..45226e21 100644
--- a/linux/obc/VcInterfaceIF.h
+++ b/linux/obc/VcInterfaceIF.h
@@ -24,7 +24,7 @@ class VcInterfaceIF {
*/
virtual ReturnValue_t write(const uint8_t* data, size_t size) = 0;
- virtual void setRegisterAddress(uint32_t* ptmeBaseAddress) = 0;
+ virtual ReturnValue_t initialize() = 0;
};
#endif /* LINUX_OBC_VCINTERFACEIF_H_ */
diff --git a/mission/tmtc/CCSDSHandler.cpp b/mission/tmtc/CCSDSHandler.cpp
index ba34d273..5c7e19ff 100644
--- a/mission/tmtc/CCSDSHandler.cpp
+++ b/mission/tmtc/CCSDSHandler.cpp
@@ -5,6 +5,7 @@
#include "fsfw/events/EventManagerIF.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
+#include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
@@ -189,14 +190,21 @@ MessageQueueId_t CCSDSHandler::getRequestQueue() {
ReturnValue_t CCSDSHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) {
+ ReturnValue_t result = RETURN_OK;
switch (actionId) {
case SET_LOW_RATE: {
- txRateSetterIF->setRate(BitRates::RATE_400KHZ);
- return EXECUTION_FINISHED;
+ result = txRateSetterIF->setRate(RATE_100KBPS);
+ break;
}
case SET_HIGH_RATE: {
- txRateSetterIF->setRate(BitRates::RATE_2000KHZ);
- return EXECUTION_FINISHED;
+ result = txRateSetterIF->setRate(RATE_500KBPS);
+ break;
+ }
+ case ARBITRARY_RATE: {
+ uint32_t bitrate = 0;
+ SerializeAdapter::deSerialize(&bitrate, &data, &size, SerializeIF::Endianness::BIG);
+ result = txRateSetterIF->setRate(bitrate);
+ break;
}
case EN_TRANSMITTER: {
enableTransmit();
@@ -209,6 +217,10 @@ ReturnValue_t CCSDSHandler::executeAction(ActionId_t actionId, MessageQueueId_t
default:
return COMMAND_NOT_IMPLEMENTED;
}
+ if (result != RETURN_OK) {
+ return result;
+ }
+ return EXECUTION_FINISHED;
}
void CCSDSHandler::checkEvents() {
diff --git a/mission/tmtc/CCSDSHandler.h b/mission/tmtc/CCSDSHandler.h
index 3090c24e..d2782630 100644
--- a/mission/tmtc/CCSDSHandler.h
+++ b/mission/tmtc/CCSDSHandler.h
@@ -23,6 +23,9 @@
* @brief This class handles the data exchange with the CCSDS IP cores implemented in the
* programmable logic of the Q7S.
*
+ * @details After reboot default CADU bitrate is always set to 100 kbps (results in downlink rate
+ * of 200 kbps due to convolutional code added by syrlinks transceiver)
+ *
* @author J. Meier
*/
class CCSDSHandler : public SystemObject,
@@ -85,6 +88,13 @@ class CCSDSHandler : public SystemObject,
static const ActionId_t SET_HIGH_RATE = 1;
static const ActionId_t EN_TRANSMITTER = 2;
static const ActionId_t DIS_TRANSMITTER = 3;
+ static const ActionId_t ARBITRARY_RATE = 4;
+
+ // Syrlinks supports two bitrates (200 kbps and 1000 kbps)
+ // Due to convolutional code added by the syrlinks the input frequency must be half the
+ // target frequency
+ static const uint32_t RATE_100KBPS = 100000;
+ static const uint32_t RATE_500KBPS = 500000;
//! [EXPORT] : [COMMENT] Received action message with unknown action id
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xA0);