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);