Merge pull request 'meier/ptme' (#129) from meier/ptme into develop
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good

Reviewed-on: #129
Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
This commit is contained in:
Robin Müller 2022-01-26 15:59:10 +01:00
commit 71ada855c7
24 changed files with 241 additions and 202 deletions

View File

@ -20,6 +20,7 @@
13. [Eclipse](#eclipse) 13. [Eclipse](#eclipse)
14. [Running the OBSW on a Raspberry Pi](#rpi) 14. [Running the OBSW on a Raspberry Pi](#rpi)
15. [FSFW](#fsfw) 15. [FSFW](#fsfw)
16. [Coding Style](#coding-style)
# <a id="general"></a> General information # <a id="general"></a> General information
@ -1151,3 +1152,15 @@ git merge upstream/master
Alternatively, changes from other upstreams (forks) and branches can be merged like that Alternatively, changes from other upstreams (forks) and branches can be merged like that
in the same way. in the same way.
# <a id="coding-style"></a> Coding Style
* the formatting is based on the clang-format tools
## Setting up eclipse auto-fromatter with clang-format
1. Help &rarr; Install New Software &rarr; 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 &rarr; C/C++ &rarr; CppStyle
6. Insert the path to the clang-format executable
7. Under C/C++ &rarr; Code Style &rarr; 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

View File

@ -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_REGISTERS[] = "/dev/uio0";
static constexpr char UIO_PDEC_CONFIG_MEMORY[] = "/dev/uio2"; static constexpr char UIO_PDEC_CONFIG_MEMORY[] = "/dev/uio2";
static constexpr char UIO_PDEC_RAM[] = "/dev/uio3"; 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 { namespace gpioNames {
static constexpr char GYRO_0_ADIS_CS[] = "gyro_0_adis_chip_select"; 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_CLOCK[] = "rx_clock_enable_ltc2872";
static constexpr char RS485_EN_RX_DATA[] = "rx_data_enable_ltc2872"; static constexpr char RS485_EN_RX_DATA[] = "rx_data_enable_ltc2872";
static constexpr char PDEC_RESET[] = "pdec_reset"; static constexpr char PDEC_RESET[] = "pdec_reset";
static constexpr char BIT_RATE_SEL[] = "bit_rate_sel";
} // namespace gpioNames } // namespace gpioNames
} // namespace q7s } // namespace q7s

View File

@ -115,12 +115,14 @@ void initmission::initTasks() {
} }
#endif /* OBSW_USE_CCSDS_IP_CORE == 1 */ #endif /* OBSW_USE_CCSDS_IP_CORE == 1 */
#if OBSW_ADD_ACS_HANDLERS == 1
PeriodicTaskIF* acsCtrl = factory->createPeriodicTask( PeriodicTaskIF* acsCtrl = factory->createPeriodicTask(
"ACS_CTRL", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc); "ACS_CTRL", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc);
result = acsCtrl->addComponent(objects::GPS_CONTROLLER); result = acsCtrl->addComponent(objects::GPS_CONTROLLER);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("ACS_CTRL", objects::GPS_CONTROLLER); initmission::printAddObjectError("ACS_CTRL", objects::GPS_CONTROLLER);
} }
#endif /* OBSW_ADD_ACS_HANDLERS */
#if BOARD_TE0720 == 0 #if BOARD_TE0720 == 0
// FS task, task interval does not matter because it runs in permanent loop, priority low // FS task, task interval does not matter because it runs in permanent loop, priority low

View File

@ -81,6 +81,7 @@
#include <linux/obc/PtmeConfig.h> #include <linux/obc/PtmeConfig.h>
#include <linux/obc/PtmeRateSetter.h> #include <linux/obc/PtmeRateSetter.h>
#include <linux/obc/TxRateSetterIF.h> #include <linux/obc/TxRateSetterIF.h>
#include <linux/obc/PtmeAxiConfig.h>
ResetArgs resetArgsGnss0; ResetArgs resetArgsGnss0;
ResetArgs resetArgsGnss1; ResetArgs resetArgsGnss1;
@ -892,49 +893,50 @@ void ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF) {
GpioCookie* gpioCookiePtmeIp = new GpioCookie; GpioCookie* gpioCookiePtmeIp = new GpioCookie;
GpiodRegularByLineName* gpio = nullptr; GpiodRegularByLineName* gpio = nullptr;
std::stringstream consumer; 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()); gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC0, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_BUSY, gpio); gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_BUSY, gpio);
consumer.str(""); consumer.str("PAPB VC0");
consumer << "0x" << std::hex << objects::PAPB_VC0;
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC0, consumer.str()); gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC0, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_EMPTY, gpio); gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_EMPTY, gpio);
consumer.str(""); consumer.str("PAPB VC 1");
consumer << "0x" << std::hex << objects::PAPB_VC1;
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC1, consumer.str()); gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC1, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_BUSY, gpio); gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_BUSY, gpio);
consumer.str(""); consumer.str("");
consumer << "0x" << std::hex << objects::PAPB_VC1; consumer.str("PAPB VC 1");
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC1, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_EMPTY, gpio); gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_EMPTY, gpio);
consumer.str(""); 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()); gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC2, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_BUSY, gpio); gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_BUSY, gpio);
consumer.str(""); 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()); gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC2, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_EMPTY, gpio); gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_EMPTY, gpio);
consumer.str(""); 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()); gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC3, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_BUSY, gpio); gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_BUSY, gpio);
consumer.str(""); 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()); gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC3, consumer.str());
gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_EMPTY, gpio); gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_EMPTY, gpio);
gpioComIF->addGpios(gpioCookiePtmeIp); gpioComIF->addGpios(gpioCookiePtmeIp);
// Creating virtual channel interfaces // Creating virtual channel interfaces
VcInterfaceIF* vc0 = new PapbVcInterface(objects::PAPB_VC0, gpioComIF, gpioIds::VC0_PAPB_BUSY, VcInterfaceIF* vc0 =
gpioIds::VC0_PAPB_EMPTY, PtmeConfig::VC0_OFFSETT); new PapbVcInterface(gpioComIF, gpioIds::VC0_PAPB_BUSY, gpioIds::VC0_PAPB_EMPTY, q7s::UIO_PTME,
VcInterfaceIF* vc1 = new PapbVcInterface(objects::PAPB_VC1, gpioComIF, gpioIds::VC1_PAPB_BUSY, q7s::uiomapids::PTME_VC0);
gpioIds::VC1_PAPB_EMPTY, PtmeConfig::VC1_OFFSETT); VcInterfaceIF* vc1 =
VcInterfaceIF* vc2 = new PapbVcInterface(objects::PAPB_VC2, gpioComIF, gpioIds::VC2_PAPB_BUSY, new PapbVcInterface(gpioComIF, gpioIds::VC1_PAPB_BUSY, gpioIds::VC1_PAPB_EMPTY, q7s::UIO_PTME,
gpioIds::VC2_PAPB_EMPTY, PtmeConfig::VC2_OFFSETT); q7s::uiomapids::PTME_VC1);
VcInterfaceIF* vc3 = new PapbVcInterface(objects::PAPB_VC3, gpioComIF, gpioIds::VC3_PAPB_BUSY, VcInterfaceIF* vc2 =
gpioIds::VC3_PAPB_EMPTY, PtmeConfig::VC3_OFFSETT); 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 // Creating ptme object and adding virtual channel interfaces
Ptme* ptme = new Ptme(objects::PTME); Ptme* ptme = new Ptme(objects::PTME);
@ -943,17 +945,9 @@ void ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF) {
ptme->addVcInterface(ccsds::VC2, vc2); ptme->addVcInterface(ccsds::VC2, vc2);
ptme->addVcInterface(ccsds::VC3, vc3); ptme->addVcInterface(ccsds::VC3, vc3);
GpioCookie* gpioCookieRateSetter = new GpioCookie; PtmeAxiConfig* ptmeAxiConfig =
consumer.str(""); new PtmeAxiConfig(objects::PTME_AXI_CONFIG, q7s::UIO_PTME, q7s::uiomapids::PTME_CONFIG);
consumer << "ptme rate setter"; TxRateSetterIF* txRateSetterIF = new PtmeRateSetter(objects::TX_RATE_SETTER, ptmeAxiConfig);
// 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);
CCSDSHandler* ccsdsHandler = new CCSDSHandler( CCSDSHandler* ccsdsHandler = new CCSDSHandler(
objects::CCSDS_HANDLER, objects::PTME, objects::CCSDS_PACKET_DISTRIBUTOR, txRateSetterIF, objects::CCSDS_HANDLER, objects::PTME, objects::CCSDS_PACKET_DISTRIBUTOR, txRateSetterIF,
gpioComIF, gpioIds::RS485_EN_TX_CLOCK, gpioIds::RS485_EN_TX_DATA); gpioComIF, gpioIds::RS485_EN_TX_CLOCK, gpioIds::RS485_EN_TX_DATA);
@ -979,8 +973,7 @@ void ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF) {
gpioComIF->addGpios(gpioCookiePdec); gpioComIF->addGpios(gpioCookiePdec);
new PdecHandler(objects::PDEC_HANDLER, objects::CCSDS_HANDLER, gpioComIF, gpioIds::PDEC_RESET, 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), q7s::UIO_PDEC_CONFIG_MEMORY, q7s::UIO_PDEC_RAM, q7s::UIO_PDEC_REGISTERS);
std::string(q7s::UIO_PDEC_REGISTERS));
#if BOARD_TE0720 == 0 #if BOARD_TE0720 == 0
GpioCookie* gpioRS485Chip = new GpioCookie; GpioCookie* gpioRS485Chip = new GpioCookie;

View File

@ -24,6 +24,7 @@ enum commonClassIds: uint8_t {
PLOC_MEMORY_DUMPER, //PLMEMDUMP PLOC_MEMORY_DUMPER, //PLMEMDUMP
PDEC_HANDLER, //PDEC PDEC_HANDLER, //PDEC
CCSDS_HANDLER, //CCSDS CCSDS_HANDLER, //CCSDS
RATE_SETTER, //RS
ARCSEC_JSON_BASE, //JSONBASE ARCSEC_JSON_BASE, //JSONBASE
NVM_PARAM_BASE, //NVMB NVM_PARAM_BASE, //NVMB
COMMON_CLASS_ID_END // [EXPORT] : [END] COMMON_CLASS_ID_END // [EXPORT] : [END]

View File

@ -12,11 +12,7 @@ enum commonObjects: uint32_t {
TMTC_POLLING_TASK = 0x50000400, TMTC_POLLING_TASK = 0x50000400,
FILE_SYSTEM_HANDLER = 0x50000500, FILE_SYSTEM_HANDLER = 0x50000500,
PTME = 0x50000600, PTME = 0x50000600,
PAPB_VC0 = 0x50000700, PDEC_HANDLER = 0x50000700,
PAPB_VC1 = 0x50000701,
PAPB_VC2 = 0x50000702,
PAPB_VC3 = 0x50000703,
PDEC_HANDLER = 0x50000704,
CCSDS_HANDLER = 0x50000800, CCSDS_HANDLER = 0x50000800,
/* 0x43 ('C') for Controllers */ /* 0x43 ('C') for Controllers */
@ -90,7 +86,9 @@ enum commonObjects: uint32_t {
PLOC_UPDATER = 0x44330000, PLOC_UPDATER = 0x44330000,
PLOC_MEMORY_DUMPER = 0x44330001, PLOC_MEMORY_DUMPER = 0x44330001,
STR_HELPER = 0x44330002 STR_HELPER = 0x44330002,
PTME_AXI_CONFIG = 44330003,
TX_RATE_SETTER = 44330004
}; };
} }

2
fsfw

@ -1 +1 @@
Subproject commit 9b77060295c9c32ebfc2e7cf6517eb2e66216191 Subproject commit faf7da2743dcd30d83c3ab2f7b4d85277878e636

View File

@ -4,6 +4,7 @@ target_sources(${TARGET_NAME} PUBLIC
PdecHandler.cpp PdecHandler.cpp
PdecConfig.cpp PdecConfig.cpp
PtmeRateSetter.cpp PtmeRateSetter.cpp
PtmeAxiConfig.cpp
) )

View File

@ -1,26 +1,26 @@
#include <fsfw_hal/linux/uio/UioMapper.h>
#include <linux/obc/PapbVcInterface.h> #include <linux/obc/PapbVcInterface.h>
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
PapbVcInterface::PapbVcInterface(object_id_t objectId, LinuxLibgpioIF* gpioComIF, PapbVcInterface::PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId,
gpioId_t papbBusyId, gpioId_t papbEmptyId, uint32_t vcOffset) gpioId_t papbEmptyId, std::string uioFile, int mapNum)
: SystemObject(objectId), : gpioComIF(gpioComIF),
gpioComIF(gpioComIF),
papbBusyId(papbBusyId), papbBusyId(papbBusyId),
papbEmptyId(papbEmptyId), papbEmptyId(papbEmptyId),
vcOffset(vcOffset) {} uioFile(uioFile),
mapNum(mapNum) {}
PapbVcInterface::~PapbVcInterface() {} PapbVcInterface::~PapbVcInterface() {}
void PapbVcInterface::setRegisterAddress(uint32_t* ptmeBaseAddress) { ReturnValue_t PapbVcInterface::initialize() {
vcBaseReg = ptmeBaseAddress + vcOffset; UioMapper uioMapper(uioFile, mapNum);
return uioMapper.getMappedAdress(&vcBaseReg, UioMapper::Permissions::WRITE_ONLY);
} }
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) { if (pollPapbBusySignal() == RETURN_OK) {
startPacketTransfer(); startPacketTransfer();
} }
for (size_t idx = 0; idx < size; idx++) { for (size_t idx = 0; idx < size; idx++) {
if (pollPapbBusySignal() == RETURN_OK) { if (pollPapbBusySignal() == RETURN_OK) {
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(*(data + idx)); *(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(*(data + idx));
@ -30,7 +30,6 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
return RETURN_FAILED; return RETURN_FAILED;
} }
} }
if (pollPapbBusySignal() == RETURN_OK) { if (pollPapbBusySignal() == RETURN_OK) {
endPacketTransfer(); endPacketTransfer();
} }

View File

@ -3,9 +3,7 @@
#include <fsfw_hal/common/gpio/gpioDefinitions.h> #include <fsfw_hal/common/gpio/gpioDefinitions.h>
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h> #include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h" #include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "linux/obc/VcInterfaceIF.h" #include "linux/obc/VcInterfaceIF.h"
@ -15,26 +13,27 @@
* *
* @author J. Meier * @author J. Meier
*/ */
class PapbVcInterface : public SystemObject, public VcInterfaceIF, public HasReturnvaluesIF { class PapbVcInterface : public VcInterfaceIF, public HasReturnvaluesIF {
public: public:
/** /**
* @brief Constructor * @brief Constructor
* *
* @param objectId
* @param papbBusyId The ID of the GPIO which is connected to the PAPBBusy_N signal of the * @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 * VcInterface IP Core. A low logic level indicates the VcInterface is not
* ready to receive more data. * ready to receive more data.
* @param papbEmptyId The ID of the GPIO which is connected to the PAPBEmpty signal of the * @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 * VcInterface IP Core. The signal is high when there are no packets in the
* external buffer memory (BRAM). * 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, PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId, gpioId_t papbEmptyId,
gpioId_t papbEmptyId, uint32_t vcOffset); std::string uioFile, int mapNum);
virtual ~PapbVcInterface(); 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; ReturnValue_t initialize() 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;
@ -69,6 +68,9 @@ class PapbVcInterface : public SystemObject, public VcInterfaceIF, public HasRet
/** High when external buffer memory of virtual channel is empty */ /** High when external buffer memory of virtual channel is empty */
gpioId_t papbEmptyId = gpio::NO_GPIO; gpioId_t papbEmptyId = gpio::NO_GPIO;
std::string uioFile;
int mapNum = 0;
uint32_t* vcBaseReg = nullptr; uint32_t* vcBaseReg = nullptr;
uint32_t vcOffset = 0; uint32_t vcOffset = 0;

View File

@ -1,16 +1,14 @@
#include "PdecHandler.h"
#include <fcntl.h> #include <fcntl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <cstring> #include <cstring>
#include <sstream> #include <sstream>
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "PdecHandler.h"
#include "fsfw/ipc/QueueFactory.h" #include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/tmtcservices/TmTcMessage.h" #include "fsfw/tmtcservices/TmTcMessage.h"
#include "fsfw_hal/linux/uio/UioMapper.h"
PdecHandler::PdecHandler(object_id_t objectId, object_id_t tcDestinationId, PdecHandler::PdecHandler(object_id_t objectId, object_id_t tcDestinationId,
LinuxLibgpioIF* gpioComIF, gpioId_t pdecReset, std::string uioConfigMemory, LinuxLibgpioIF* gpioComIF, gpioId_t pdecReset, std::string uioConfigMemory,
@ -44,17 +42,18 @@ ReturnValue_t PdecHandler::initialize() {
ReturnValue_t result = RETURN_OK; ReturnValue_t result = RETURN_OK;
result = getRegisterAddress(); UioMapper regMapper(uioRegisters);
result = regMapper.getMappedAdress(&registerBaseAddress, UioMapper::Permissions::READ_WRITE);
if (result != RETURN_OK) { if (result != RETURN_OK) {
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
UioMapper configMemMapper(uioConfigMemory);
result = getConfigMemoryBaseAddress(); result = configMemMapper.getMappedAdress(&memoryBaseAddress, UioMapper::Permissions::READ_WRITE);
if (result != RETURN_OK) { if (result != RETURN_OK) {
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
UioMapper ramMapper(uioRamMemory);
result = getRamBaseAddress(); result = ramMapper.getMappedAdress(&ramBaseAddress, UioMapper::Permissions::READ_WRITE);
if (result != RETURN_OK) { if (result != RETURN_OK) {
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
@ -76,55 +75,6 @@ ReturnValue_t PdecHandler::initialize() {
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;
}
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;
}
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<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;
}
return RETURN_OK;
}
ReturnValue_t PdecHandler::getRamBaseAddress() {
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));
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;

View File

@ -231,25 +231,6 @@ class PdecHandler : public SystemObject,
*/ */
void readCommandQueue(void); 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 * @brief This functions writes the configuration parameters to the configuration
* section of the PDEC. * section of the PDEC.

View File

@ -1,7 +1,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <linux/obc/Ptme.h> #include <linux/obc/Ptme.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <unistd.h>
#include "PtmeConfig.h" #include "PtmeConfig.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
@ -10,28 +10,10 @@ Ptme::Ptme(object_id_t objectId) : SystemObject(objectId) {}
Ptme::~Ptme() {} Ptme::~Ptme() {}
ReturnValue_t Ptme::initialize() { 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<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;
}
VcInterfaceMapIter iter; VcInterfaceMapIter iter;
for (iter = vcInterfaceMap.begin(); iter != vcInterfaceMap.end(); iter++) { for (iter = vcInterfaceMap.begin(); iter != vcInterfaceMap.end(); iter++) {
iter->second->setRegisterAddress(ptmeBaseAddress); iter->second->initialize();
} }
return RETURN_OK; return RETURN_OK;
} }

View File

@ -44,14 +44,6 @@ class Ptme : public PtmeIF, public SystemObject, public HasReturnvaluesIF {
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;
#else
/** Size of mapped address space */
static const int MAP_SIZE = 0x40000;
#endif /* BOARD_TE0720 == 1 */
/** /**
* Configuration bits: * Configuration bits:
* bit[1:0]: Size of data (1,2,3 or 4 bytes). 1 Byte <=> b00 * bit[1:0]: Size of data (1,2,3 or 4 bytes). 1 Byte <=> b00

View File

@ -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<uint32_t>(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;
}

42
linux/obc/PtmeAxiConfig.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef LINUX_OBC_PTMEAXICONFIG_H_
#define LINUX_OBC_PTMEAXICONFIG_H_
#include <string>
#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_ */

View File

@ -25,7 +25,8 @@ static const char UIO_DEVICE_FILE[] = "/dev/uio1";
#else #else
static const char UIO_DEVICE_FILE[] = "/dev/uio1"; static const char UIO_DEVICE_FILE[] = "/dev/uio1";
#endif #endif
// Bit clock frequency of PMTE IP core in Hz
static const uint32_t BIT_CLK_FREQ = 20000000;
}; // namespace PtmeConfig }; // namespace PtmeConfig
#endif /* LINUX_OBC_PTMECONFIG_H_ */ #endif /* LINUX_OBC_PTMECONFIG_H_ */

View File

@ -2,24 +2,26 @@
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
PtmeRateSetter::PtmeRateSetter(gpioId_t bitrateSel, GpioIF* gpioif) PtmeRateSetter::PtmeRateSetter(object_id_t objectId, PtmeAxiConfig* ptmeAxiConfig)
: bitrateSel(bitrateSel), gpioif(gpioif) {} : SystemObject(objectId), ptmeAxiConfig(ptmeAxiConfig) {}
PtmeRateSetter::~PtmeRateSetter() {} PtmeRateSetter::~PtmeRateSetter() {}
ReturnValue_t PtmeRateSetter::setRate(BitRates rate) { ReturnValue_t PtmeRateSetter::initialize() {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; if (ptmeAxiConfig == nullptr) {
switch (rate) { sif::warning << "PtmeRateSetter::initialize: Invalid PtmeAxiConfig object" << std::endl;
case RATE_2000KHZ: return HasReturnvaluesIF::RETURN_FAILED;
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;
} }
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<uint8_t>(rateVal));
} }

View File

@ -3,36 +3,46 @@
#include "TxRateSetterIF.h" #include "TxRateSetterIF.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h" #include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "fsfw_hal/common/gpio/GpioIF.h" #include "linux/obc/PtmeAxiConfig.h"
#include "fsfw_hal/common/gpio/gpioDefinitions.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 * @brief Class to set the downlink bit rate by writing to the AXI configuration interface of the
* the programmable logic. * PTME IP core.
* *
* @details The cadu_rate_switcher module sets the input rate to the syrlinks transceiver either * @details This is the bitrate of the CADU clock and not the downlink which has twice the bitrate
* to 2000 kHz (bitrateSel = 1) or 400 kHz (bitrate = 0). * of the CADU clock due to the convolutional code added by the s-Band transceiver.
* *
* @author J. Meier * @author J. Meier
*/ */
class PtmeRateSetter : public TxRateSetterIF { class PtmeRateSetter : public TxRateSetterIF, public SystemObject, public HasReturnvaluesIF {
public: public:
/** /**
* @brief Constructor * @brief Constructor
* *
* @param bitrateSel GPIO ID of the GPIO connected to the bitrate_sel input of the * objectId Object id of system object
* cadu_rate_switcher. * ptmeAxiConfig Pointer to object providing access to PTME configuration registers.
* @param gpioif GPIO interface to drive the bitrateSel GPIO
*/ */
PtmeRateSetter(gpioId_t bitrateSel, GpioIF* gpioif); PtmeRateSetter(object_id_t objectId, PtmeAxiConfig* ptmeAxiConfig);
virtual ~PtmeRateSetter(); virtual ~PtmeRateSetter();
virtual ReturnValue_t setRate(BitRates rate); virtual ReturnValue_t initialize() override;
virtual ReturnValue_t setRate(uint32_t bitRate);
private: 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_ */ #endif /* LINUX_OBC_PTMERATESETTER_H_ */

View File

@ -3,8 +3,6 @@
#include "fsfw/returnvalues/HasReturnvaluesIF.h" #include "fsfw/returnvalues/HasReturnvaluesIF.h"
enum BitRates : uint32_t { RATE_2000KHZ, RATE_400KHZ };
/** /**
* @brief Abstract class for objects implementing the functionality to switch the * @brief Abstract class for objects implementing the functionality to switch the
* downlink bit rate. * downlink bit rate.
@ -16,7 +14,7 @@ class TxRateSetterIF {
TxRateSetterIF(){}; TxRateSetterIF(){};
virtual ~TxRateSetterIF(){}; virtual ~TxRateSetterIF(){};
virtual ReturnValue_t setRate(BitRates bitRate) = 0; virtual ReturnValue_t setRate(uint32_t bitRate) = 0;
}; };
#endif /* LINUX_OBC_TXRATESETTERIF_H_ */ #endif /* LINUX_OBC_TXRATESETTERIF_H_ */

View File

@ -24,7 +24,7 @@ class VcInterfaceIF {
*/ */
virtual ReturnValue_t write(const uint8_t* data, size_t size) = 0; 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_ */ #endif /* LINUX_OBC_VCINTERFACEIF_H_ */

View File

@ -5,6 +5,7 @@
#include "fsfw/events/EventManagerIF.h" #include "fsfw/events/EventManagerIF.h"
#include "fsfw/ipc/QueueFactory.h" #include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h" #include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
@ -189,14 +190,21 @@ MessageQueueId_t CCSDSHandler::getRequestQueue() {
ReturnValue_t CCSDSHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, ReturnValue_t CCSDSHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) { const uint8_t* data, size_t size) {
ReturnValue_t result = RETURN_OK;
switch (actionId) { switch (actionId) {
case SET_LOW_RATE: { case SET_LOW_RATE: {
txRateSetterIF->setRate(BitRates::RATE_400KHZ); result = txRateSetterIF->setRate(RATE_100KBPS);
return EXECUTION_FINISHED; break;
} }
case SET_HIGH_RATE: { case SET_HIGH_RATE: {
txRateSetterIF->setRate(BitRates::RATE_2000KHZ); result = txRateSetterIF->setRate(RATE_500KBPS);
return EXECUTION_FINISHED; break;
}
case ARBITRARY_RATE: {
uint32_t bitrate = 0;
SerializeAdapter::deSerialize(&bitrate, &data, &size, SerializeIF::Endianness::BIG);
result = txRateSetterIF->setRate(bitrate);
break;
} }
case EN_TRANSMITTER: { case EN_TRANSMITTER: {
enableTransmit(); enableTransmit();
@ -209,6 +217,10 @@ ReturnValue_t CCSDSHandler::executeAction(ActionId_t actionId, MessageQueueId_t
default: default:
return COMMAND_NOT_IMPLEMENTED; return COMMAND_NOT_IMPLEMENTED;
} }
if (result != RETURN_OK) {
return result;
}
return EXECUTION_FINISHED;
} }
void CCSDSHandler::checkEvents() { void CCSDSHandler::checkEvents() {

View File

@ -23,6 +23,9 @@
* @brief This class handles the data exchange with the CCSDS IP cores implemented in the * @brief This class handles the data exchange with the CCSDS IP cores implemented in the
* programmable logic of the Q7S. * 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 * @author J. Meier
*/ */
class CCSDSHandler : public SystemObject, class CCSDSHandler : public SystemObject,
@ -85,6 +88,13 @@ class CCSDSHandler : public SystemObject,
static const ActionId_t SET_HIGH_RATE = 1; static const ActionId_t SET_HIGH_RATE = 1;
static const ActionId_t EN_TRANSMITTER = 2; static const ActionId_t EN_TRANSMITTER = 2;
static const ActionId_t DIS_TRANSMITTER = 3; 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 //! [EXPORT] : [COMMENT] Received action message with unknown action id
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xA0); static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xA0);

2
tmtc

@ -1 +1 @@
Subproject commit 6f24d6a83995ca7a895c17a77a00bceac4d7f141 Subproject commit 598635ee4fb1eb246980564ae9f3a0feb1f4da30