From 5b26564058aba88f7160c9f0af19b0725b5261c5 Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Sun, 26 Sep 2021 08:29:30 +0200 Subject: [PATCH] ptme ip core packet insertion --- bsp_q7s/boardconfig/busConf.h | 8 + bsp_q7s/core/ObjectFactory.cpp | 126 +++++--- bsp_q7s/core/ObjectFactory.h | 1 + common/config/ccsdsConfig.h | 15 + common/config/commonObjects.h | 7 +- linux/fsfwconfig/OBSWConfig.h.in | 5 + linux/obc/PapbVcInterface.cpp | 10 +- linux/obc/PapbVcInterface.h | 10 +- linux/obc/Ptme.cpp | 17 +- linux/obc/Ptme.h | 11 +- linux/obc/PtmeConfig.h | 2 +- linux/obc/PtmeIF.h | 2 +- linux/obc/VcInterfaceIF.h | 5 +- mission/CMakeLists.txt | 1 + mission/tmtc/CCSDSHandler.cpp | 500 ++++--------------------------- mission/tmtc/CCSDSHandler.h | 131 ++------ mission/tmtc/CMakeLists.txt | 6 + mission/tmtc/VirtualChannel.cpp | 30 +- mission/tmtc/VirtualChannel.h | 83 +---- mission/utility/TmFunnel.cpp | 4 +- 20 files changed, 252 insertions(+), 722 deletions(-) create mode 100644 common/config/ccsdsConfig.h create mode 100644 mission/tmtc/CMakeLists.txt diff --git a/bsp_q7s/boardconfig/busConf.h b/bsp_q7s/boardconfig/busConf.h index 1149a54e..4b64e775 100644 --- a/bsp_q7s/boardconfig/busConf.h +++ b/bsp_q7s/boardconfig/busConf.h @@ -52,6 +52,14 @@ namespace gpioNames { static constexpr char EN_RW_4[] = "enable_rw_4"; static constexpr char SPI_MUX_SELECT[] = "spi_mux_select"; static constexpr char RAD_SENSOR_CHIP_SELECT[] = "rad_sensor_chip_select"; + static constexpr char PAPB_BUSY_SIGNAL_VC0[] = "papb_busy_signal_vc0"; + static constexpr char PAPB_EMPTY_SIGNAL_VC0[] = "papb_empty_signal_vc0"; + static constexpr char PAPB_BUSY_SIGNAL_VC1[] = "papb_busy_signal_vc1"; + static constexpr char PAPB_EMPTY_SIGNAL_VC1[] = "papb_empty_signal_vc1"; + static constexpr char PAPB_BUSY_SIGNAL_VC2[] = "papb_busy_signal_vc2"; + static constexpr char PAPB_EMPTY_SIGNAL_VC2[] = "papb_empty_signal_vc2"; + static constexpr char PAPB_BUSY_SIGNAL_VC3[] = "papb_busy_signal_vc3"; + static constexpr char PAPB_EMPTY_SIGNAL_VC3[] = "papb_empty_signal_vc3"; } } diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index a5a76f8b..86709292 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -2,6 +2,7 @@ #include "ObjectFactory.h" #include "OBSWConfig.h" #include "devConf.h" +#include "ccsdsConfig.h" #include "busConf.h" #include "tmtc/apid.h" #include "devices/addresses.h" @@ -47,6 +48,8 @@ #include "mission/devices/devicedefinitions/RwDefinitions.h" #include "mission/devices/devicedefinitions/StarTrackerDefinitions.h" #include "mission/devices/GPSHyperionHandler.h" +#include "mission/tmtc/CCSDSHandler.h" +#include "mission/tmtc/VirtualChannel.h" #include "mission/utility/TmFunnel.h" #include "fsfw_hal/linux/uart/UartComIF.h" @@ -84,6 +87,7 @@ #include #include +#include ResetArgs resetArgsGnss0; ResetArgs resetArgsGnss1; @@ -101,7 +105,12 @@ void Factory::setStaticFrameworkObjectIds() { //DeviceHandlerBase::powerSwitcherId = objects::PCDU_HANDLER; DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT; + +#if OBSW_TM_TO_PTME == 1 + TmFunnel::downlinkDestination = objects::CCSDS_HANDLER; +#else TmFunnel::downlinkDestination = objects::TMTC_BRIDGE; +#endif /* OBSW_TM_TO_PTME == 1 */ // No storage object for now. TmFunnel::storageDestination = objects::NO_OBJECT; @@ -174,53 +183,7 @@ void ObjectFactory::produce(void* args) { #endif /* TE7020 != 0 */ #if OBSW_USE_CCSDS_IP_CORE == 1 - - // GPIO definitions of signals connected to the virtual channel interfaces of the PTME IP Core - GpioCookie* gpioCookiePtmeIp = new GpioCookie; - GpiodRegular* vcSignal = new GpiodRegular("PAPB VC0 Busy Signal", - q7s::GPIO_VC_STATUS_SIGNALS_LABEL, q7s::VC0_PAPB_BUSY_LINE); - gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_BUSY, vcSignal); - vcSignal = new GpiodRegular("PAPB VC0 Empty Signal", q7s::GPIO_VC_STATUS_SIGNALS_LABEL, - q7s::VC0_PAPB_EMPTY_LINE); - gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_EMPTY, vcSignal); - vcSignal = new GpiodRegular("PAPB VC1 Busy Signal", q7s::GPIO_VC_STATUS_SIGNALS_LABEL, - q7s::VC1_PAPB_BUSY_LINE); - gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_BUSY, vcSignal); - vcSignal = new GpiodRegular("PAPB VC1 Empty Signal", q7s::GPIO_VC_STATUS_SIGNALS_LABEL, - q7s::VC1_PAPB_EMPTY_LINE); - gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_EMPTY, vcSignal); - vcSignal = new GpiodRegular("PAPB VC2 Busy Signal", q7s::GPIO_VC_STATUS_SIGNALS_LABEL, - q7s::VC2_PAPB_BUSY_LINE); - gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_BUSY, vcSignal); - vcSignal = new GpiodRegular("PAPB VC2 Empty Signal", q7s::GPIO_VC_STATUS_SIGNALS_LABEL, - q7s::VC2_PAPB_EMPTY_LINE); - gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_EMPTY, vcSignal); - vcSignal = new GpiodRegular("PAPB VC3 Busy Signal", q7s::GPIO_VC_STATUS_SIGNALS_LABEL, - q7s::VC3_PAPB_BUSY_LINE); - gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_BUSY, vcSignal); - vcSignal = new GpiodRegular("PAPB VC3 Empty Signal", q7s::GPIO_VC_STATUS_SIGNALS_LABEL, - q7s::VC3_PAPB_EMPTY_LINE); - gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_EMPTY, vcSignal); - - gpioComIF->addGpios(gpioCookiePtmeIp); - - // Creating virtual channel interfaces - PapbVcInterface* vc = new PapbVcInterface(objects::PAPB_VC0, gpioComIF, gpioIds::VC0_PAPB_BUSY, - gpioIds::VC0_PAPB_EMPTY); - PapbVcInterface* vc = new PapbVcInterface(objects::PAPB_VC1, gpioComIF, gpioIds::VC1_PAPB_BUSY, - gpioIds::VC1_PAPB_EMPTY); - PapbVcInterface* vc = new PapbVcInterface(objects::PAPB_VC2, gpioComIF, gpioIds::VC2_PAPB_BUSY, - gpioIds::VC2_PAPB_EMPTY); - PapbVcInterface* vc = new PapbVcInterface(objects::PAPB_VC3, gpioComIF, gpioIds::VC3_PAPB_BUSY, - gpioIds::VC3_PAPB_EMPTY); - - // Creating ptme object and adding virtual channel interfaces - Ptme* ptme = new Ptme(objects::PTME); - ptme->addVcInterface(0, vc); - ptme->addVcInterface(1, vc); - ptme->addVcInterface(2, vc); - ptme->addVcInterface(3, vc); - + createCcsdsComponents(gpioComIF); #endif /* OBSW_USE_CCSDS_IP_CORE == 1 */ #if OBSW_USE_TMTC_TCP_BRIDGE == 0 @@ -922,6 +885,75 @@ void ObjectFactory::createReactionWheelComponents(LinuxLibgpioIF* gpioComIF) { rw4SpiCookie->setCallbackArgs(rwHandler4); } +void ObjectFactory::createCcsdsComponents(LinuxLibgpioIF *gpioComIF) { + // GPIO definitions of signals connected to the virtual channel interfaces of the PTME IP Core + GpioCookie* gpioCookiePtmeIp = new GpioCookie; + GpiodRegularByLineName* gpio = nullptr; + std::stringstream consumer; + consumer << "0x" << std::hex << objects::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; + 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; + 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()); + gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_EMPTY, gpio); + consumer.str(""); + consumer << "0x" << std::hex << objects::PAPB_VC2; + 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; + 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; + 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; + 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); + + // Creating ptme object and adding virtual channel interfaces + Ptme* ptme = new Ptme(objects::PTME); + ptme->addVcInterface(ccsds::VC0, vc0); + ptme->addVcInterface(ccsds::VC1, vc1); + ptme->addVcInterface(ccsds::VC2, vc2); + ptme->addVcInterface(ccsds::VC3, vc3); + + CCSDSHandler* ccsdsHandler = new CCSDSHandler(objects::CCSDS_HANDLER, objects::PTME); + + VirtualChannel* vc = nullptr; + vc = new VirtualChannel(ccsds::VC0, config::VC0_QUEUE_SIZE); + ccsdsHandler->addVirtualChannel(ccsds::VC0, vc); + vc = new VirtualChannel(ccsds::VC1, config::VC1_QUEUE_SIZE); + ccsdsHandler->addVirtualChannel(ccsds::VC1, vc); + vc = new VirtualChannel(2, config::VC2_QUEUE_SIZE); + ccsdsHandler->addVirtualChannel(ccsds::VC2, vc); + vc = new VirtualChannel(3, config::VC3_QUEUE_SIZE); + ccsdsHandler->addVirtualChannel(ccsds::VC3, vc); +} + void ObjectFactory::createTestComponents(LinuxLibgpioIF* gpioComIF) { #if BOARD_TE0720 == 0 diff --git a/bsp_q7s/core/ObjectFactory.h b/bsp_q7s/core/ObjectFactory.h index ad9533a5..0e723142 100644 --- a/bsp_q7s/core/ObjectFactory.h +++ b/bsp_q7s/core/ObjectFactory.h @@ -22,6 +22,7 @@ void createSolarArrayDeploymentComponents(); void createSyrlinksComponents(); void createRtdComponents(LinuxLibgpioIF* gpioComIF); void createReactionWheelComponents(LinuxLibgpioIF* gpioComIF); +void createCcsdsComponents(LinuxLibgpioIF *gpioComIF); void createTestComponents(LinuxLibgpioIF* gpioComIF); }; diff --git a/common/config/ccsdsConfig.h b/common/config/ccsdsConfig.h new file mode 100644 index 00000000..8466a9fa --- /dev/null +++ b/common/config/ccsdsConfig.h @@ -0,0 +1,15 @@ +#ifndef COMMON_CONFIG_CCSDSCONFIG_H_ +#define COMMON_CONFIG_CCSDSCONFIG_H_ + +namespace ccsds { +enum { + VC0, + VC1, + VC2, + VC3 +}; +} + + + +#endif /* COMMON_CONFIG_CCSDSCONFIG_H_ */ diff --git a/common/config/commonObjects.h b/common/config/commonObjects.h index 0a66cd9a..43cd396c 100644 --- a/common/config/commonObjects.h +++ b/common/config/commonObjects.h @@ -13,9 +13,10 @@ enum commonObjects: uint32_t { FILE_SYSTEM_HANDLER = 0x50000500, PTME = 0x50000600, PAPB_VC0 = 0x50000700, - PAPB_VC1 = 0x500007001, - PAPB_VC2 = 0x500007002, - PAPB_VC3 = 0x500007003, + PAPB_VC1 = 0x50000701, + PAPB_VC2 = 0x50000702, + PAPB_VC3 = 0x50000703, + CCSDS_HANDLER = 0x50000800, /* 0x43 ('C') for Controllers */ THERMAL_CONTROLLER = 0x43400001, diff --git a/linux/fsfwconfig/OBSWConfig.h.in b/linux/fsfwconfig/OBSWConfig.h.in index f3d3fad6..afaed4a5 100644 --- a/linux/fsfwconfig/OBSWConfig.h.in +++ b/linux/fsfwconfig/OBSWConfig.h.in @@ -123,7 +123,12 @@ namespace config { /* Add mission configuration flags here */ static constexpr uint32_t OBSW_FILESYSTEM_HANDLER_QUEUE_SIZE = 50; static constexpr uint32_t PLOC_UPDATER_QUEUE_SIZE = 50; +static constexpr uint32_t CCSDS_HANDLER_QUEUE_SIZE = 50; static constexpr uint8_t NUMBER_OF_VIRTUAL_CHANNELS = 4; +static constexpr uint8_t VC0_QUEUE_SIZE = 50; +static constexpr uint8_t VC1_QUEUE_SIZE = 50; +static constexpr uint8_t VC2_QUEUE_SIZE = 50; +static constexpr uint8_t VC3_QUEUE_SIZE = 50; #ifdef __cplusplus } diff --git a/linux/obc/PapbVcInterface.cpp b/linux/obc/PapbVcInterface.cpp index 0c3c759a..6cbd81a3 100644 --- a/linux/obc/PapbVcInterface.cpp +++ b/linux/obc/PapbVcInterface.cpp @@ -3,7 +3,7 @@ PapbVcInterface::PapbVcInterface(object_id_t objectId, LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId, gpioId_t papbEmptyId, uint32_t vcOffset) : - SystemObject(objectId), gpioComIF(gpioComIF), uioVcInterface(uioVcInterface), papbBusyId( + SystemObject(objectId), gpioComIF(gpioComIF), papbBusyId( papbBusyId), papbEmptyId(papbEmptyId), vcOffset(vcOffset) { } @@ -15,19 +15,19 @@ void PapbVcInterface::setRegisterAddress(uint32_t* ptmeBaseAddress) { vcBaseReg = ptmeBaseAddress + vcOffset; } -ReturnValue_t PapbVcInterface::write(const uint8_t * data, size_t dataLen) { +ReturnValue_t PapbVcInterface::write(const uint8_t * data, size_t size) { if(pollPapbBusySignal() == RETURN_OK) { startPacketTransfer(); } - for(size_t idx = 0; idx < dataLen; idx++) { + for(size_t idx = 0; idx < size; idx++) { if(pollPapbBusySignal() == RETURN_OK) { *(vcBaseReg + DATA_REG_OFFSET) = static_cast(*(data + idx)); } else { sif::warning << "PapbVcInterface::sendTm: Only written " << idx - 1 << " of " - << dataLen << " data" << std::endl; + << size << " data" << std::endl; return RETURN_FAILED; } } @@ -95,7 +95,7 @@ ReturnValue_t PapbVcInterface::sendTestFrame() { testPacket[idx] = static_cast(idx & 0xFF); } - ReturnValue_t result = sendTm(testPacket, 1105); + ReturnValue_t result = write(testPacket, 1105); if(result != RETURN_OK) { return result; } diff --git a/linux/obc/PapbVcInterface.h b/linux/obc/PapbVcInterface.h index 05947ac6..937f4280 100644 --- a/linux/obc/PapbVcInterface.h +++ b/linux/obc/PapbVcInterface.h @@ -5,8 +5,8 @@ #include "linux/obc/VcInterfaceIF.h" #include #include -#include #include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/objectmanager/ObjectManager.h" /** * @brief This class handles the transmission of data to a virtual channel of the PTME IP Core @@ -14,7 +14,9 @@ * * @author J. Meier */ -class PapbVcInterface : VcInterfaceIF, HasReturnvaluesIF { +class PapbVcInterface: public SystemObject, + public VcInterfaceIF, + public HasReturnvaluesIF { public: /** * @brief Constructor @@ -31,6 +33,10 @@ public: gpioId_t papbEmptyId, uint32_t vcOffset); virtual ~PapbVcInterface(); + ReturnValue_t write(const uint8_t* data, size_t size) override; + + void setRegisterAddress(uint32_t* ptmeBaseAddress) override; + private: static const uint8_t INTERFACE_ID = CLASS_ID::CCSDS_IP_CORE_BRIDGE; diff --git a/linux/obc/Ptme.cpp b/linux/obc/Ptme.cpp index 480b5836..80f9945c 100644 --- a/linux/obc/Ptme.cpp +++ b/linux/obc/Ptme.cpp @@ -3,6 +3,7 @@ #include #include "fsfw/serviceinterface/ServiceInterface.h" +#include "PtmeConfig.h" Ptme::Ptme(object_id_t objectId) : SystemObject(objectId) { @@ -12,9 +13,8 @@ Ptme::~Ptme() { } ReturnValue_t Ptme::initialize() { - ReturnValue_t result = TmTcBridge::initialize(); - fd = open(PtmeConfig::UIO_DEVICE_FILE, O_RDWR); + 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; @@ -32,10 +32,15 @@ ReturnValue_t Ptme::initialize() { return RETURN_FAILED; } - return result; + VcInterfaceMapIter iter; + for (iter = vcInterfaceMap.begin(); iter != vcInterfaceMap.end(); iter++) { + iter->second->setRegisterAddress(ptmeBaseAddress); + } + + return RETURN_OK; } -ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t * data, size_t dataLen) { +ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t * data, size_t size) { ReturnValue_t result = RETURN_OK; VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId); if (vcInterfaceMapIter == vcInterfaceMap.end()) { @@ -43,13 +48,13 @@ ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t * data, size_t dataLen "channel with id " << static_cast(vcId) << std::endl; return UNKNOWN_VC_ID; } - result = vcInterfaceMapIter->second.write(data, size); + result = vcInterfaceMapIter->second->write(data, size); return result; } void Ptme::addVcInterface(VcId_t vcId, VcInterfaceIF* vc) { - if (vcId > config::MAX_VIRTUAL_CHANNEL_ID) { + if (vcId > config::NUMBER_OF_VIRTUAL_CHANNELS) { sif::warning << "Ptme::addVcInterface: Invalid virtual channel ID" << std::endl; return; } diff --git a/linux/obc/Ptme.h b/linux/obc/Ptme.h index 6ef118ab..aa131d9e 100644 --- a/linux/obc/Ptme.h +++ b/linux/obc/Ptme.h @@ -18,8 +18,13 @@ * The IP cores are implemented on the programmable logic and are accessible through the * linux UIO driver. */ -class Ptme : PtmeIF, SystemObject, HasReturnvaluesIF { +class Ptme : public PtmeIF, + public SystemObject, + public HasReturnvaluesIF { public: + + using VcId_t = uint8_t; + /** * @brief Constructor * @@ -29,7 +34,7 @@ public: virtual ~Ptme(); ReturnValue_t initialize() override; - ReturnValue_t writeToVc(uint8_t vcId, uint8_t* data, size_t size) override; + ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) override; /** * @brief This function adds the reference to a virtual channel interface to the vcInterface @@ -73,8 +78,6 @@ private: uint32_t* ptmeBaseAddress = nullptr; - using VcId_t = uint8_t; - using VcInterfaceMap = std::unordered_map; using VcInterfaceMapIter = VcInterfaceMap::iterator; diff --git a/linux/obc/PtmeConfig.h b/linux/obc/PtmeConfig.h index 34fd8876..f4468570 100644 --- a/linux/obc/PtmeConfig.h +++ b/linux/obc/PtmeConfig.h @@ -20,7 +20,7 @@ namespace PtmeConfig { static const uint32_t VC2_OFFSETT = 0x8000; static const uint32_t VC3_OFFSETT = 0xC000; - static const std::string UIO_DEVICE_FILE = "/dev/uio0"; + static const char UIO_DEVICE_FILE[] = "/dev/uio0"; }; #endif /* LINUX_OBC_PTMECONFIG_H_ */ diff --git a/linux/obc/PtmeIF.h b/linux/obc/PtmeIF.h index c89d25f0..53d9498b 100644 --- a/linux/obc/PtmeIF.h +++ b/linux/obc/PtmeIF.h @@ -22,7 +22,7 @@ public: * @param data Pointer to buffer holding the data to write * @param size Number of bytes to write */ - virtual ReturnValue_t writeToVc(uint8_t vcId, uint8_t* data, size_t size) = 0; + virtual ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) = 0; }; #endif /* LINUX_OBC_PTMEIF_H_ */ diff --git a/linux/obc/VcInterfaceIF.h b/linux/obc/VcInterfaceIF.h index ce643b48..28b8d1f1 100644 --- a/linux/obc/VcInterfaceIF.h +++ b/linux/obc/VcInterfaceIF.h @@ -1,6 +1,7 @@ #ifndef LINUX_OBC_VCINTERFACEIF_H_ #define LINUX_OBC_VCINTERFACEIF_H_ +#include #include "fsfw/returnvalues/HasReturnvaluesIF.h" /** @@ -20,7 +21,9 @@ public: * @param data Pointer to buffer holding the data to write * @param size Number of bytes to write */ - virtual ReturnValue_t write(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; }; #endif /* LINUX_OBC_VCINTERFACEIF_H_ */ diff --git a/mission/CMakeLists.txt b/mission/CMakeLists.txt index 46f562a5..876201a8 100644 --- a/mission/CMakeLists.txt +++ b/mission/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory(core) add_subdirectory(devices) add_subdirectory(utility) add_subdirectory(memory) +add_subdirectory(tmtc) diff --git a/mission/tmtc/CCSDSHandler.cpp b/mission/tmtc/CCSDSHandler.cpp index b17af452..2a337d68 100644 --- a/mission/tmtc/CCSDSHandler.cpp +++ b/mission/tmtc/CCSDSHandler.cpp @@ -1,133 +1,29 @@ -#include -#include -#include -#include -#include -#include -#include -#include +#include "fsfw/serviceinterface/ServiceInterface.h" +#include "fsfw/serviceinterface/serviceInterfaceDefintions.h" +#include "fsfw/objectmanager/ObjectManager.h" +#include "fsfw/ipc/QueueFactory.h" -const float CCSDSHandler::DEFAULT_RATES[BoardHandler::USED_VIRTUAL_CHANNELS_PER_BOARD] = - { CCSDSHandler::DEFAULT_BYTES_PER_SECOND, CCSDSHandler::DEFAULT_BYTES_PER_SECOND, - CCSDSHandler::DEFAULT_BYTES_PER_SECOND, CCSDSHandler::DEFAULT_BYTES_PER_SECOND }; +#include "CCSDSHandler.h" -CCSDSHandler::CCSDSHandler(object_id_t setObjectId, uint8_t setSwitchId1, - uint8_t setSwitchId2, object_id_t setChannel, uint16_t setSCID, - BoardHandler::DataPoolIds setPool) : - SystemObject(setObjectId), tmPartHealth(setObjectId + 1, 0), commandQueue(), state( - STATE_IDLE), commState(SEND_WRITE), mode(MODE_OFF), submode( - SUBMODE_NONE), boardHandler((uint8_t*) frameBuffer, - sizeof(frameBuffer), setSCID, setPool), dataLinkLayer( - this->frameBuffer, boardHandler.getClcw(), 0, setSCID), frameLength( - 0), channelId(setChannel), memoryHelper(this, &commandQueue), pendingWrite( - false), pendingRead(false), modeHelper(this), healthHelper(this, - setObjectId), parameterHelper(this), powerSwitcher(setSwitchId1, - setSwitchId2), switchOffWasReported(false), fdir(setObjectId, - setChannel) { - memset(this->frameBuffer, 0, sizeof(frameBuffer)); - DataSet mySet; - PoolVector rateRatio( - datapool::DATA_RATE_ASSIGN, &mySet, PoolVariableIF::VAR_WRITE); - for (uint8_t i = 0; i < BoardHandler::USED_VIRTUAL_CHANNELS_PER_BOARD; - ++i) { - virtualChannels[i] = new VCGeneration(i, - BoardHandler::TM_PACKETS_PER_CALL_PER_CHANNEL); - rateLimitOverload[i] = 0; - rateRatio[i] = DEFAULT_RATES[i]; - } - mySet.commit(PoolVariableIF::VALID); - //Set real-time channel to high responsiveness. - virtualChannels[0]->setIdlePacketIntervalMs( - VCGeneration::IDLE_INTERVAL_RT_CHANNEL); +CCSDSHandler::CCSDSHandler(object_id_t objectId, object_id_t ptmeId) : + SystemObject(objectId), ptmeId(ptmeId), parameterHelper(this) { + commandQueue = QueueFactory::instance()->createMessageQueue(QUEUE_SIZE); } CCSDSHandler::~CCSDSHandler() { - for (uint8_t i = 0; i < BoardHandler::USED_VIRTUAL_CHANNELS_PER_BOARD; - ++i) { - delete virtualChannels[i]; - } } -void CCSDSHandler::printFrameBuffer(void) { - debug << "frame_buffer contains: " << std::endl; - for (uint32_t i = 0; i < this->frameLength; ++i) { - debug << "frame_buffer[" << std::dec << i << "]: " << std::hex - << std::showbase << (uint16_t) this->frameBuffer[i] << std::dec - << std::endl; - } -} - -ReturnValue_t CCSDSHandler::packetProcessing(void) { - rateSet.read(); - const float* usedRateRatios = NULL; - if (rateSet.dataRates.isValid()) { - usedRateRatios = rateSet.dataRates.value; - } else { - usedRateRatios = DEFAULT_RATES; - } - for (uint8_t i = 0; i < BoardHandler::USED_VIRTUAL_CHANNELS_PER_BOARD; - ++i) { - //Set current cycle Limit first - uint32_t newLimit = (usedRateRatios[i]) / SENDS_PER_SECOND; - if (newLimit <= rateLimitOverload[i]) { - //Calculate new overload. - rateLimitOverload[i] -= newLimit; - //Use newLimit as current rate, VC is utilized to its current limit. - rateSet.dataRate[i] = usedRateRatios[i]; //equal to newLimit * SENDS_PER_SECOND - //Don't send anything new. - continue; - } - newLimit -= rateLimitOverload[i]; - virtualChannels[i]->tmSendLimitPerCycle = newLimit; - //Send new packets. - uint32_t tempRate = virtualChannels[i]->packetProcessing(); - if (tempRate > virtualChannels[i]->tmSendLimitPerCycle) { - rateLimitOverload[i] = tempRate - virtualChannels[i]->tmSendLimitPerCycle; - //VC is fully utilized, but not more. Overload will be accounted for in next cycles. - rateSet.dataRate[i] = virtualChannels[i]->tmSendLimitPerCycle * SENDS_PER_SECOND; - } else { - //Data rate extended to a Bytes/s range. Filtering is performed in controller. - rateSet.dataRate[i] = tempRate * SENDS_PER_SECOND; - rateLimitOverload[i] = 0; - } - } - rateSet.commit(PoolVariableIF::VALID); - return RETURN_OK; -} - -ReturnValue_t CCSDSHandler::packetProcessingCheck(void) { - ReturnValue_t status = RETURN_FAILED; - for (uint8_t vc = 0; vc < BoardHandler::USED_VIRTUAL_CHANNELS_PER_BOARD; - ++vc) { - status = this->virtualChannels[vc]->packetProcessingCheck(); - if (status != RETURN_OK) { - error << "CCSDSHandler " << std::hex << this->getObjectId() - << " ::packetProcessingCheck: Error on VC " << (uint16_t) vc - << ". Error code: " << status << std::dec << std::endl; - } - } - return RETURN_OK; -} - -ReturnValue_t CCSDSHandler::performOperation(void) { +ReturnValue_t CCSDSHandler::performOperation(uint8_t operationCode) { readCommandQueue(); handleTelemetry(); handleTelecommands(); return RETURN_OK; } -void CCSDSHandler::addVirtualChannel(VcId_t virtualChannelId, VirtualChannel* virtualChannel) { - auto status = virtualChannelMap.emplace(virtualChannelId, virtualChannel); - if (status.second == false) { - sif::warning << "CCSDSHandler::addVcInterface: Failed to add virtual channel with virtual " - << "channel id " << static_cast(virtualChannelId) << std::endl; - } -} - void CCSDSHandler::handleTelemetry() { VirtualChannelMapIter iter; - for (iter = virtualChannelMap.begin(); iter != VirtualChannelMap.end(); iter++) { - iter->second.virtualChannel->performOperation(); + for (iter = virtualChannelMap.begin(); iter != virtualChannelMap.end(); iter++) { + iter->second->performOperation(); } } @@ -135,374 +31,78 @@ void CCSDSHandler::handleTelecommands() { } -void CCSDSHandler::searchFrame() { - frameLength = this->boardHandler.findFrame(); - while (frameLength != 0) { - ReturnValue_t frame_status = this->dataLinkLayer.processFrame( - frameLength); - if (frame_status != RETURN_OK) { - triggerEvent(DataLinkLayer::FRAME_PROCESSING_FAILED, frame_status, - 0); - } - boardHandler.resetFrameBuffer(); - frameLength = boardHandler.findFrame(); - } -} - ReturnValue_t CCSDSHandler::initialize() { - PtmeIF *ptme = objectManager->get(ptmeId); + ReturnValue_t result = RETURN_OK; + PtmeIF* ptme = ObjectManager::instance()->get(ptmeId); if (ptme == nullptr) { + sif::warning << "Invalid PTME object" << std::endl; return ObjectManagerIF::CHILD_INIT_FAILED; } - status = boardHandler.initialize(channel); - if (status != RETURN_OK) { - return status; + + result = parameterHelper.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; } - status = modeHelper.initialize(); - if (status != RETURN_OK) { - return status; - } - status = healthHelper.initialize(); - if (status != HasReturnvaluesIF::RETURN_OK) { - return status; - } - status = memoryHelper.initialize(); - if (status != HasReturnvaluesIF::RETURN_OK) { - return status; - } - status = parameterHelper.initialize(); - if (status != HasReturnvaluesIF::RETURN_OK) { - return status; - } - status = powerSwitcher.initialize(objects::PCDU_HANDLER); - if (status != HasReturnvaluesIF::RETURN_OK) { - return status; - } - StorageManagerIF* tmStore = objectManager->get( - objects::TM_STORE); - status = dataLinkLayer.initialize(); - if ((tmStore != NULL) && status == RETURN_OK) { - status = RETURN_OK; - for (uint8_t i = 0; i < BoardHandler::USED_VIRTUAL_CHANNELS_PER_BOARD; - ++i) { -// this->virtualChannels[i] = objectManager->get( -// objects::CCSDS_VC_BASE + i); - if (this->virtualChannels[i] != NULL) { - this->virtualChannels[i]->setPacketStore(tmStore); - this->virtualChannels[i]->setBoardHandler(&this->boardHandler); - } else { - status = RETURN_FAILED; - } - } - } else { - status = RETURN_FAILED; - error << "CCSDSHandler " << std::hex << this->getObjectId() << std::dec - << " ::CCSDSHandler: Configuration failed." << std::endl; - } - status = fdir.initialize(); - if (status != HasReturnvaluesIF::RETURN_OK) { - return status; - } - return status; + return result; } void CCSDSHandler::readCommandQueue(void) { CommandMessage commandMessage; ReturnValue_t result = RETURN_FAILED; - result = commandQueue.receiveMessage(&commandMessage); + result = commandQueue->receiveMessage(&commandMessage); if (result == RETURN_OK) { result = parameterHelper.handleParameterMessage(&commandMessage); if (result == RETURN_OK) { return; } CommandMessage reply; - reply.setReplyRejected(CommandMessage::UNKNOW_COMMAND, + reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, commandMessage.getCommand()); - commandQueue.reply(&reply); + commandQueue->reply(&reply); } } MessageQueueId_t CCSDSHandler::getCommandQueue() const { - return commandQueue.getId(); + return commandQueue->getId(); } -void CCSDSHandler::flushTmChannels() { - for (uint8_t i = 0; i < BoardHandler::USED_VIRTUAL_CHANNELS_PER_BOARD; - ++i) { - virtualChannels[i]->flush(); - } -} +void CCSDSHandler::addVirtualChannel(VcId_t vcId, VirtualChannel* virtualChannel) { + if (vcId > config::NUMBER_OF_VIRTUAL_CHANNELS) { + sif::warning << "CCSDSHandler::addVirtualChannel: Invalid virtual channel ID" << std::endl; + return; + } -ReturnValue_t CCSDSHandler::handleMemoryLoad(uint32_t address, - const uint8_t* data, uint32_t size, uint8_t** dataPointer) { - if (size != 4) { - return INVALID_SIZE; - } - ReturnValue_t result = boardHandler.manualWriteToRegister(address, data); - if (result == RETURN_OK) { - pendingWrite = true; - return DO_IT_MYSELF; - } - return result; -} + if (virtualChannel == nullptr) { + sif::warning << "CCSDSHandler::addVirtualChannel: Invalid virtual channel interface" << std::endl; + return; + } -ReturnValue_t CCSDSHandler::handleMemoryDump(uint32_t address, uint32_t size, - uint8_t** dataPointer, uint8_t* dumpTarget) { - if (size != 4) { - return INVALID_SIZE; - } - ReturnValue_t result = boardHandler.sendRegisterReadCommand(address); - if (result == RETURN_OK) { - pendingRead = true; - return DO_IT_MYSELF; - } - return result; -} - -ReturnValue_t CCSDSHandler::checkModeCommand(Mode_t commandedMode, - Submode_t commandedSubmode, uint32_t* msToReachTheMode) { - if (state != STATE_IDLE) { - return IN_TRANSITION; - } - switch (commandedMode) { - case MODE_ON: - if ((commandedSubmode == SUBMODE_ACTIVE) - || (commandedSubmode == SUBMODE_PASSIVE)) { - return RETURN_OK; - } else { - return INVALID_SUBMODE; - } - break; - case MODE_OFF: - if (commandedSubmode == SUBMODE_NONE) { - return RETURN_OK; - } else { - return INVALID_SUBMODE; - } - default: - return INVALID_MODE; - } -} - -void CCSDSHandler::startTransition(Mode_t commandedMode, - Submode_t commandedSubmode) { - if (commandedMode == mode) { - if (mode == MODE_ON) { - state = STATE_SELECT_SUBMODE; - } else { - //Turn off switch again anyway - state = STATE_TURN_OFF; - } - } else { - switch (commandedMode) { - case MODE_ON: - state = STATE_TURN_ON; - break; - case MODE_OFF: - state = STATE_TURN_OFF; - break; - default: - //Error case. Cannot happen? - error << "CCSDSHandler::startTransition: Invalid commanded mode: " - << commandedMode << std::endl; - return; - } - } - triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode); -} - -void CCSDSHandler::getMode(Mode_t* modeReturn, Submode_t* submodeReturn) { - *modeReturn = mode; - *submodeReturn = submode; -} - -void CCSDSHandler::setToExternalControl() { - healthHelper.setHealth(EXTERNAL_CONTROL); -} - -void CCSDSHandler::announceMode(bool recursive) { - triggerEvent(MODE_INFO, mode, submode); -} - -void CCSDSHandler::setParentQueue(MessageQueueId_t parentQueueId) { - modeHelper.setParentQueue(parentQueueId); - healthHelper.setParentQeueue(parentQueueId); - tmPartHealth.setParentQueue(parentQueueId); -} - -void CCSDSHandler::doStateMachine() { - ReturnValue_t status = RETURN_FAILED; - powerSwitcher.doStateMachine(); - switch (state) { - case STATE_IDLE: - //Do nothing? Do perform operation stuff? - break; - case STATE_TURN_ON: - powerSwitcher.turnOn(); - modeHelper.startTimer(powerSwitcher.getSwitchDelay()); - state = STATE_WAIT_ON; - break; - case STATE_WAIT_ON: - if (powerSwitcher.checkSwitchState() == RETURN_OK) { - modeHelper.startTimer(LINK_UP_DELAY_MS); - state = STATE_WAIT_LINK; - } - if (boardHandler.checkChannel() == RETURN_OK) { - boardHandler.startStateTranstion(); - state = STATE_INITIALIZE_BOARD; - } else { - if (modeHelper.isTimedOut()) { - triggerEvent(MODE_TRANSITION_FAILED, - PowerSwitchIF::SWITCH_TIMEOUT, state); - setMode(MODE_OFF, SUBMODE_NONE); - } - } - break; - case STATE_WAIT_LINK: - if (boardHandler.checkAndResetChannel() == RETURN_OK) { - boardHandler.startStateTranstion(); - state = STATE_INITIALIZE_BOARD; - } else { - if (modeHelper.isTimedOut()) { - triggerEvent(MODE_TRANSITION_FAILED, DeviceHandlerIF::TIMEOUT, - state); - setMode(MODE_OFF, SUBMODE_NONE); - } - } - break; - case STATE_INITIALIZE_BOARD: - status = boardHandler.initializeBoard(); - switch (status) { - case RETURN_OK: - state = STATE_SELECT_SUBMODE; - break; - case BoardHandler::IN_TRANSITION: - //cannot last forever, so just wait. - break; - default: - triggerEvent(MODE_TRANSITION_FAILED, status, state); - state = STATE_TURN_OFF; - break; - } - break; - case STATE_SELECT_SUBMODE: - boardHandler.startStateTranstion(); - if (modeHelper.commandedSubmode == SUBMODE_PASSIVE) { - state = STATE_WAIT_SUBMODE_PASSIVE; - } else { - state = STATE_WAIT_SUBMODE_ACTIVE; - } - break; - case STATE_WAIT_SUBMODE_PASSIVE: - //Just one wait cycle to get rid of pending TM. - state = STATE_DO_PASSIVATE; - break; - case STATE_DO_PASSIVATE: - status = boardHandler.tmPassivate(); - switch (status) { - case RETURN_OK: - setMode(MODE_ON, SUBMODE_PASSIVE); - break; - case BoardHandler::IN_TRANSITION: - //cannot last forever, so just wait. - break; - default: - //If it comes here and fails then, there might be something wrong with the board. - triggerEvent(MODE_TRANSITION_FAILED, status, state); - state = STATE_TURN_OFF; - break; - } - break; - case STATE_WAIT_SUBMODE_ACTIVE: - status = boardHandler.tmActivate(); - switch (status) { - case RETURN_OK: - setMode(MODE_ON, SUBMODE_ACTIVE); - break; - case BoardHandler::IN_TRANSITION: - //cannot last forever, so just wait. - break; - default: - //If it comes here and fails then, there might be something wrong with the board. - triggerEvent(MODE_TRANSITION_FAILED, status, state); - state = STATE_TURN_OFF; - break; - } - break; - case STATE_TURN_OFF: - //Passivate first. Mainly optimization for System Testbed. - boardHandler.startStateTranstion(); - state = STATE_DO_PASSIVATE_OFF; - //No break - case STATE_DO_PASSIVATE_OFF: - status = boardHandler.tmPassivate(); - switch (status) { - case RETURN_OK: - state = STATE_TURN_SWITCH_OFF; - break; - case BoardHandler::IN_TRANSITION: - //cannot last forever, so just wait. - break; - default: - //If it comes here and fails then, there might be something wrong with the board. - //Just turn it off. - state = STATE_TURN_SWITCH_OFF; - break; - } - break; - case STATE_TURN_SWITCH_OFF: - powerSwitcher.turnOff(); - modeHelper.startTimer(powerSwitcher.getSwitchDelay()); - state = STATE_WAIT_OFF; - break; - case STATE_WAIT_OFF: - if ((boardHandler.checkAndResetChannel() == RMAPChannelIF::LINK_DOWN) - || (powerSwitcher.checkSwitchState() == RETURN_OK)) { - setMode(MODE_OFF, SUBMODE_NONE); - state = STATE_IDLE; - } else { - if (modeHelper.isTimedOut()) { - triggerEvent(MODE_TRANSITION_FAILED, status, state); - setMode(mode, submode); - } - } - break; - default: - break; - } -} - -ReturnValue_t CCSDSHandler::addVirtualChannel(uint8_t virtualChannelId, - VirtualChannelReceptionIF* object) { - return this->dataLinkLayer.addVirtualChannel(virtualChannelId, object); -} - -void CCSDSHandler::setMode(Mode_t newMode, Submode_t newSubmode) { - triggerEvent(MODE_INFO, newMode, newSubmode); - if (newMode == MODE_OFF) { - boardHandler.setDataPoolVaraiblesInvalid(); - } - modeHelper.modeChanged(newMode, newSubmode); - state = STATE_IDLE; - mode = newMode; - submode = newSubmode; -} - -Mode_t CCSDSHandler::getMode() const { - return mode; -} - -Submode_t CCSDSHandler::getSubmode() const { - return submode; + auto status = virtualChannelMap.emplace(vcId, virtualChannel); + if (status.second == false) { + sif::warning << "CCSDSHandler::addVirtualChannel: Failed to add virtual channel to " + "virtual channel map" << std::endl; + return; + } } MessageQueueId_t CCSDSHandler::getReportReceptionQueue(uint8_t virtualChannel) { if (virtualChannel < config::NUMBER_OF_VIRTUAL_CHANNELS) { - return virtualChannels[virtualChannel]->getReportReceptionQueue(); + VirtualChannelMapIter iter = virtualChannelMap.find(virtualChannel); + if (iter != virtualChannelMap.end()) { + return iter->second->getReportReceptionQueue(); + } + else { + sif::warning << "CCSDSHandler::getReportReceptionQueue: Virtual channel with ID " + << static_cast(virtualChannel) << " not in virtual channel map" + << std::endl; + return MessageQueueIF::NO_QUEUE; + } } else { sif::debug << "CCSDSHandler::getReportReceptionQueue: Invalid virtual channel requested"; + } + return MessageQueueIF::NO_QUEUE; } ReturnValue_t CCSDSHandler::getParameter(uint8_t domainId, uint8_t uniqueIdentifier, diff --git a/mission/tmtc/CCSDSHandler.h b/mission/tmtc/CCSDSHandler.h index 8780b4e8..05693a38 100644 --- a/mission/tmtc/CCSDSHandler.h +++ b/mission/tmtc/CCSDSHandler.h @@ -1,12 +1,13 @@ #ifndef CCSDSHANDLER_H_ #define CCSDSHANDLER_H_ -#include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/serviceinterface/serviceInterfaceDefintions.h" +#include "OBSWConfig.h" #include "fsfw/objectmanager/SystemObject.h" #include "fsfw/tasks/ExecutableObjectIF.h" #include "fsfw/returnvalues/HasReturnvaluesIF.h" #include "fsfw/parameters/ParameterHelper.h" +#include "VirtualChannel.h" +#include /** * @brief This class handles the data exchange with the CCSDS IP cores implemented in the @@ -20,63 +21,20 @@ class CCSDSHandler: public SystemObject, public HasReturnvaluesIF, public ReceivesParameterMessagesIF { public: - static const uint32_t LINK_UP_DELAY_MS = 2000; //!< The maximum time it takes to reconfigure the CCSDS Board. - static const uint32_t MAX_FRAME_SIZE = 1024; - static const Submode_t SUBMODE_ACTIVE = 1; //!< Submode where the TM part of the board is on. - static const Submode_t SUBMODE_PASSIVE = 0; //!< Submode where the TM part of the board is off. - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CCSDS_BOARD; - static const Event CCSDS_BOARD_RESET_FAILED = MAKE_EVENT(0, SEVERITY::LOW); //!> Resetting the communication channel failed. Severity LOW, par1: returnCode, par2: 0 - static const Event CCSDS_BOARD_SWITCHED = MAKE_EVENT(1, SEVERITY::INFO); //!> Switched active CCSDS-Board. Par1: objectId of now active board, Par2: objectId of now passive board. + using VcId_t = uint8_t; - static const ActionId_t SET_DATA_RATE_RATIO = 1; - static const float SENDS_PER_SECOND = 2.5; - static const uint32_t MINIMUM_BYTES_PER_SECOND = - (VCGeneration::IDLE_PACKET_SIZE - / (VCGeneration::DEFAULT_IDLE_INTERVAL / 1000)) + 1; //!< +1 to be on the safe side. - static const float DEFAULT_RATES[BoardHandler::USED_VIRTUAL_CHANNELS_PER_BOARD]; - static const uint32_t DEFAULT_BYTES_PER_SECOND = 1300; + /** + * @brief Constructor + * + * @param objectId Object ID of the CCSDS handler + * @param ptmeId Object ID of the PTME object providing access to the PTME IP Core. + */ + CCSDSHandler(object_id_t objectId, object_id_t ptmeId); - HealthDevice tmPartHealth; //!< A helper device to dedicatetly set the telemetry part to not healthy. - /** - * Main Constructor of the class. - * Initializes all attributes with default values. Sets the frame buffer to zero. - * Creates all TM Virtual Channels (with \c new). Initialization of communication partners - * is done in the #initialize routine. - * @param setObjectId Object identifier of the class. - * @param setSwitchId1 Switch id of the first switch of the board. - * @param setSwitchId2 Switch id of the second switch of the board. - * @param set_channel RMAP channel identifier. This is forwarded to the #boardHandler class. - * @param set_scid Configured SpaceCraft Identifier. Is forwarded to #boardHandler and #dataLinkLayer class. - */ - CCSDSHandler(object_id_t setObjectId, uint8_t setSwitchId1, - uint8_t setSwitchId2, object_id_t setChannel, uint16_t setSCID, - BoardHandler::DataPoolIds setPool); - /** - * The destructor deletes all TM Virtual Channels. - */ ~CCSDSHandler(); - /** - * Main executing method of the CCSDS Board handling. - * The method coordinates reading and writing of buffers and registers on the CCSDS Board - * as well as checking communication states and looking for frames. The state machine is - * executed here as well. To ensure a smooth communication without much delay, the last read - * and write calls are checked in the beginning and new requests as well as the state machine - * are issued in the end. - * @return Always returns #RETURN_OK. - */ - ReturnValue_t performOperation(void); - ReturnValue_t handleMemoryLoad(uint32_t address, const uint8_t* data, - uint32_t size, uint8_t** dataPointer); - ReturnValue_t handleMemoryDump(uint32_t address, uint32_t size, - uint8_t** dataPointer, uint8_t* dumpTarget); - /** - * Initialization routine of the class. - * It initializes connections to the power unit and to the Telemetry store which is set for - * every TM Virtual Channel. - * @return - */ + ReturnValue_t performOperation(uint8_t operationCode = 0) override; ReturnValue_t initialize(); MessageQueueId_t getCommandQueue() const; @@ -85,74 +43,31 @@ public: * * @param virtualChannelId ID of the virtual channel to add * @param virtualChannel Pointer to virtual channel object - * - * @return RETURN_OK if successful, otherwise RETURN_FAILED */ void addVirtualChannel(VcId_t virtualChannelId, VirtualChannel* virtualChannel); - Mode_t getMode() const; - Submode_t getSubmode() const; - void setParentQueue(MessageQueueId_t parentQueueId); MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0); - ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier, ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues, uint16_t startAtIndex); -protected: - MessageQueue commandQueue; //!< Queue to receive control commands. - VCGeneration* virtualChannels[BoardHandler::USED_VIRTUAL_CHANNELS_PER_BOARD];//!< An array of VCGeneration classes which each manage on TM Virtual Channel. - uint32_t rateLimitOverload[BoardHandler::USED_VIRTUAL_CHANNELS_PER_BOARD];//!< Used to smooth data rate in case large packets are sent. - /** - * This method reads the command queue and initializes a state transition if a command of this type was found. - */ - void readCommandQueue(void); - - /** - * This method flushes all pending messages in the TM queue by calling the \c flush method of - * all #virtualChannels. - * This is necessary to avoid doubled TM packets if the TM sender issues its messages to both the - * nominal and redundant CCSDS Board. - */ - void flushTmChannels(); - /** - * This is a helper method to print the current content of the frame buffers. - */ - void printFrameBuffer(void); - /** - * This is an important method which triggers searching for and handling found frames. - * It first calls the boardHandler method to find a frame in the received data. If a - * well-formed frame was found it calls the #dataLinkLayer class to process the frame - */ - void searchFrame(); - /** - * Calls the packet processing routine of each TM Virtual Channel. - * This triggers reception of incoming packets from the OBSW and forwarding to the CCSDS Board. - * There are different sending strategies for forwarding the packets to the board. - * @return Returns #RETURN_OK or the status of the failed virtual channel method. - */ - ReturnValue_t packetProcessing(void); - /** - * With this method the successful forwarding of Telemetry to the TM Virtual Channels is checked. - * The method calls the check routine of each virtual channel. - * @return Returns #RETURN_OK or the status of the failed virtual channel method. - */ - ReturnValue_t packetProcessingCheck(void); - - ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, - uint32_t *msToReachTheMode); - void startTransition(Mode_t mode, Submode_t submode); - void getMode(Mode_t *mode, Submode_t *submode); - void setToExternalControl(); - void announceMode(bool recursive); private: - using VcId_t = uint8_t; - using VirtualChannelMap = std::unordered_map; + static const uint32_t QUEUE_SIZE = config::CCSDS_HANDLER_QUEUE_SIZE; + + using VirtualChannelMap = std::unordered_map; using VirtualChannelMapIter = VirtualChannelMap::iterator; VirtualChannelMap virtualChannelMap; + // Object ID of PTME object + object_id_t ptmeId; + + MessageQueueIF* commandQueue = nullptr; + + ParameterHelper parameterHelper; + + void readCommandQueue(void); void handleTelemetry(); void handleTelecommands(); }; diff --git a/mission/tmtc/CMakeLists.txt b/mission/tmtc/CMakeLists.txt new file mode 100644 index 00000000..7da87b6c --- /dev/null +++ b/mission/tmtc/CMakeLists.txt @@ -0,0 +1,6 @@ +target_sources(${TARGET_NAME} PUBLIC + CCSDSHandler.cpp + VirtualChannel.cpp +) + + diff --git a/mission/tmtc/VirtualChannel.cpp b/mission/tmtc/VirtualChannel.cpp index 8e106de1..1f8f5ffb 100644 --- a/mission/tmtc/VirtualChannel.cpp +++ b/mission/tmtc/VirtualChannel.cpp @@ -1,13 +1,11 @@ #include "CCSDSHandler.h" +#include "VirtualChannel.h" #include "OBSWConfig.h" #include "fsfw/serviceinterface/ServiceInterfaceStream.h" #include "fsfw/objectmanager/ObjectManager.h" - - -#include - -#include +#include "fsfw/tmtcservices/TmTcMessage.h" +#include "fsfw/ipc/QueueFactory.h" VirtualChannel::VirtualChannel(uint8_t vcId, uint32_t tmQueueDepth) : @@ -22,10 +20,11 @@ ReturnValue_t VirtualChannel::initialize() { sif::error << "VirtualChannel::initialize: Failed to get tm store" << std::endl; return RETURN_FAILED; } + return RETURN_OK; } ReturnValue_t VirtualChannel::performOperation() { - ReturnValue_t status = RETURN_OK; + ReturnValue_t result = RETURN_OK; TmTcMessage message; while(tmQueue->receiveMessage(&message) == RETURN_OK) { @@ -41,7 +40,7 @@ ReturnValue_t VirtualChannel::performOperation() { } if (linkIsUp) { - result = ptme->writeToVc(virtualChannleId, data, size); + result = ptme->writeToVc(vcId, data, size); } tmStore->deleteData(storeId); @@ -54,7 +53,7 @@ ReturnValue_t VirtualChannel::performOperation() { } MessageQueueId_t VirtualChannel::getReportReceptionQueue(uint8_t virtualChannel) { - return tmQueue.getId(); + return tmQueue->getId(); } void VirtualChannel::setPtmeObject(PtmeIF* ptme) { @@ -64,17 +63,6 @@ void VirtualChannel::setPtmeObject(PtmeIF* ptme) { ptme = ptme; } -void VirtualChannel::setIdlePacketIntervalMs(uint32_t idlePacketIntervalMs) { - timer.timeout = idlePacketIntervalMs; -} - -ReturnValue_t VirtualChannel::flush() { - TmTcMessage message; - ReturnValue_t status = RETURN_FAILED; - for (status = tmQueue.receiveMessage(&message); status == RETURN_OK; - status = tmQueue.receiveMessage(&message)) { - packetStore->deleteData(message.getStorageId()); - } - boardHandler->resetVC(virtualChannelId); - return status; +void VirtualChannel::setLinkState(bool linkIsUp) { + linkIsUp = linkIsUp; } diff --git a/mission/tmtc/VirtualChannel.h b/mission/tmtc/VirtualChannel.h index cba4b0b4..d897e2d6 100644 --- a/mission/tmtc/VirtualChannel.h +++ b/mission/tmtc/VirtualChannel.h @@ -4,33 +4,16 @@ #include "fsfw/tmtcservices/AcceptsTelemetryIF.h" #include "fsfw/returnvalues/HasReturnvaluesIF.h" #include - -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include /** - * @brief This class represents a virtual channel in the software. + * @brief This class represents a virtual channel. Sending a tm message to an object of this class + * will forward the tm packet to the respective virtual channel of the PTME IP Core. * * @author J. Meier */ class VirtualChannel: public AcceptsTelemetryIF, public HasReturnvaluesIF { public: - - uint32_t tmSendLimitPerCycle; //!< Current maximum bytes per cycle. - - static const uint32_t IDLE_INTERVAL_RT_CHANNEL = 2000; //!< Real Time channel (VC 0) idle interval. - - static const uint16_t IDLE_PACKET_SIZE = 1015; //!< Size of generated idle packets. - - static const uint32_t DEFAULT_IDLE_INTERVAL = 20000; //!< Default if too lazy to set. - /** * @brief Constructor * @@ -40,28 +23,7 @@ class VirtualChannel: public AcceptsTelemetryIF, public HasReturnvaluesIF { VirtualChannel(uint8_t vcId, uint32_t tmQueueDepth); ReturnValue_t initialize(); - - /** - * One of the main public methods. - * Checks the tmQueue, calls #handlePacket if packets were found and keeps track of the number of sent bytes, - * to stop transmission before a buffer overflow occurs. If no packets were sent, an idle packet is generated. - * @return Number of sent bytes. 0 if an error occurred. - */ - uint32_t packetProcessing(void); - /** - * Another important method to check successful forwarding of packets. - * Checks how many packets have been forwarded to the CCSDS Board and tries to get as many - * RMAP write replys. The pending messages are deleted here. - * @return @c RETURN_OK on success, or one of many error codes, mainly coming from @c receiveVCAcknowledge. - */ - ReturnValue_t packetProcessingCheck(void); - /** - * Setter. - * @param setStore Sets the #packetStore used. - */ - void setPacketStore(StorageManagerIF* setStore); - MessageQueueId_t getReportReceptionQueue(); - + MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) override; ReturnValue_t performOperation(); /** @@ -69,42 +31,21 @@ class VirtualChannel: public AcceptsTelemetryIF, public HasReturnvaluesIF { * * @param ptme Pointer to ptme object */ - void setPtmeObject(Ptme* ptme); + void setPtmeObject(PtmeIF* ptme); + + /** + * @brief Can be used by the owner to set the link state. Packets will be discarded if link + * to ground station is down. + */ + void setLinkState(bool linkIsUp); private: PtmeIF* ptme = nullptr; MessageQueueIF* tmQueue = nullptr; - uint8_t virtualChannelId; + uint8_t vcId; bool linkIsUp; StorageManagerIF* tmStore = nullptr; - - - BoardHandler* boardHandler; //!< A reference to the "hardware part" of handling the packets. - store_address_t pendingTm[BoardHandler::TM_PACKETS_PER_CALL_PER_CHANNEL]; //!< List of packets sent to the board. Is used to check if all Space Packets sent received the CCSDS Board. - uint16_t sendCount; //!< Counter to identify how many packets have been sent coming in to the board (without Idle Packets). - Countdown timer; - SpacePacket idlePacket; - uint32_t accumulatedByteCount; - - store_address_t pendingPacket; - - static const uint32_t TM_SEND_LIMIT_PER_CYCLE = 1300; //!< The maximum number of bytes to send to the CCSDS Board VC per cycle. - - /** - * Helper method to send an idle packet. - * @return @c RETURN_OK on success, @c RETURN_FAILED otherwise. - */ - ReturnValue_t sendIdlePacket(uint32_t size); - /** - * A helper method to handle incoming packets. - * Reads a packet from #packetStore and tries to forward it to the CCSDS BoardHandler class. - * Calls the hardware layer with @c writeToVc. Depending on what the "hardware" layer does, - * it stores the sent packet id's to find out if they were all received by the CCSDS Board. - * @param store_id ID of a packet in the #packetStore. - * @return @c RETURN_OK on success, the return code of @c writeToVc otherwise. - */ - ReturnValue_t handlePacket(store_address_t storeId); }; #endif /* VIRTUALCHANNEL_H_ */ diff --git a/mission/utility/TmFunnel.cpp b/mission/utility/TmFunnel.cpp index d718f6cf..5838ae75 100644 --- a/mission/utility/TmFunnel.cpp +++ b/mission/utility/TmFunnel.cpp @@ -99,12 +99,12 @@ ReturnValue_t TmFunnel::initialize() { return ObjectManagerIF::CHILD_INIT_FAILED; } -#if OBSW_USE_PTME_IP_CORE == 1 +#if OBSW_TM_TO_PTME == 1 // Live TM will be sent via the virtual channel 0 tmQueue->setDefaultDestination(tmTarget->getReportReceptionQueue(0)); #else tmQueue->setDefaultDestination(tmTarget->getReportReceptionQueue()); -#endif /* OBSW_USE_CCSDS_IP_CORES == 1 */ +#endif /* OBSW_TM_TO_PTME == 1 */ // Storage destination is optional. if(storageDestination == objects::NO_OBJECT) {