refactored TM funnels to allow multiple TM recipients #312

Merged
meierj merged 5 commits from mueller/tm_funnel_improvements into develop 2022-11-02 13:10:43 +01:00
40 changed files with 262 additions and 167 deletions

View File

@ -10,6 +10,9 @@ list yields a list of all related PRs for each release.
# [unreleased] # [unreleased]
- Extended TM funnels to allow multiple TM recipients.
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/312
# [v1.15.0] 27.10.2022 # [v1.15.0] 27.10.2022
- Consistent device file naming - Consistent device file naming

View File

@ -4,7 +4,7 @@
#include <fsfw/tmtcservices/PusServiceBase.h> #include <fsfw/tmtcservices/PusServiceBase.h>
#include <mission/controller/ThermalController.h> #include <mission/controller/ThermalController.h>
#include <mission/core/GenericFactory.h> #include <mission/core/GenericFactory.h>
#include <mission/tmtc/TmFunnel.h> #include <mission/tmtc/TmFunnelHandler.h>
#include <objects/systemObjectList.h> #include <objects/systemObjectList.h>
#include <tmtc/pusIds.h> #include <tmtc/pusIds.h>
@ -59,7 +59,9 @@ void Factory::setStaticFrameworkObjectIds() {
void ObjectFactory::produce(void* args) { void ObjectFactory::produce(void* args) {
Factory::setStaticFrameworkObjectIds(); Factory::setStaticFrameworkObjectIds();
ObjectFactory::produceGenericObjects(); PusTmFunnel* pusFunnel;
CfdpTmFunnel* cfdpFunnel;
ObjectFactory::produceGenericObjects(nullptr, &pusFunnel, &cfdpFunnel);
dummy::DummyCfg cfg; dummy::DummyCfg cfg;
dummy::createDummies(cfg); dummy::createDummies(cfg);

View File

@ -30,11 +30,11 @@
#include "linux/devices/ploc/PlocSupervisorHandler.h" #include "linux/devices/ploc/PlocSupervisorHandler.h"
#include "linux/devices/startracker/StarTrackerHandler.h" #include "linux/devices/startracker/StarTrackerHandler.h"
#include "linux/devices/startracker/StrHelper.h" #include "linux/devices/startracker/StrHelper.h"
#include "linux/obc/AxiPtmeConfig.h" #include "linux/ipcore/AxiPtmeConfig.h"
#include "linux/obc/PapbVcInterface.h" #include "linux/ipcore/PapbVcInterface.h"
#include "linux/obc/PdecHandler.h" #include "linux/ipcore/PdecHandler.h"
#include "linux/obc/Ptme.h" #include "linux/ipcore/Ptme.h"
#include "linux/obc/PtmeConfig.h" #include "linux/ipcore/PtmeConfig.h"
#include "mission/csp/CspCookie.h" #include "mission/csp/CspCookie.h"
#include "mission/system/fdir/AcsBoardFdir.h" #include "mission/system/fdir/AcsBoardFdir.h"
#include "mission/system/fdir/GomspacePowerFdir.h" #include "mission/system/fdir/GomspacePowerFdir.h"
@ -92,8 +92,8 @@
#include "mission/devices/devicedefinitions/SyrlinksDefinitions.h" #include "mission/devices/devicedefinitions/SyrlinksDefinitions.h"
#include "mission/devices/devicedefinitions/payloadPcduDefinitions.h" #include "mission/devices/devicedefinitions/payloadPcduDefinitions.h"
#include "mission/system/objects/AcsBoardAssembly.h" #include "mission/system/objects/AcsBoardAssembly.h"
#include "mission/tmtc/CCSDSHandler.h" #include "mission/tmtc/CcsdsIpCoreHandler.h"
#include "mission/tmtc/TmFunnel.h" #include "mission/tmtc/TmFunnelHandler.h"
#include "mission/tmtc/VirtualChannel.h" #include "mission/tmtc/VirtualChannel.h"
ResetArgs RESET_ARGS_GNSS; ResetArgs RESET_ARGS_GNSS;
@ -705,7 +705,8 @@ void ObjectFactory::createReactionWheelComponents(LinuxLibgpioIF* gpioComIF,
#endif /* OBSW_ADD_RW == 1 */ #endif /* OBSW_ADD_RW == 1 */
} }
ReturnValue_t ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF) { ReturnValue_t ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF,
CcsdsIpCoreHandler** ipCoreHandler) {
using namespace gpio; using namespace gpio;
// GPIO definitions of signals connected to the virtual channel interfaces of the PTME IP Core // GPIO definitions of signals connected to the virtual channel interfaces of the PTME IP Core
GpioCookie* gpioCookiePtmeIp = new GpioCookie; GpioCookie* gpioCookiePtmeIp = new GpioCookie;
@ -768,18 +769,19 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF) {
#else #else
static const uint32_t TRANSMITTER_TIMEOUT = 900000; // 15 minutes static const uint32_t TRANSMITTER_TIMEOUT = 900000; // 15 minutes
#endif #endif
CCSDSHandler* ccsdsHandler = new CCSDSHandler( *ipCoreHandler = new CcsdsIpCoreHandler(
objects::CCSDS_HANDLER, objects::PTME, objects::CCSDS_PACKET_DISTRIBUTOR, ptmeConfig, objects::CCSDS_HANDLER, objects::PTME, objects::CCSDS_PACKET_DISTRIBUTOR, ptmeConfig,
gpioComIF, gpioIds::RS485_EN_TX_CLOCK, gpioIds::RS485_EN_TX_DATA, TRANSMITTER_TIMEOUT); gpioComIF, gpioIds::RS485_EN_TX_CLOCK, gpioIds::RS485_EN_TX_DATA, TRANSMITTER_TIMEOUT);
VirtualChannel* vc = nullptr; VirtualChannel* vc = nullptr;
vc = new VirtualChannel(ccsds::VC0, common::VC0_QUEUE_SIZE, objects::CCSDS_HANDLER); vc = new VirtualChannel(ccsds::VC0, common::VC0_QUEUE_SIZE, objects::CCSDS_HANDLER);
ccsdsHandler->addVirtualChannel(ccsds::VC0, vc); (*ipCoreHandler)->addVirtualChannel(ccsds::VC0, vc);
vc = new VirtualChannel(ccsds::VC1, common::VC1_QUEUE_SIZE, objects::CCSDS_HANDLER); vc = new VirtualChannel(ccsds::VC1, common::VC1_QUEUE_SIZE, objects::CCSDS_HANDLER);
ccsdsHandler->addVirtualChannel(ccsds::VC1, vc); (*ipCoreHandler)->addVirtualChannel(ccsds::VC1, vc);
vc = new VirtualChannel(ccsds::VC2, common::VC2_QUEUE_SIZE, objects::CCSDS_HANDLER); vc = new VirtualChannel(ccsds::VC2, common::VC2_QUEUE_SIZE, objects::CCSDS_HANDLER);
ccsdsHandler->addVirtualChannel(ccsds::VC2, vc); (*ipCoreHandler)->addVirtualChannel(ccsds::VC2, vc);
vc = new VirtualChannel(ccsds::VC3, common::VC3_QUEUE_SIZE, objects::CCSDS_HANDLER); vc = new VirtualChannel(ccsds::VC3, common::VC3_QUEUE_SIZE, objects::CCSDS_HANDLER);
ccsdsHandler->addVirtualChannel(ccsds::VC3, vc); (*ipCoreHandler)->addVirtualChannel(ccsds::VC3, vc);
GpioCookie* gpioCookiePdec = new GpioCookie; GpioCookie* gpioCookiePdec = new GpioCookie;
consumer.str(""); consumer.str("");
consumer << "0x" << std::hex << objects::PDEC_HANDLER; consumer << "0x" << std::hex << objects::PDEC_HANDLER;

View File

@ -2,6 +2,9 @@
#define BSP_Q7S_OBJECTFACTORY_H_ #define BSP_Q7S_OBJECTFACTORY_H_
#include <fsfw/returnvalues/returnvalue.h> #include <fsfw/returnvalues/returnvalue.h>
#include <mission/tmtc/CcsdsIpCoreHandler.h>
#include <mission/tmtc/CfdpTmFunnel.h>
#include <mission/tmtc/PusTmFunnel.h>
#include <string> #include <string>
@ -37,7 +40,7 @@ void createSolarArrayDeploymentComponents(PowerSwitchIF& pwrSwitcher, GpioIF& gp
void createSyrlinksComponents(PowerSwitchIF* pwrSwitcher); void createSyrlinksComponents(PowerSwitchIF* pwrSwitcher);
void createPayloadComponents(LinuxLibgpioIF* gpioComIF); void createPayloadComponents(LinuxLibgpioIF* gpioComIF);
void createReactionWheelComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF* pwrSwitcher); void createReactionWheelComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF* pwrSwitcher);
ReturnValue_t createCcsdsComponents(LinuxLibgpioIF* gpioComIF); ReturnValue_t createCcsdsComponents(LinuxLibgpioIF* gpioComIF, CcsdsIpCoreHandler** ipCoreHandler);
void createMiscComponents(); void createMiscComponents();
void createTestComponents(LinuxLibgpioIF* gpioComIF); void createTestComponents(LinuxLibgpioIF* gpioComIF);

View File

@ -17,7 +17,9 @@
void ObjectFactory::produce(void* args) { void ObjectFactory::produce(void* args) {
ObjectFactory::setStatics(); ObjectFactory::setStatics();
HealthTableIF* healthTable = nullptr; HealthTableIF* healthTable = nullptr;
ObjectFactory::produceGenericObjects(&healthTable); PusTmFunnel* pusFunnel = nullptr;
CfdpTmFunnel* cfdpFunnel = nullptr;
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel);
LinuxLibgpioIF* gpioComIF = nullptr; LinuxLibgpioIF* gpioComIF = nullptr;
UartComIF* uartComIF = nullptr; UartComIF* uartComIF = nullptr;
@ -75,7 +77,11 @@ void ObjectFactory::produce(void* args) {
createStrComponents(pwrSwitcher); createStrComponents(pwrSwitcher);
#endif /* OBSW_ADD_STAR_TRACKER == 1 */ #endif /* OBSW_ADD_STAR_TRACKER == 1 */
#if OBSW_ADD_CCSDS_IP_CORES == 1 #if OBSW_ADD_CCSDS_IP_CORES == 1
createCcsdsComponents(gpioComIF); CcsdsIpCoreHandler* ipCoreHandler = nullptr;
createCcsdsComponents(gpioComIF, &ipCoreHandler);
#if OBSW_TM_TO_PTME == 1
ObjectFactory::addTmtcIpCoresToFunnels(*ipCoreHandler, *pusFunnel, *cfdpFunnel);
#endif
#endif /* OBSW_ADD_CCSDS_IP_CORES == 1 */ #endif /* OBSW_ADD_CCSDS_IP_CORES == 1 */
/* Test Task */ /* Test Task */
#if OBSW_ADD_TEST_CODE == 1 #if OBSW_ADD_TEST_CODE == 1

View File

@ -16,7 +16,9 @@
void ObjectFactory::produce(void* args) { void ObjectFactory::produce(void* args) {
ObjectFactory::setStatics(); ObjectFactory::setStatics();
HealthTableIF* healthTable = nullptr; HealthTableIF* healthTable = nullptr;
ObjectFactory::produceGenericObjects(&healthTable); PusTmFunnel* pusFunnel = nullptr;
CfdpTmFunnel* cfdpFunnel = nullptr;
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel);
LinuxLibgpioIF* gpioComIF = nullptr; LinuxLibgpioIF* gpioComIF = nullptr;
UartComIF* uartComIF = nullptr; UartComIF* uartComIF = nullptr;
@ -62,7 +64,11 @@ void ObjectFactory::produce(void* args) {
createStrComponents(pwrSwitcher); createStrComponents(pwrSwitcher);
#endif /* OBSW_ADD_STAR_TRACKER == 1 */ #endif /* OBSW_ADD_STAR_TRACKER == 1 */
#if OBSW_ADD_CCSDS_IP_CORES == 1 #if OBSW_ADD_CCSDS_IP_CORES == 1
createCcsdsComponents(gpioComIF); CcsdsIpCoreHandler* ipCoreHandler = nullptr;
createCcsdsComponents(gpioComIF, &ipCoreHandler);
#if OBSW_TM_TO_PTME == 1
ObjectFactory::addTmtcIpCoresToFunnels(*ipCoreHandler, *pusFunnel, *cfdpFunnel);
#endif
#endif /* OBSW_ADD_CCSDS_IP_CORES == 1 */ #endif /* OBSW_ADD_CCSDS_IP_CORES == 1 */
#if OBSW_ADD_SCEX_DEVICE == 1 #if OBSW_ADD_SCEX_DEVICE == 1

View File

@ -4,6 +4,6 @@ add_subdirectory(callbacks)
add_subdirectory(boardtest) add_subdirectory(boardtest)
add_subdirectory(devices) add_subdirectory(devices)
add_subdirectory(fsfwconfig) add_subdirectory(fsfwconfig)
add_subdirectory(obc) add_subdirectory(ipcore)
target_sources(${OBSW_NAME} PUBLIC ObjectFactory.cpp InitMission.cpp) target_sources(${OBSW_NAME} PUBLIC ObjectFactory.cpp InitMission.cpp)

View File

@ -18,13 +18,14 @@
#include <mission/devices/SusHandler.h> #include <mission/devices/SusHandler.h>
#include <mission/system/fdir/RtdFdir.h> #include <mission/system/fdir/RtdFdir.h>
#include <mission/system/fdir/SusFdir.h> #include <mission/system/fdir/SusFdir.h>
#include <mission/system/objects/SusAssembly.h>
#include <mission/system/objects/TcsBoardAssembly.h>
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "devConf.h" #include "devConf.h"
#include "devices/addresses.h" #include "devices/addresses.h"
#include "devices/gpioIds.h" #include "devices/gpioIds.h"
#include "eive/definitions.h"
#include "mission/system/objects/SusAssembly.h"
#include "mission/system/objects/TcsBoardAssembly.h"
#include "mission/system/tree/acsModeTree.h" #include "mission/system/tree/acsModeTree.h"
void ObjectFactory::createSunSensorComponents(GpioIF* gpioComIF, SpiComIF* spiComIF, void ObjectFactory::createSunSensorComponents(GpioIF* gpioComIF, SpiComIF* spiComIF,
@ -354,3 +355,9 @@ void ObjectFactory::gpioChecker(ReturnValue_t result, std::string output) {
sif::error << "ObjectFactory: Adding GPIOs failed for " << output << std::endl; sif::error << "ObjectFactory: Adding GPIOs failed for " << output << std::endl;
} }
} }
void ObjectFactory::addTmtcIpCoresToFunnels(CcsdsIpCoreHandler& ipCoreHandler,
PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel) {
cfdpFunnel.addDestination(ipCoreHandler, config::LIVE_TM);
pusFunnel.addDestination(ipCoreHandler, config::LIVE_TM);
}

View File

@ -4,6 +4,9 @@
#include <fsfw/returnvalues/returnvalue.h> #include <fsfw/returnvalues/returnvalue.h>
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h> #include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
#include <mission/memory/SdCardMountedIF.h> #include <mission/memory/SdCardMountedIF.h>
#include <mission/tmtc/CcsdsIpCoreHandler.h>
#include <mission/tmtc/CfdpTmFunnel.h>
#include <mission/tmtc/PusTmFunnel.h>
#include <optional> #include <optional>
#include <string> #include <string>
@ -29,4 +32,7 @@ void gpioChecker(ReturnValue_t result, std::string output);
void createThermalController(); void createThermalController();
AcsController* createAcsController(bool connectSubsystem); AcsController* createAcsController(bool connectSubsystem);
void addTmtcIpCoresToFunnels(CcsdsIpCoreHandler& ipCoreHandler, PusTmFunnel& pusFunnel,
CfdpTmFunnel& cfdpFunnel);
} // namespace ObjectFactory } // namespace ObjectFactory

View File

@ -1,5 +1,5 @@
#include <fsfw_hal/linux/uio/UioMapper.h> #include <fsfw_hal/linux/uio/UioMapper.h>
#include <linux/obc/PapbVcInterface.h> #include <linux/ipcore/PapbVcInterface.h>
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"

View File

@ -6,7 +6,7 @@
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"
#include "linux/obc/VcInterfaceIF.h" #include "linux/ipcore/VcInterfaceIF.h"
/** /**
* @brief This class handles the transmission of data to a virtual channel of the PTME IP Core * @brief This class handles the transmission of data to a virtual channel of the PTME IP Core

View File

@ -1,5 +1,5 @@
#include <fcntl.h> #include <fcntl.h>
#include <linux/obc/Ptme.h> #include <linux/ipcore/Ptme.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <unistd.h> #include <unistd.h>

View File

@ -9,8 +9,8 @@
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"
#include "linux/obc/PtmeIF.h" #include "linux/ipcore/PtmeIF.h"
#include "linux/obc/VcInterfaceIF.h" #include "linux/ipcore/VcInterfaceIF.h"
/** /**
* @brief This class handles the interfacing to the telemetry (PTME) IP core responsible for the * @brief This class handles the interfacing to the telemetry (PTME) IP core responsible for the

View File

@ -4,7 +4,7 @@
#include "AxiPtmeConfig.h" #include "AxiPtmeConfig.h"
#include "fsfw/objectmanager/SystemObject.h" #include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"
#include "linux/obc/PtmeConfig.h" #include "linux/ipcore/PtmeConfig.h"
#include "returnvalues/classIds.h" #include "returnvalues/classIds.h"
/** /**

View File

@ -24,7 +24,7 @@
#include <fsfw_hal/host/HostFilesystem.h> #include <fsfw_hal/host/HostFilesystem.h>
#include <mission/tmtc/CfdpTmFunnel.h> #include <mission/tmtc/CfdpTmFunnel.h>
#include <mission/tmtc/PusTmFunnel.h> #include <mission/tmtc/PusTmFunnel.h>
#include <mission/tmtc/TmFunnel.h> #include <mission/tmtc/TmFunnelHandler.h>
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "eive/definitions.h" #include "eive/definitions.h"
@ -66,7 +66,8 @@ EiveFaultHandler EIVE_FAULT_HANDLER;
} // namespace cfdp } // namespace cfdp
void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_) { void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFunnel** pusFunnel,
CfdpTmFunnel** cfdpFunnel) {
// Framework objects // Framework objects
new EventManager(objects::EVENT_MANAGER); new EventManager(objects::EVENT_MANAGER);
auto healthTable = new HealthTable(objects::HEALTH_TABLE); auto healthTable = new HealthTable(objects::HEALTH_TABLE);
@ -98,12 +99,12 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_) {
#if OBSW_ADD_TCPIP_BRIDGE == 1 #if OBSW_ADD_TCPIP_BRIDGE == 1
#if OBSW_USE_TMTC_TCP_BRIDGE == 0 #if OBSW_USE_TMTC_TCP_BRIDGE == 0
auto tmtcBridge = new UdpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); auto tcpIpTmtcBridge = new UdpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
new UdpTcPollingTask(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE); new UdpTcPollingTask(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE);
sif::info << "Created UDP server for TMTC commanding with listener port " sif::info << "Created UDP server for TMTC commanding with listener port "
<< udpBridge->getUdpPort() << std::endl; << udpBridge->getUdpPort() << std::endl;
#else #else
auto tmtcBridge = new TcpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); auto tcpIpTmtcBridge = new TcpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
auto tcpServer = new TcpTmTcServer(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE); auto tcpServer = new TcpTmTcServer(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE);
// TCP is stream based. Use packet ID as start marker when parsing for space packets // TCP is stream based. Use packet ID as start marker when parsing for space packets
tcpServer->setSpacePacketParsingOptions({common::PUS_PACKET_ID, common::CFDP_PACKET_ID}); tcpServer->setSpacePacketParsingOptions({common::PUS_PACKET_ID, common::CFDP_PACKET_ID});
@ -113,23 +114,21 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_) {
tcpServer->enableWiretapping(true); tcpServer->enableWiretapping(true);
#endif /* OBSW_TCP_SERVER_WIRETAPPING == 1 */ #endif /* OBSW_TCP_SERVER_WIRETAPPING == 1 */
#endif /* OBSW_USE_TMTC_TCP_BRIDGE == 0 */ #endif /* OBSW_USE_TMTC_TCP_BRIDGE == 0 */
tmtcBridge->setMaxNumberOfPacketsStored(300); tcpIpTmtcBridge->setMaxNumberOfPacketsStored(300);
#endif /* OBSW_ADD_TCPIP_BRIDGE == 1 */ #endif /* OBSW_ADD_TCPIP_BRIDGE == 1 */
auto* ccsdsDistrib = auto* ccsdsDistrib =
new CcsdsDistributor(config::EIVE_PUS_APID, objects::CCSDS_PACKET_DISTRIBUTOR); new CcsdsDistributor(config::EIVE_PUS_APID, objects::CCSDS_PACKET_DISTRIBUTOR);
new PusDistributor(config::EIVE_PUS_APID, objects::PUS_PACKET_DISTRIBUTOR, ccsdsDistrib); new PusDistributor(config::EIVE_PUS_APID, objects::PUS_PACKET_DISTRIBUTOR, ccsdsDistrib);
uint8_t vc = 0; *cfdpFunnel = new CfdpTmFunnel(objects::CFDP_TM_FUNNEL, config::EIVE_CFDP_APID, *tmStore);
#if OBSW_TM_TO_PTME == 1 *pusFunnel = new PusTmFunnel(objects::PUS_TM_FUNNEL, *timeStamper, *tmStore);
vc = config::LIVE_TM; #if OBSW_ADD_TCPIP_BRIDGE == 1
(*cfdpFunnel)->addDestination(*tcpIpTmtcBridge, 0);
(*pusFunnel)->addDestination(*tcpIpTmtcBridge, 0);
#endif #endif
auto* cfdpFunnel =
new CfdpTmFunnel(objects::CFDP_TM_FUNNEL, config::EIVE_CFDP_APID, *tmtcBridge, *tmStore, vc);
auto* pusFunnel =
new PusTmFunnel(objects::PUS_TM_FUNNEL, *tmtcBridge, *timeStamper, *tmStore, vc);
// Every TM packet goes through this funnel // Every TM packet goes through this funnel
new TmFunnel(objects::TM_FUNNEL, *pusFunnel, *cfdpFunnel); new TmFunnelHandler(objects::TM_FUNNEL, **pusFunnel, **cfdpFunnel);
// PUS service stack // PUS service stack
new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION, config::EIVE_PUS_APID, new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION, config::EIVE_PUS_APID,
@ -165,7 +164,7 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_) {
new CfdpDistributor(distribCfg); new CfdpDistributor(distribCfg);
auto* msgQueue = QueueFactory::instance()->createMessageQueue(32); auto* msgQueue = QueueFactory::instance()->createMessageQueue(32);
FsfwHandlerParams params(objects::CFDP_HANDLER, HOST_FS, *cfdpFunnel, *tcStore, *tmStore, FsfwHandlerParams params(objects::CFDP_HANDLER, HOST_FS, **cfdpFunnel, *tcStore, *tmStore,
*msgQueue); *msgQueue);
cfdp::IndicationCfg indicationCfg; cfdp::IndicationCfg indicationCfg;
UnsignedByteField<uint16_t> apid(config::EIVE_LOCAL_CFDP_ENTITY_ID); UnsignedByteField<uint16_t> apid(config::EIVE_LOCAL_CFDP_ENTITY_ID);

View File

@ -2,10 +2,13 @@
#define MISSION_CORE_GENERICFACTORY_H_ #define MISSION_CORE_GENERICFACTORY_H_
class HealthTableIF; class HealthTableIF;
class PusTmFunnel;
class CfdpTmFunnel;
namespace ObjectFactory { namespace ObjectFactory {
void produceGenericObjects(HealthTableIF** healthTable = nullptr); void produceGenericObjects(HealthTableIF** healthTable, PusTmFunnel** pusFunnel,
CfdpTmFunnel** cfdpFunnel);
} }

View File

@ -1,3 +1,4 @@
target_sources( target_sources(
${LIB_EIVE_MISSION} PRIVATE CCSDSHandler.cpp VirtualChannel.cpp TmFunnel.cpp ${LIB_EIVE_MISSION}
CfdpTmFunnel.cpp PusTmFunnel.cpp) PRIVATE CcsdsIpCoreHandler.cpp VirtualChannel.cpp TmFunnelHandler.cpp
TmFunnelBase.cpp CfdpTmFunnel.cpp PusTmFunnel.cpp)

View File

@ -1,7 +1,7 @@
#include "CCSDSHandler.h" #include "CcsdsIpCoreHandler.h"
#include <linux/obc/PdecHandler.h> #include <linux/ipcore/PdecHandler.h>
#include <linux/obc/PtmeConfig.h> #include <linux/ipcore/PtmeConfig.h>
#include "fsfw/events/EventManagerIF.h" #include "fsfw/events/EventManagerIF.h"
#include "fsfw/ipc/QueueFactory.h" #include "fsfw/ipc/QueueFactory.h"
@ -11,9 +11,10 @@
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h" #include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
#include "mission/devices/devicedefinitions/SyrlinksDefinitions.h" #include "mission/devices/devicedefinitions/SyrlinksDefinitions.h"
CCSDSHandler::CCSDSHandler(object_id_t objectId, object_id_t ptmeId, object_id_t tcDestination, CcsdsIpCoreHandler::CcsdsIpCoreHandler(object_id_t objectId, object_id_t ptmeId,
PtmeConfig* ptmeConfig, GpioIF* gpioIF, gpioId_t enTxClock, object_id_t tcDestination, PtmeConfig* ptmeConfig,
gpioId_t enTxData, uint32_t transmitterTimeout) GpioIF* gpioIF, gpioId_t enTxClock, gpioId_t enTxData,
uint32_t transmitterTimeout)
: SystemObject(objectId), : SystemObject(objectId),
ptmeId(ptmeId), ptmeId(ptmeId),
tcDestination(tcDestination), tcDestination(tcDestination),
@ -30,9 +31,9 @@ CCSDSHandler::CCSDSHandler(object_id_t objectId, object_id_t ptmeId, object_id_t
QueueFactory::instance()->createMessageQueue(10, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs); QueueFactory::instance()->createMessageQueue(10, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
} }
CCSDSHandler::~CCSDSHandler() {} CcsdsIpCoreHandler::~CcsdsIpCoreHandler() {}
ReturnValue_t CCSDSHandler::performOperation(uint8_t operationCode) { ReturnValue_t CcsdsIpCoreHandler::performOperation(uint8_t operationCode) {
checkEvents(); checkEvents();
readCommandQueue(); readCommandQueue();
handleTelemetry(); handleTelemetry();
@ -41,16 +42,16 @@ ReturnValue_t CCSDSHandler::performOperation(uint8_t operationCode) {
return returnvalue::OK; return returnvalue::OK;
} }
void CCSDSHandler::handleTelemetry() { void CcsdsIpCoreHandler::handleTelemetry() {
VirtualChannelMapIter iter; VirtualChannelMapIter iter;
for (iter = virtualChannelMap.begin(); iter != virtualChannelMap.end(); iter++) { for (iter = virtualChannelMap.begin(); iter != virtualChannelMap.end(); iter++) {
iter->second->performOperation(); iter->second->performOperation();
} }
} }
void CCSDSHandler::handleTelecommands() {} void CcsdsIpCoreHandler::handleTelecommands() {}
ReturnValue_t CCSDSHandler::initialize() { ReturnValue_t CcsdsIpCoreHandler::initialize() {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
PtmeIF* ptme = ObjectManager::instance()->get<PtmeIF>(ptmeId); PtmeIF* ptme = ObjectManager::instance()->get<PtmeIF>(ptmeId);
if (ptme == nullptr) { if (ptme == nullptr) {
@ -62,7 +63,7 @@ ReturnValue_t CCSDSHandler::initialize() {
ObjectManager::instance()->get<AcceptsTelecommandsIF>(tcDestination); ObjectManager::instance()->get<AcceptsTelecommandsIF>(tcDestination);
if (tcDistributor == nullptr) { if (tcDistributor == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "CCSDSHandler::initialize: Invalid TC Distributor object" << std::endl; sif::error << "CcsdsHandler::initialize: Invalid TC Distributor object" << std::endl;
#endif #endif
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
@ -91,14 +92,14 @@ ReturnValue_t CCSDSHandler::initialize() {
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER); EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
if (manager == nullptr) { if (manager == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "CCSDSHandler::initialize: Invalid event manager" << std::endl; sif::error << "CcsdsHandler::initialize: Invalid event manager" << std::endl;
#endif #endif
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
result = manager->registerListener(eventQueue->getId()); result = manager->registerListener(eventQueue->getId());
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "CCSDSHandler::initialize: Failed to register CCSDS handler as event " sif::warning << "CcsdsHandler::initialize: Failed to register CCSDS handler as event "
"listener" "listener"
<< std::endl; << std::endl;
#endif #endif
@ -110,7 +111,7 @@ ReturnValue_t CCSDSHandler::initialize() {
event::getEventId(PdecHandler::BIT_LOCK_PDEC)); event::getEventId(PdecHandler::BIT_LOCK_PDEC));
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "CCSDSHandler::initialize: Failed to subscribe to events from PDEC " sif::error << "CcsdsHandler::initialize: Failed to subscribe to events from PDEC "
"handler" "handler"
<< std::endl; << std::endl;
#endif #endif
@ -136,7 +137,7 @@ ReturnValue_t CCSDSHandler::initialize() {
return result; return result;
} }
void CCSDSHandler::readCommandQueue(void) { void CcsdsIpCoreHandler::readCommandQueue(void) {
CommandMessage commandMessage; CommandMessage commandMessage;
ReturnValue_t result = returnvalue::FAILED; ReturnValue_t result = returnvalue::FAILED;
@ -157,60 +158,61 @@ void CCSDSHandler::readCommandQueue(void) {
} }
} }
MessageQueueId_t CCSDSHandler::getCommandQueue() const { return commandQueue->getId(); } MessageQueueId_t CcsdsIpCoreHandler::getCommandQueue() const { return commandQueue->getId(); }
void CCSDSHandler::addVirtualChannel(VcId_t vcId, VirtualChannel* virtualChannel) { void CcsdsIpCoreHandler::addVirtualChannel(VcId_t vcId, VirtualChannel* virtualChannel) {
if (vcId > common::NUMBER_OF_VIRTUAL_CHANNELS) { if (vcId > common::NUMBER_OF_VIRTUAL_CHANNELS) {
sif::warning << "CCSDSHandler::addVirtualChannel: Invalid virtual channel ID" << std::endl; sif::warning << "CcsdsHandler::addVirtualChannel: Invalid virtual channel ID" << std::endl;
return; return;
} }
if (virtualChannel == nullptr) { if (virtualChannel == nullptr) {
sif::warning << "CCSDSHandler::addVirtualChannel: Invalid virtual channel interface" sif::warning << "CcsdsHandler::addVirtualChannel: Invalid virtual channel interface"
<< std::endl; << std::endl;
return; return;
} }
auto status = virtualChannelMap.emplace(vcId, virtualChannel); auto status = virtualChannelMap.emplace(vcId, virtualChannel);
if (status.second == false) { if (status.second == false) {
sif::warning << "CCSDSHandler::addVirtualChannel: Failed to add virtual channel to " sif::warning << "CcsdsHandler::addVirtualChannel: Failed to add virtual channel to "
"virtual channel map" "virtual channel map"
<< std::endl; << std::endl;
return; return;
} }
} }
MessageQueueId_t CCSDSHandler::getReportReceptionQueue(uint8_t virtualChannel) const { MessageQueueId_t CcsdsIpCoreHandler::getReportReceptionQueue(uint8_t virtualChannel) const {
if (virtualChannel < common::NUMBER_OF_VIRTUAL_CHANNELS) { if (virtualChannel < common::NUMBER_OF_VIRTUAL_CHANNELS) {
auto iter = virtualChannelMap.find(virtualChannel); auto iter = virtualChannelMap.find(virtualChannel);
if (iter != virtualChannelMap.end()) { if (iter != virtualChannelMap.end()) {
return iter->second->getReportReceptionQueue(); return iter->second->getReportReceptionQueue();
} else { } else {
sif::warning << "CCSDSHandler::getReportReceptionQueue: Virtual channel with ID " sif::warning << "CcsdsHandler::getReportReceptionQueue: Virtual channel with ID "
<< static_cast<unsigned int>(virtualChannel) << " not in virtual channel map" << static_cast<unsigned int>(virtualChannel) << " not in virtual channel map"
<< std::endl; << std::endl;
return MessageQueueIF::NO_QUEUE; return MessageQueueIF::NO_QUEUE;
} }
} else { } else {
sif::debug << "CCSDSHandler::getReportReceptionQueue: Invalid virtual channel requested"; sif::debug << "CcsdsHandler::getReportReceptionQueue: Invalid virtual channel requested";
} }
return MessageQueueIF::NO_QUEUE; return MessageQueueIF::NO_QUEUE;
} }
ReturnValue_t CCSDSHandler::getParameter(uint8_t domainId, uint8_t uniqueIdentifier, ReturnValue_t CcsdsIpCoreHandler::getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
ParameterWrapper* parameterWrapper, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) { const ParameterWrapper* newValues,
uint16_t startAtIndex) {
return returnvalue::OK; return returnvalue::OK;
} }
uint32_t CCSDSHandler::getIdentifier() const { return 0; } uint32_t CcsdsIpCoreHandler::getIdentifier() const { return 0; }
MessageQueueId_t CCSDSHandler::getRequestQueue() const { MessageQueueId_t CcsdsIpCoreHandler::getRequestQueue() const {
// Forward packets directly to TC distributor // Forward packets directly to TC distributor
return tcDistributorQueueId; return tcDistributorQueueId;
} }
ReturnValue_t CCSDSHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, ReturnValue_t CcsdsIpCoreHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) { const uint8_t* data, size_t size) {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
switch (actionId) { switch (actionId) {
@ -261,7 +263,7 @@ ReturnValue_t CCSDSHandler::executeAction(ActionId_t actionId, MessageQueueId_t
return EXECUTION_FINISHED; return EXECUTION_FINISHED;
} }
void CCSDSHandler::checkEvents() { void CcsdsIpCoreHandler::checkEvents() {
EventMessage event; EventMessage event;
for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK; for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK;
result = eventQueue->receiveMessage(&event)) { result = eventQueue->receiveMessage(&event)) {
@ -270,14 +272,14 @@ void CCSDSHandler::checkEvents() {
handleEvent(&event); handleEvent(&event);
break; break;
default: default:
sif::debug << "CCSDSHandler::checkEvents: Did not subscribe to this event message" sif::debug << "CcsdsHandler::checkEvents: Did not subscribe to this event message"
<< std::endl; << std::endl;
break; break;
} }
} }
} }
void CCSDSHandler::handleEvent(EventMessage* eventMessage) { void CcsdsIpCoreHandler::handleEvent(EventMessage* eventMessage) {
Event event = eventMessage->getEvent(); Event event = eventMessage->getEvent();
switch (event) { switch (event) {
case PdecHandler::BIT_LOCK_PDEC: { case PdecHandler::BIT_LOCK_PDEC: {
@ -289,12 +291,12 @@ void CCSDSHandler::handleEvent(EventMessage* eventMessage) {
break; break;
} }
default: default:
sif::debug << "CCSDSHandler::handleEvent: Did not subscribe to this event" << std::endl; sif::debug << "CcsdsHandler::handleEvent: Did not subscribe to this event" << std::endl;
break; break;
} }
} }
void CCSDSHandler::handleBitLockEvent() { void CcsdsIpCoreHandler::handleBitLockEvent() {
if (transmitterCountdown.isBusy()) { if (transmitterCountdown.isBusy()) {
// Transmitter already enabled // Transmitter already enabled
return; return;
@ -302,21 +304,21 @@ void CCSDSHandler::handleBitLockEvent() {
enableTransmit(); enableTransmit();
} }
void CCSDSHandler::handleCarrierLockEvent() { void CcsdsIpCoreHandler::handleCarrierLockEvent() {
if (!enableTxWhenCarrierLock) { if (!enableTxWhenCarrierLock) {
return; return;
} }
enableTransmit(); enableTransmit();
} }
void CCSDSHandler::forwardLinkstate() { void CcsdsIpCoreHandler::forwardLinkstate() {
VirtualChannelMapIter iter; VirtualChannelMapIter iter;
for (iter = virtualChannelMap.begin(); iter != virtualChannelMap.end(); iter++) { for (iter = virtualChannelMap.begin(); iter != virtualChannelMap.end(); iter++) {
iter->second->setLinkState(linkState); iter->second->setLinkState(linkState);
} }
} }
void CCSDSHandler::enableTransmit() { void CcsdsIpCoreHandler::enableTransmit() {
if (transmitterCountdown.isBusy()) { if (transmitterCountdown.isBusy()) {
// Transmitter already enabled // Transmitter already enabled
return; return;
@ -327,7 +329,7 @@ void CCSDSHandler::enableTransmit() {
#endif #endif
} }
void CCSDSHandler::checkTxTimer() { void CcsdsIpCoreHandler::checkTxTimer() {
if (linkState == DOWN) { if (linkState == DOWN) {
return; return;
} }
@ -336,7 +338,7 @@ void CCSDSHandler::checkTxTimer() {
} }
} }
void CCSDSHandler::disableTransmit() { void CcsdsIpCoreHandler::disableTransmit() {
#ifndef TE0720_1CFA #ifndef TE0720_1CFA
gpioIF->pullLow(enTxClock); gpioIF->pullLow(enTxClock);
gpioIF->pullLow(enTxData); gpioIF->pullLow(enTxData);
@ -346,4 +348,4 @@ void CCSDSHandler::disableTransmit() {
transmitterCountdown.setTimeout(0); transmitterCountdown.setTimeout(0);
} }
const char* CCSDSHandler::getName() const { return "CCSDS Handler"; } const char* CcsdsIpCoreHandler::getName() const { return "CCSDS Handler"; }

View File

@ -17,7 +17,7 @@
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h" #include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
#include "fsfw_hal/common/gpio/GpioIF.h" #include "fsfw_hal/common/gpio/GpioIF.h"
#include "fsfw_hal/common/gpio/gpioDefinitions.h" #include "fsfw_hal/common/gpio/gpioDefinitions.h"
#include "linux/obc/PtmeConfig.h" #include "linux/ipcore/PtmeConfig.h"
/** /**
* @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
@ -28,7 +28,7 @@
* *
* @author J. Meier * @author J. Meier
*/ */
class CCSDSHandler : public SystemObject, class CcsdsIpCoreHandler : public SystemObject,
public ExecutableObjectIF, public ExecutableObjectIF,
public AcceptsTelemetryIF, public AcceptsTelemetryIF,
public AcceptsTelecommandsIF, public AcceptsTelecommandsIF,
@ -49,11 +49,11 @@ class CCSDSHandler : public SystemObject,
* @param enTxClock GPIO ID of RS485 tx clock enable * @param enTxClock GPIO ID of RS485 tx clock enable
* @param enTxData GPIO ID of RS485 tx data enable * @param enTxData GPIO ID of RS485 tx data enable
*/ */
CCSDSHandler(object_id_t objectId, object_id_t ptmeId, object_id_t tcDestination, CcsdsIpCoreHandler(object_id_t objectId, object_id_t ptmeId, object_id_t tcDestination,
PtmeConfig* ptmeConfig, GpioIF* gpioIF, gpioId_t enTxClock, gpioId_t enTxData, PtmeConfig* ptmeConfig, GpioIF* gpioIF, gpioId_t enTxClock, gpioId_t enTxData,
uint32_t transmitterTimeout = 900000); uint32_t transmitterTimeout = 900000);
~CCSDSHandler(); ~CcsdsIpCoreHandler();
ReturnValue_t performOperation(uint8_t operationCode = 0) override; ReturnValue_t performOperation(uint8_t operationCode = 0) override;
ReturnValue_t initialize(); ReturnValue_t initialize();

View File

@ -5,29 +5,21 @@
#include "fsfw/tmtcservices/TmTcMessage.h" #include "fsfw/tmtcservices/TmTcMessage.h"
CfdpTmFunnel::CfdpTmFunnel(object_id_t objectId, uint16_t cfdpInCcsdsApid, CfdpTmFunnel::CfdpTmFunnel(object_id_t objectId, uint16_t cfdpInCcsdsApid,
const AcceptsTelemetryIF& downlinkDestination, StorageManagerIF& tmStore, StorageManagerIF& tmStore)
uint8_t vc) : TmFunnelBase(objectId, tmStore, 10), cfdpInCcsdsApid(cfdpInCcsdsApid) {}
: SystemObject(objectId), cfdpInCcsdsApid(cfdpInCcsdsApid), tmStore(tmStore) {
msgQueue = QueueFactory::instance()->createMessageQueue(5);
msgQueue->setDefaultDestination(downlinkDestination.getReportReceptionQueue(vc));
}
const char* CfdpTmFunnel::getName() const { return "CFDP TM Funnel"; } const char* CfdpTmFunnel::getName() const { return "CFDP TM Funnel"; }
MessageQueueId_t CfdpTmFunnel::getReportReceptionQueue(uint8_t virtualChannel) const {
return msgQueue->getId();
}
ReturnValue_t CfdpTmFunnel::performOperation(uint8_t) { ReturnValue_t CfdpTmFunnel::performOperation(uint8_t) {
TmTcMessage currentMessage; TmTcMessage currentMessage;
ReturnValue_t status = msgQueue->receiveMessage(&currentMessage); ReturnValue_t status = tmQueue->receiveMessage(&currentMessage);
while (status == returnvalue::OK) { while (status == returnvalue::OK) {
status = handlePacket(currentMessage); status = handlePacket(currentMessage);
if (status != returnvalue::OK) { if (status != returnvalue::OK) {
sif::warning << "CfdpTmFunnel packet handling failed" << std::endl; sif::warning << "CfdpTmFunnel packet handling failed" << std::endl;
break; break;
} }
status = msgQueue->receiveMessage(&currentMessage); status = tmQueue->receiveMessage(&currentMessage);
} }
if (status == MessageQueueIF::EMPTY) { if (status == MessageQueueIF::EMPTY) {
@ -74,12 +66,27 @@ ReturnValue_t CfdpTmFunnel::handlePacket(TmTcMessage& msg) {
// Delete old packet // Delete old packet
tmStore.deleteData(msg.getStorageId()); tmStore.deleteData(msg.getStorageId());
msg.setStorageId(newStoreId); msg.setStorageId(newStoreId);
result = msgQueue->sendToDefault(&msg); store_address_t origStoreId = newStoreId;
for (unsigned int idx = 0; idx < destinations.size(); idx++) {
const auto& destVcidPair = destinations[idx];
if (destinations.size() > 1) {
if (idx <= destinations.size() - 1) {
// Create copy of data to ensure each TM recipient has its own copy. That way, we don't need
// to bother with send order and where the data is deleted.
store_address_t storeId;
result = tmStore.addData(&storeId, newPacketData, serSize);
msg.setStorageId(storeId);
} else {
msg.setStorageId(origStoreId);
}
}
result = tmQueue->sendMessage(destVcidPair.first, &msg);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
tmStore.deleteData(msg.getStorageId());
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "CfdpTmFunnel::handlePacket: Error sending TM to downlink handler" << std::endl; sif::error << "PusTmFunnel::handlePacket: Error sending TM to downlink handler" << std::endl;
#endif #endif
tmStore.deleteData(msg.getStorageId());
}
} }
return result; return result;
} }

View File

@ -1,19 +1,19 @@
#ifndef FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H #ifndef FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H
#define FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H #define FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H
#include <mission/tmtc/TmFunnelBase.h>
#include <vector>
#include "fsfw/objectmanager/SystemObject.h" #include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/storagemanager/StorageManagerIF.h" #include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h" #include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
#include "fsfw/tmtcservices/TmTcMessage.h" #include "fsfw/tmtcservices/TmTcMessage.h"
class CfdpTmFunnel : public AcceptsTelemetryIF, public SystemObject { class CfdpTmFunnel : public TmFunnelBase {
public: public:
CfdpTmFunnel(object_id_t objectId, uint16_t cfdpInCcsdsApid, CfdpTmFunnel(object_id_t objectId, uint16_t cfdpInCcsdsApid, StorageManagerIF& tmStore);
const AcceptsTelemetryIF& downlinkDestination, StorageManagerIF& tmStore,
uint8_t vc);
[[nodiscard]] const char* getName() const override; [[nodiscard]] const char* getName() const override;
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
ReturnValue_t performOperation(uint8_t opCode); ReturnValue_t performOperation(uint8_t opCode);
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
@ -22,7 +22,5 @@ class CfdpTmFunnel : public AcceptsTelemetryIF, public SystemObject {
uint16_t sourceSequenceCount = 0; uint16_t sourceSequenceCount = 0;
uint16_t cfdpInCcsdsApid; uint16_t cfdpInCcsdsApid;
MessageQueueIF* msgQueue;
StorageManagerIF& tmStore;
}; };
#endif // FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H #endif // FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H

View File

@ -4,21 +4,12 @@
#include "fsfw/objectmanager.h" #include "fsfw/objectmanager.h"
#include "fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h" #include "fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h"
PusTmFunnel::PusTmFunnel(object_id_t objectId, const AcceptsTelemetryIF &downlinkDestination, PusTmFunnel::PusTmFunnel(object_id_t objectId, TimeReaderIF &timeReader, StorageManagerIF &tmStore,
TimeReaderIF &timeReader, StorageManagerIF &tmStore, uint8_t vcId,
uint32_t messageDepth) uint32_t messageDepth)
: SystemObject(objectId), timeReader(timeReader), tmStore(tmStore) { : TmFunnelBase(objectId, tmStore, messageDepth), timeReader(timeReader) {}
tmQueue = QueueFactory::instance()->createMessageQueue(messageDepth,
MessageQueueMessage::MAX_MESSAGE_SIZE);
tmQueue->setDefaultDestination(downlinkDestination.getReportReceptionQueue(vcId));
}
PusTmFunnel::~PusTmFunnel() = default; PusTmFunnel::~PusTmFunnel() = default;
MessageQueueId_t PusTmFunnel::getReportReceptionQueue(uint8_t virtualChannel) const {
return tmQueue->getId();
}
ReturnValue_t PusTmFunnel::performOperation(uint8_t) { ReturnValue_t PusTmFunnel::performOperation(uint8_t) {
TmTcMessage currentMessage; TmTcMessage currentMessage;
ReturnValue_t status = tmQueue->receiveMessage(&currentMessage); ReturnValue_t status = tmQueue->receiveMessage(&currentMessage);
@ -40,7 +31,8 @@ ReturnValue_t PusTmFunnel::performOperation(uint8_t) {
ReturnValue_t PusTmFunnel::handlePacket(TmTcMessage &message) { ReturnValue_t PusTmFunnel::handlePacket(TmTcMessage &message) {
uint8_t *packetData = nullptr; uint8_t *packetData = nullptr;
size_t size = 0; size_t size = 0;
ReturnValue_t result = tmStore.modifyData(message.getStorageId(), &packetData, &size); store_address_t origStoreId = message.getStorageId();
ReturnValue_t result = tmStore.modifyData(origStoreId, &packetData, &size);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
@ -56,12 +48,26 @@ ReturnValue_t PusTmFunnel::handlePacket(TmTcMessage &message) {
sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT; sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT;
packet.updateErrorControl(); packet.updateErrorControl();
result = tmQueue->sendToDefault(&message); for (unsigned int idx = 0; idx < destinations.size(); idx++) {
const auto &destVcidPair = destinations[idx];
if (destinations.size() > 1) {
if (idx <= destinations.size() - 1) {
// Create copy of data to ensure each TM recipient has its own copy. That way, we don't need
// to bother with send order and where the data is deleted.
store_address_t storeId;
result = tmStore.addData(&storeId, packetData, size);
message.setStorageId(storeId);
} else {
message.setStorageId(origStoreId);
}
}
result = tmQueue->sendMessage(destVcidPair.first, &message);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
tmStore.deleteData(message.getStorageId());
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PusTmFunnel::handlePacket: Error sending TM to downlink handler" << std::endl; sif::error << "PusTmFunnel::handlePacket: Error sending TM to downlink handler" << std::endl;
#endif #endif
tmStore.deleteData(message.getStorageId());
}
} }
return result; return result;
} }

View File

@ -6,6 +6,9 @@
#include <fsfw/tasks/ExecutableObjectIF.h> #include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h> #include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
#include <fsfw/tmtcservices/TmTcMessage.h> #include <fsfw/tmtcservices/TmTcMessage.h>
#include <mission/tmtc/TmFunnelBase.h>
#include <vector>
#include "fsfw/timemanager/TimeReaderIF.h" #include "fsfw/timemanager/TimeReaderIF.h"
@ -20,22 +23,19 @@
* @ingroup utility * @ingroup utility
* @author J. Meier, R. Mueller * @author J. Meier, R. Mueller
*/ */
class PusTmFunnel : public AcceptsTelemetryIF, public SystemObject { class PusTmFunnel : public TmFunnelBase {
public: public:
explicit PusTmFunnel(object_id_t objectId, const AcceptsTelemetryIF &downlinkDestination, explicit PusTmFunnel(object_id_t objectId, TimeReaderIF &timeReader, StorageManagerIF &tmStore,
TimeReaderIF &timeReader, StorageManagerIF &tmStore, uint8_t vdId, uint32_t messageDepth = 10);
uint32_t messageDepth = 20);
[[nodiscard]] const char *getName() const override; [[nodiscard]] const char *getName() const override;
~PusTmFunnel() override; ~PusTmFunnel() override;
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
ReturnValue_t performOperation(uint8_t operationCode); ReturnValue_t performOperation(uint8_t operationCode);
private: private:
uint16_t sourceSequenceCount = 0; uint16_t sourceSequenceCount = 0;
TimeReaderIF &timeReader; TimeReaderIF &timeReader;
StorageManagerIF &tmStore;
MessageQueueIF *tmQueue = nullptr;
ReturnValue_t handlePacket(TmTcMessage &message); ReturnValue_t handlePacket(TmTcMessage &message);
}; };

View File

@ -1,16 +0,0 @@
#include "TmFunnel.h"
#include <fsfw/ipc/QueueFactory.h>
TmFunnel::TmFunnel(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel)
: SystemObject(objectId), pusFunnel(pusFunnel), cfdpFunnel(cfdpFunnel) {}
TmFunnel::~TmFunnel() = default;
ReturnValue_t TmFunnel::performOperation(uint8_t operationCode) {
pusFunnel.performOperation(operationCode);
cfdpFunnel.performOperation(operationCode);
return returnvalue::OK;
}
ReturnValue_t TmFunnel::initialize() { return returnvalue::OK; }

View File

@ -0,0 +1,19 @@
#include "TmFunnelBase.h"
#include "fsfw/ipc/QueueFactory.h"
TmFunnelBase::TmFunnelBase(object_id_t objectId, StorageManagerIF &tmStore, uint32_t tmMsgDepth)
: SystemObject(objectId), tmStore(tmStore) {
tmQueue = QueueFactory::instance()->createMessageQueue(tmMsgDepth);
}
TmFunnelBase::~TmFunnelBase() { QueueFactory::instance()->deleteMessageQueue(tmQueue); }
MessageQueueId_t TmFunnelBase::getReportReceptionQueue(uint8_t virtualChannel) const {
return tmQueue->getId();
}
void TmFunnelBase::addDestination(const AcceptsTelemetryIF &downlinkDestination, uint8_t vcid) {
auto queueId = downlinkDestination.getReportReceptionQueue(vcid);
destinations.emplace_back(queueId, vcid);
}

View File

@ -0,0 +1,24 @@
#ifndef MISSION_TMTC_TMFUNNELBASE_H_
#define MISSION_TMTC_TMFUNNELBASE_H_
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/storagemanager/StorageManagerIF.h>
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
#include <vector>
class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject {
public:
TmFunnelBase(object_id_t objectId, StorageManagerIF& tmStore, uint32_t tmMsgDepth);
void addDestination(const AcceptsTelemetryIF& downlinkDestination, uint8_t vcid = 0);
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
virtual ~TmFunnelBase();
protected:
StorageManagerIF& tmStore;
std::vector<std::pair<MessageQueueId_t, uint8_t>> destinations;
MessageQueueIF* tmQueue = nullptr;
};
#endif /* MISSION_TMTC_TMFUNNELBASE_H_ */

View File

@ -0,0 +1,17 @@
#include "TmFunnelHandler.h"
#include <fsfw/ipc/QueueFactory.h>
TmFunnelHandler::TmFunnelHandler(object_id_t objectId, PusTmFunnel& pusFunnel,
CfdpTmFunnel& cfdpFunnel)
: SystemObject(objectId), pusFunnel(pusFunnel), cfdpFunnel(cfdpFunnel) {}
TmFunnelHandler::~TmFunnelHandler() = default;
ReturnValue_t TmFunnelHandler::performOperation(uint8_t operationCode) {
pusFunnel.performOperation(operationCode);
cfdpFunnel.performOperation(operationCode);
return returnvalue::OK;
}
ReturnValue_t TmFunnelHandler::initialize() { return returnvalue::OK; }

View File

@ -19,10 +19,10 @@
* @ingroup utility * @ingroup utility
* @author J. Meier, R. Mueller * @author J. Meier, R. Mueller
*/ */
class TmFunnel : public ExecutableObjectIF, public SystemObject { class TmFunnelHandler : public ExecutableObjectIF, public SystemObject {
public: public:
TmFunnel(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel); TmFunnelHandler(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel);
~TmFunnel() override; ~TmFunnelHandler() override;
ReturnValue_t performOperation(uint8_t operationCode) override; ReturnValue_t performOperation(uint8_t operationCode) override;
ReturnValue_t initialize() override; ReturnValue_t initialize() override;

View File

@ -1,6 +1,6 @@
#include "VirtualChannel.h" #include "VirtualChannel.h"
#include "CCSDSHandler.h" #include "CcsdsIpCoreHandler.h"
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "fsfw/ipc/QueueFactory.h" #include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/objectmanager/ObjectManager.h"

View File

@ -2,7 +2,7 @@
#define VIRTUALCHANNEL_H_ #define VIRTUALCHANNEL_H_
#include <fsfw/ipc/MessageQueueIF.h> #include <fsfw/ipc/MessageQueueIF.h>
#include <linux/obc/PtmeIF.h> #include <linux/ipcore/PtmeIF.h>
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"