diff --git a/bsp_q7s/boardconfig/busConf.h b/bsp_q7s/boardconfig/busConf.h index f5b4a860..5bec55a2 100644 --- a/bsp_q7s/boardconfig/busConf.h +++ b/bsp_q7s/boardconfig/busConf.h @@ -90,6 +90,16 @@ static constexpr uint32_t SPI_MUX_BIT_5 = 17; static constexpr uint32_t SPI_MUX_BIT_6 = 9; static constexpr uint32_t EN_RW_CS = 17; +static constexpr char GPIO_VC_STATUS_SIGNALS_LABEL[] = "/amba_pl/gpio@81200000"; +static constexpr uint32_t VC0_PAPB_EMPTY_LINE = 0; +static constexpr uint32_t VC0_PAPB_BUSY_LINE = 1; +static constexpr uint32_t VC1_PAPB_EMPTY_LINE = 2; +static constexpr uint32_t VC1_PAPB_BUSY_LINE = 3; +static constexpr uint32_t VC2_PAPB_EMPTY_LINE = 4; +static constexpr uint32_t VC2_PAPB_BUSY_LINE = 5; +static constexpr uint32_t VC3_PAPB_EMPTY_LINE = 6; +static constexpr uint32_t VC3_PAPB_BUSY_LINE = 7; + } #endif /* BSP_Q7S_BOARDCONFIG_BUSCONF_H_ */ diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index 024be8dd..0fcaff62 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -173,25 +173,55 @@ void ObjectFactory::produce(void* args) { #endif /* TE7020 != 0 */ -#if OBSW_USE_PTME_IP_CORE == 1 - GpioCookie* gpioCookiePtmeIp = new GpioCookie; - GpiodRegular* vc0PapbBusyN = new GpiodRegular(std::string("gpiochip0"), 0, std::string("PAPBBusy_N")); - gpioCookiePtmeIp->addGpio(gpioIds::PAPB_BUSY_N, papbBusyN); - GpiodRegular* vc0PapbEmpty = new GpiodRegular(st_d::string("gpiochip0"), 1, - std::string("PAPBEmpty_VC0")); - gpioCookiePtmeIp->addGpio(gpioIds::PAPB_EMPTY, papbEmpty); - gpioComIF->addGpios(gpioCookiePtmeIp); - PapbVcInterface* vc0 = new PapbVcInterface(objects::PAPB_VC0, gpioComIF, ) - Ptme* ptme = new Ptme(objects::PTME); - ptme->addVcInterface(0, vc0); - ptme->addVcInterface(1, vc1); - ptme->addVcInterface(2, vc2); - ptme->addVcInterface(3, vc3); +#if OBSW_USE_CCSDS_IP_CORE == 1 - new CCSDSIPCoreBridge(objects::CCSDS_IP_CORE_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR, - objects::TM_STORE, objects::TC_STORE, gpioComIF, std::string("/dev/uio0"), - gpioIds::PAPB_BUSY_N, gpioIds::PAPB_EMPTY); -#endif /* OBSW_USE_TMTC_IP_CORE_BRIDGE == 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); + +#endif /* OBSW_USE_CCSDS_IP_CORE == 1 */ #if OBSW_USE_TMTC_TCP_BRIDGE == 0 auto udpBridge = new UdpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); diff --git a/common/config/commonConfig.h.in b/common/config/commonConfig.h.in index 55af54e3..c089c575 100644 --- a/common/config/commonConfig.h.in +++ b/common/config/commonConfig.h.in @@ -8,7 +8,7 @@ #define OBSW_USE_TMTC_TCP_BRIDGE 1 // This will cause the OBSW to initialize the TMTC bridge responsible for exchanging data with the // CCSDS IP Cores. -#define OBSW_USE_TMTC_IP_CORE_BRIDGE 0 +#define OBSW_USE_CCSDS_IP_CORE 1 // Set to 1 if all telemetry should be sent to the PTME IP Core #define OBSW_TM_TO_PTME 0 // Set to 1 if telecommands are received via the PDEC IP Core diff --git a/common/config/commonObjects.h b/common/config/commonObjects.h index 5fc61bd4..0a66cd9a 100644 --- a/common/config/commonObjects.h +++ b/common/config/commonObjects.h @@ -13,9 +13,9 @@ enum commonObjects: uint32_t { FILE_SYSTEM_HANDLER = 0x50000500, PTME = 0x50000600, PAPB_VC0 = 0x50000700, - PAPB_VC0 = 0x500007001, - PAPB_VC0 = 0x500007002, - PAPB_VC0 = 0x500007003, + PAPB_VC1 = 0x500007001, + PAPB_VC2 = 0x500007002, + PAPB_VC3 = 0x500007003, /* 0x43 ('C') for Controllers */ THERMAL_CONTROLLER = 0x43400001, diff --git a/linux/fsfwconfig/devices/gpioIds.h b/linux/fsfwconfig/devices/gpioIds.h index b450bf8b..2016245d 100644 --- a/linux/fsfwconfig/devices/gpioIds.h +++ b/linux/fsfwconfig/devices/gpioIds.h @@ -89,7 +89,16 @@ enum gpioId_t { EN_RW_CS, - SPI_MUX + SPI_MUX, + + VC0_PAPB_EMPTY, + VC0_PAPB_BUSY, + VC1_PAPB_EMPTY, + VC1_PAPB_BUSY, + VC2_PAPB_EMPTY, + VC2_PAPB_BUSY, + VC3_PAPB_EMPTY, + VC3_PAPB_BUSY }; } diff --git a/linux/obc/PapbVcInterface.cpp b/linux/obc/PapbVcInterface.cpp index 736c8b24..0c3c759a 100644 --- a/linux/obc/PapbVcInterface.cpp +++ b/linux/obc/PapbVcInterface.cpp @@ -53,12 +53,12 @@ ReturnValue_t PapbVcInterface::pollPapbBusySignal() { /** Check if PAPB interface is ready to receive data */ result = gpioComIF->readGpio(papbBusyId, &papbBusyState); if (result != RETURN_OK) { - sif::debug << "PapbVcInterface::pollPapbBusySignal: Failed to read papb busy signal" + sif::warning << "PapbVcInterface::pollPapbBusySignal: Failed to read papb busy signal" << std::endl; return RETURN_FAILED; } if (!papbBusyState) { - sif::debug << "PapbVcInterface::pollPapbBusySignal: PAPB busy" << std::endl; + sif::warning << "PapbVcInterface::pollPapbBusySignal: PAPB busy" << std::endl; return PAPB_BUSY; } @@ -72,7 +72,7 @@ void PapbVcInterface::isVcInterfaceBufferEmpty() { result = gpioComIF->readGpio(papbEmptyId, &papbEmptyState); if (result != RETURN_OK) { - sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal" + sif::warning << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal" << std::endl; return; } diff --git a/mission/tmtc/CCSDSHandler.cpp b/mission/tmtc/CCSDSHandler.cpp index 38428c14..b17af452 100644 --- a/mission/tmtc/CCSDSHandler.cpp +++ b/mission/tmtc/CCSDSHandler.cpp @@ -1,13 +1,3 @@ -/******************************* - * FLP Flight Software Framework (FSFW) - * (c) 2016 IRS, Uni Stuttgart - *******************************/ -/* - * CCSDSHandler.cpp - * - * Created on: Feb 9, 2012 - * Author: baetz - */ #include #include #include @@ -121,9 +111,30 @@ ReturnValue_t CCSDSHandler::packetProcessingCheck(void) { ReturnValue_t CCSDSHandler::performOperation(void) { 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(); + } +} + +void CCSDSHandler::handleTelecommands() { + +} + void CCSDSHandler::searchFrame() { frameLength = this->boardHandler.findFrame(); while (frameLength != 0) { @@ -198,17 +209,18 @@ ReturnValue_t CCSDSHandler::initialize() { void CCSDSHandler::readCommandQueue(void) { CommandMessage commandMessage; ReturnValue_t result = RETURN_FAILED; - while (commandQueue.receiveMessage(&commandMessage) == RETURN_OK) { - result = parameterHelper.handleParameterMessage(&commandMessage); - if (result == RETURN_OK) { - return; - } - CommandMessage reply; - reply.setReplyRejected(CommandMessage::UNKNOW_COMMAND, - commandMessage.getCommand()); - commandQueue.reply(&reply); - } + result = commandQueue.receiveMessage(&commandMessage); + if (result == RETURN_OK) { + result = parameterHelper.handleParameterMessage(&commandMessage); + if (result == RETURN_OK) { + return; + } + CommandMessage reply; + reply.setReplyRejected(CommandMessage::UNKNOW_COMMAND, + commandMessage.getCommand()); + commandQueue.reply(&reply); + } } MessageQueueId_t CCSDSHandler::getCommandQueue() const { @@ -486,120 +498,15 @@ Submode_t CCSDSHandler::getSubmode() const { } MessageQueueId_t CCSDSHandler::getReportReceptionQueue(uint8_t virtualChannel) { - if (virtualChannel < Ptme::NUM_OF_VIRTUAL_CHANNELS) { + if (virtualChannel < config::NUMBER_OF_VIRTUAL_CHANNELS) { return virtualChannels[virtualChannel]->getReportReceptionQueue(); } else { sif::debug << "CCSDSHandler::getReportReceptionQueue: Invalid virtual channel requested"; } } -void CCSDSHandler::executeAllWriteCommands() { - ReturnValue_t returnValue = boardHandler.sendWriteCommands(); - if (returnValue != RETURN_OK) { - triggerEvent(DeviceHandlerIF::DEVICE_SENDING_COMMAND_FAILED, - returnValue, 0); - } - if (submode == SUBMODE_ACTIVE) { - returnValue = this->packetProcessing(); - if (returnValue != RETURN_OK) { - triggerEvent(DeviceHandlerIF::DEVICE_SENDING_COMMAND_FAILED, - returnValue, 1); - } - } -} - -void CCSDSHandler::handleAllWriteReplies() { - ReturnValue_t returnValue = boardHandler.getWriteReplys(); - if (returnValue != RETURN_OK) { - triggerEvent(DeviceHandlerIF::DEVICE_SENDING_COMMAND_FAILED, - returnValue, 0); - } - if (pendingWrite) { - memoryHelper.completeLoad(returnValue); - pendingWrite = false; - } - if (submode == SUBMODE_ACTIVE) { - returnValue = packetProcessingCheck(); - } else { - this->flushTmChannels(); - } -} - -void CCSDSHandler::executeAllReadCommands() { - ReturnValue_t returnValue = boardHandler.sendReadCommands(); - if (returnValue != RETURN_OK) { - triggerEvent(DeviceHandlerIF::DEVICE_REQUESTING_REPLY_FAILED, - returnValue, 0); - } -} - -void CCSDSHandler::handleAllReadReplies() { - if ((mode == MODE_ON) && (state == STATE_IDLE)) { - ReturnValue_t returnValue = boardHandler.getReadReplys(); - if (returnValue == RETURN_OK) { - searchFrame(); - } else { - triggerEvent(DeviceHandlerIF::DEVICE_REQUESTING_REPLY_FAILED, - returnValue, 0); - //do nothing. - } - if (pendingRead) { - uint8_t* tempBuffer; - returnValue = boardHandler.getRegisterReadReply(&tempBuffer); - memoryHelper.completeDump(returnValue, tempBuffer, - BoardHandler::REGISTER_LENGTH); - pendingRead = false; - } - } -} - -ReturnValue_t CCSDSHandler::getParameter(uint8_t domainId, uint16_t parameterId, - ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues, - uint16_t startAtIndex) { - ReturnValue_t result = fdir.getParameter(domainId, parameterId, - parameterWrapper, newValues, startAtIndex); - if (result != INVALID_DOMAIN_ID) { - return result; - } - if (domainId != DOMAIN_ID_BASE) { - return INVALID_DOMAIN_ID; - } - switch (parameterId) { - case 0: - parameterWrapper->set(boardHandler.tmPhysicalLayerRegisterValue); - break; - case 1: - parameterWrapper->set(boardHandler.tmCodingSublayerRegisterValue); - break; - default: - return INVALID_MATRIX_ID; - } - return RETURN_OK; -} - -ReturnValue_t CCSDSHandler::setHealth(HealthState health) { - healthHelper.setHealth(health); - return RETURN_OK; -} - -HasHealthIF::HealthState CCSDSHandler::getHealth() { - return healthHelper.getHealth(); -} - -CCSDSHandler::DataRateSet::DataRateSet() : - ControllerSet(), dataRate(datapool::VC_DATA_RATE_RAW, this, - PoolVariableIF::VAR_WRITE), dataRates( - datapool::DATA_RATE_ASSIGN, this, PoolVariableIF::VAR_READ) { -} - -CCSDSHandler::DataRateSet::~DataRateSet() { -} - -void CCSDSHandler::DataRateSet::setToDefault() { - dataRate.value = {0.0, 0.0, 0.0, 0.0}; -} - -void CCSDSHandler::triggerEvent(Event event, uint32_t parameter1, - uint32_t parameter2) { - fdir.triggerEvent(event, parameter1, parameter2); +ReturnValue_t CCSDSHandler::getParameter(uint8_t domainId, uint8_t uniqueIdentifier, + ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues, + uint16_t startAtIndex) { + return RETURN_OK; } diff --git a/mission/tmtc/CCSDSHandler.h b/mission/tmtc/CCSDSHandler.h index 77c8b2c1..8780b4e8 100644 --- a/mission/tmtc/CCSDSHandler.h +++ b/mission/tmtc/CCSDSHandler.h @@ -16,7 +16,6 @@ */ class CCSDSHandler: public SystemObject, public ExecutableObjectIF, - public HasModesIF, public AcceptsTelemetryIF, public HasReturnvaluesIF, public ReceivesParameterMessagesIF { @@ -80,27 +79,26 @@ public: */ ReturnValue_t initialize(); MessageQueueId_t getCommandQueue() const; + /** - * Method to configure the TC Virtual Channels in the TC Data Link Layer. - * The call is forwarded to the #dataLinkLayer class. - * @param virtualChannelId VCID to add. - * @param object Pointer to the Virtual Channel object that is added. - * @return See the #dataLinkLayer class. + * @brief Function to add a virtual channel + * + * @param virtualChannelId ID of the virtual channel to add + * @param virtualChannel Pointer to virtual channel object + * + * @return RETURN_OK if successful, otherwise RETURN_FAILED */ - ReturnValue_t addVirtualChannel(uint8_t virtualChannelId, - VirtualChannelReceptionIF* object); + 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 setHealth(HealthState health); - HasHealthIF::HealthState getHealth(); - ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, - ParameterWrapper *parameterWrapper, - const ParameterWrapper *newValues, uint16_t startAtIndex); - void triggerEvent(Event event, uint32_t parameter1 = 0, - uint32_t parameter2 = 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. @@ -148,68 +146,15 @@ protected: void setToExternalControl(); void announceMode(bool recursive); private: - enum CcsdsState_t { - STATE_IDLE, - STATE_TURN_ON, - STATE_TURN_OFF, - STATE_DO_PASSIVATE_OFF, - STATE_TURN_SWITCH_OFF, - STATE_WAIT_ON, - STATE_WAIT_LINK, - STATE_WAIT_OFF, - STATE_INITIALIZE_BOARD, - STATE_SELECT_SUBMODE, - STATE_WAIT_SUBMODE_ACTIVE, - STATE_DO_PASSIVATE, - STATE_WAIT_SUBMODE_PASSIVE, - STATE_HANDLE_STARTUP, - }; - CcsdsState_t state; - enum CommState { - SEND_WRITE, GET_WRITE, SEND_READ, GET_READ - }; - CommState commState; - Mode_t mode; - Submode_t submode; - BoardHandler boardHandler;//!< The class that handles the low-level communication with the board. - DataLinkLayer dataLinkLayer;//!< The class that manages the TC Data Link Layer protocols. - uint8_t frameBuffer[MAX_FRAME_SIZE]; //!< The main buffer to store single frames in. - uint16_t frameLength; //!< Indicates the current length of the found frame. - object_id_t channelId; //!< Defines the id of the RMAP Channel to use. - MemoryHelper memoryHelper; //!< Helps handling memory messages. - bool pendingWrite; //!< Attribute to manage remote Memory write. + using VcId_t = uint8_t; + using VirtualChannelMap = std::unordered_map; + using VirtualChannelMapIter = VirtualChannelMap::iterator; - bool pendingRead; //!< Attribute to manage remote Memory read. + VirtualChannelMap virtualChannelMap; - ModeHelper modeHelper; //!< Helps handling mode messages. - HealthHelper healthHelper; //!< Helps setting the health information correctly. - ParameterHelper parameterHelper; - PowerSwitcher powerSwitcher; //!< Helps switching switches on and off. - - bool switchOffWasReported; //!< To avoid reporting SWITCH_WENT_OFF multiple times. - - CCSDSBoardFailureIsolation fdir; - class DataRateSet: public ControllerSet { - public: - DataRateSet(); - virtual ~DataRateSet(); - void setToDefault(); - PoolVector dataRate; - PoolVector dataRates; - }; - DataRateSet rateSet; - void setMode(Mode_t newMode, Submode_t newSubmode); //!< Method to safely setMode and inform everyone interested about it. - /** - * State machine of the Handler. - * Is responsible for handling mode transitions and for informing the modeHelper. - * In addition, it watches the SpW link and changes the Mode in case a link down or a link up is detected. - */ - void doStateMachine(); - void executeAllWriteCommands(); - void handleAllWriteReplies(); - void executeAllReadCommands(); - void handleAllReadReplies(); + void handleTelemetry(); + void handleTelecommands(); }; #endif /* CCSDSHANDLER_H_ */ diff --git a/mission/tmtc/VirtualChannel.cpp b/mission/tmtc/VirtualChannel.cpp new file mode 100644 index 00000000..8e106de1 --- /dev/null +++ b/mission/tmtc/VirtualChannel.cpp @@ -0,0 +1,80 @@ +#include "CCSDSHandler.h" +#include "OBSWConfig.h" + +#include "fsfw/serviceinterface/ServiceInterfaceStream.h" +#include "fsfw/objectmanager/ObjectManager.h" + + +#include + +#include + + +VirtualChannel::VirtualChannel(uint8_t vcId, uint32_t tmQueueDepth) : + vcId(vcId) { + tmQueue = QueueFactory::instance()->createMessageQueue(tmQueueDepth, + MessageQueueMessage::MAX_MESSAGE_SIZE); +} + +ReturnValue_t VirtualChannel::initialize() { + tmStore = ObjectManager::instance()->get(objects::TM_STORE); + if(tmStore == nullptr) { + sif::error << "VirtualChannel::initialize: Failed to get tm store" << std::endl; + return RETURN_FAILED; + } +} + +ReturnValue_t VirtualChannel::performOperation() { + ReturnValue_t status = RETURN_OK; + TmTcMessage message; + + while(tmQueue->receiveMessage(&message) == RETURN_OK) { + store_address_t storeId = message.getStorageId(); + const uint8_t* data = nullptr; + size_t size = 0; + result = tmStore->getData(storeId, &data, &size); + if (result != RETURN_OK) { + sif::warning << "VirtualChannel::performOperation: Failed to read data from IPC store" + << std::endl; + tmStore->deleteData(storeId); + return result; + } + + if (linkIsUp) { + result = ptme->writeToVc(virtualChannleId, data, size); + } + + tmStore->deleteData(storeId); + + if (result != RETURN_OK) { + return result; + } + } + return result; +} + +MessageQueueId_t VirtualChannel::getReportReceptionQueue(uint8_t virtualChannel) { + return tmQueue.getId(); +} + +void VirtualChannel::setPtmeObject(PtmeIF* ptme) { + if (ptme == nullptr) { + sif::warning << "VirtualChannel::setPtmeObject: Invalid ptme object" << std::endl; + } + 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; +} diff --git a/mission/tmtc/VirtualChannel.h b/mission/tmtc/VirtualChannel.h new file mode 100644 index 00000000..cba4b0b4 --- /dev/null +++ b/mission/tmtc/VirtualChannel.h @@ -0,0 +1,110 @@ +#ifndef VIRTUALCHANNEL_H_ +#define VIRTUALCHANNEL_H_ + +#include "fsfw/tmtcservices/AcceptsTelemetryIF.h" +#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief This class represents a virtual channel in the software. + * + * @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 + * + * @param vcId The virtual channel id assigned to this object + * @param tmQueueDepth Queue depth of queue receiving telemetry from other objects + */ + 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(); + + ReturnValue_t performOperation(); + + /** + * @brief Sets the PTME object which handles access to the PTME IP Core. + * + * @param ptme Pointer to ptme object + */ + void setPtmeObject(Ptme* ptme); + +private: + + PtmeIF* ptme = nullptr; + MessageQueueIF* tmQueue = nullptr; + uint8_t virtualChannelId; + 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 e5de3ef7..d718f6cf 100644 --- a/mission/utility/TmFunnel.cpp +++ b/mission/utility/TmFunnel.cpp @@ -46,7 +46,7 @@ ReturnValue_t TmFunnel::performOperation(uint8_t operationCode) { ReturnValue_t TmFunnel::handlePacket(TmTcMessage* message) { uint8_t* packetData = nullptr; size_t size = 0; - ReturnValue_t result = tmPool->modifyData(message->getStorageId(), + ReturnValue_t result = tmStore->modifyData(message->getStorageId(), &packetData, &size); if(result != HasReturnvaluesIF::RETURN_OK){ return result; @@ -60,7 +60,7 @@ ReturnValue_t TmFunnel::handlePacket(TmTcMessage* message) { result = tmQueue->sendToDefault(message); if(result != HasReturnvaluesIF::RETURN_OK){ - tmPool->deleteData(message->getStorageId()); + tmStore->deleteData(message->getStorageId()); sif::error << "TmFunnel::handlePacket: Error sending to downlink " "handler" << std::endl; return result; @@ -69,7 +69,7 @@ ReturnValue_t TmFunnel::handlePacket(TmTcMessage* message) { if(storageDestination != objects::NO_OBJECT) { result = storageQueue->sendToDefault(message); if(result != HasReturnvaluesIF::RETURN_OK){ - tmPool->deleteData(message->getStorageId()); + tmStore->deleteData(message->getStorageId()); sif::error << "TmFunnel::handlePacket: Error sending to storage " "handler" << std::endl; return result; @@ -80,8 +80,8 @@ ReturnValue_t TmFunnel::handlePacket(TmTcMessage* message) { ReturnValue_t TmFunnel::initialize() { - tmPool = ObjectManager::instance()->get(objects::TM_STORE); - if(tmPool == nullptr) { + tmStore = ObjectManager::instance()->get(objects::TM_STORE); + if(tmStore == nullptr) { sif::error << "TmFunnel::initialize: TM store not set." << std::endl; sif::error << "Make sure the tm store is set up properly" diff --git a/mission/utility/TmFunnel.h b/mission/utility/TmFunnel.h index 2d4575a0..b85a09e0 100644 --- a/mission/utility/TmFunnel.h +++ b/mission/utility/TmFunnel.h @@ -41,7 +41,7 @@ private: MessageQueueIF* tmQueue = nullptr; MessageQueueIF* storageQueue = nullptr; - StorageManagerIF* tmPool = nullptr; + StorageManagerIF* tmStore = nullptr; uint32_t messageDepth = 0; ReturnValue_t handlePacket(TmTcMessage* message);