v1.9.0 #175
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 <linux/obc/Ptme.h>
|
||||
#include <linux/obc/PapbVcInterface.h>
|
||||
#include <linux/obc/PtmeConfig.h>
|
||||
|
||||
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
|
||||
|
@ -22,6 +22,7 @@ void createSolarArrayDeploymentComponents();
|
||||
void createSyrlinksComponents();
|
||||
void createRtdComponents(LinuxLibgpioIF* gpioComIF);
|
||||
void createReactionWheelComponents(LinuxLibgpioIF* gpioComIF);
|
||||
void createCcsdsComponents(LinuxLibgpioIF *gpioComIF);
|
||||
void createTestComponents(LinuxLibgpioIF* gpioComIF);
|
||||
|
||||
};
|
||||
|
15
common/config/ccsdsConfig.h
Normal file
15
common/config/ccsdsConfig.h
Normal file
@ -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_ */
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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<uint32_t>(*(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<uint8_t>(idx & 0xFF);
|
||||
}
|
||||
|
||||
ReturnValue_t result = sendTm(testPacket, 1105);
|
||||
ReturnValue_t result = write(testPacket, 1105);
|
||||
if(result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
#include "linux/obc/VcInterfaceIF.h"
|
||||
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
|
||||
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
|
||||
#include <linux/obc/PapbVcInterface.h>
|
||||
#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;
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <linux/obc/Ptme.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t * data, size_t dataLen) {
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
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<unsigned int>(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;
|
||||
}
|
||||
|
@ -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<VcId_t, VcInterfaceIF*>;
|
||||
using VcInterfaceMapIter = VcInterfaceMap::iterator;
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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_ */
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef LINUX_OBC_VCINTERFACEIF_H_
|
||||
#define LINUX_OBC_VCINTERFACEIF_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#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_ */
|
||||
|
@ -2,3 +2,4 @@ add_subdirectory(core)
|
||||
add_subdirectory(devices)
|
||||
add_subdirectory(utility)
|
||||
add_subdirectory(memory)
|
||||
add_subdirectory(tmtc)
|
||||
|
@ -1,133 +1,29 @@
|
||||
#include <framework/devicehandlers/DeviceHandlerIF.h>
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
#include <framework/rmap/RMAPChannelIF.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <framework/tmtcservices/AcceptsTelecommandsIF.h>
|
||||
#include <mission/obc/ccsdsboard/CCSDSHandler.h>
|
||||
#include <math.h>
|
||||
#include <config/datapool/dataPoolInit.h>
|
||||
#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<float, BoardHandler::USED_VIRTUAL_CHANNELS_PER_BOARD> 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<unsigned int>(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<PtmeIF>(ptmeId);
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
PtmeIF* ptme = ObjectManager::instance()->get<PtmeIF>(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<StorageManagerIF>(
|
||||
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<VCGeneration>(
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
|
||||
|
||||
if (virtualChannel == nullptr) {
|
||||
sif::warning << "CCSDSHandler::addVirtualChannel: Invalid virtual channel interface" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
void CCSDSHandler::getMode(Mode_t* modeReturn, Submode_t* submodeReturn) {
|
||||
*modeReturn = mode;
|
||||
*submodeReturn = 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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<unsigned int>(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,
|
||||
|
@ -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 <unordered_map>
|
||||
|
||||
/**
|
||||
* @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;
|
||||
|
||||
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.
|
||||
* @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);
|
||||
|
||||
~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<VcId_t, VcInterfaceIF*>;
|
||||
static const uint32_t QUEUE_SIZE = config::CCSDS_HANDLER_QUEUE_SIZE;
|
||||
|
||||
using VirtualChannelMap = std::unordered_map<VcId_t, VirtualChannel*>;
|
||||
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();
|
||||
};
|
||||
|
6
mission/tmtc/CMakeLists.txt
Normal file
6
mission/tmtc/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
target_sources(${TARGET_NAME} PUBLIC
|
||||
CCSDSHandler.cpp
|
||||
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 <framework/tmtcservices/TmTcMessage.h>
|
||||
|
||||
#include <mission/obc/ccsdsboard/VirtualChannel.h>
|
||||
#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;
|
||||
}
|
||||
|
@ -4,33 +4,16 @@
|
||||
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include <fsfw/ipc/MessageQueueIF.h>
|
||||
|
||||
#include <framework/ipc/MessageQueue.h>
|
||||
#include <framework/objectmanager/SystemObject.h>
|
||||
#include <framework/osal/OSAL.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/storagemanager/StorageManagerIF.h>
|
||||
#include <framework/timemanager/Countdown.h>
|
||||
#include <framework/tmtcpacket/SpacePacket.h>
|
||||
#include <framework/tmtcservices/AcceptsTelemetryIF.h>
|
||||
#include <mission/obc/ccsdsboard/BoardHandler.h>
|
||||
#include <linux/obc/PtmeIF.h>
|
||||
|
||||
/**
|
||||
* @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_ */
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user