Merge pull request 'meier/ptme' (#104) from meier/ptme into develop
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
Reviewed-on: #104 Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
This commit is contained in:
commit
823decde5c
22
README.md
22
README.md
@ -11,13 +11,14 @@
|
|||||||
4. [Useful and Common Host Commands](#host-commands)
|
4. [Useful and Common Host Commands](#host-commands)
|
||||||
5. [Setting up Prerequisites](#set-up-prereq)
|
5. [Setting up Prerequisites](#set-up-prereq)
|
||||||
6. [Remote Debugging](#remote-debugging)
|
6. [Remote Debugging](#remote-debugging)
|
||||||
7. [Direct Debugging](#direct-debugging)
|
7. [TMTC testing](#tmtc-testing)
|
||||||
8. [Transfering Files to the Q7S](#file-transfer)
|
8. [Direct Debugging](#direct-debugging)
|
||||||
9. [Q7S OBC](#q7s)
|
9. [Transfering Files to the Q7S](#file-transfer)
|
||||||
10. [Static Code Analysis](#static-code-analysis)
|
10. [Q7S OBC](#q7s)
|
||||||
11. [Eclipse](#eclipse)
|
11. [Static Code Analysis](#static-code-analysis)
|
||||||
12. [Running the OBSW on a Raspberry Pi](#rpi)
|
12. [Eclipse](#eclipse)
|
||||||
13. [FSFW](#fsfw)
|
13. [Running the OBSW on a Raspberry Pi](#rpi)
|
||||||
|
14. [FSFW](#fsfw)
|
||||||
|
|
||||||
# <a id="general"></a> General information
|
# <a id="general"></a> General information
|
||||||
|
|
||||||
@ -574,6 +575,13 @@ alias or shell script to do this quickly.
|
|||||||
Note: When now setting up a debug session in the Xilinx SDK or Eclipse, the host must be set
|
Note: When now setting up a debug session in the Xilinx SDK or Eclipse, the host must be set
|
||||||
to localhost instead of the IP address of the Q7S.
|
to localhost instead of the IP address of the Q7S.
|
||||||
|
|
||||||
|
# <a id="tmtc-testing"></a> TMTC testing
|
||||||
|
The OBSW supports sending PUS TM packets via TCP or the PDEC IP Core which transmits the data as CADU frames. To make the CADU frames receivabel by the [TMTC porgram](https://egit.irs.uni-stuttgart.de/eive/eive-tmtc), a python script is running as systemd service on the flatsat PC which forwards TCP commands to the TCP server of the OBC and reads CADU frames from a serial interface. The PUS packets transported with the CADU frames are extracted and forwared to the TMTC program's TCP client. The code of the TMTC bridge can be found [here](https://egit.irs.uni-stuttgart.de/eive/tmtc-bridge). To connect the TMTC program to the TMTC-bridge a port forwarding from a host must be set up with the following command:
|
||||||
|
````
|
||||||
|
ssh -L 1537:127.0.0.1:7100 eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 -t bash
|
||||||
|
````
|
||||||
|
Note: The encoding of the TM packets and conversion of CADU frames takes some time. Thus the replies are received with a larger delay compared to a direct TCP connection.
|
||||||
|
|
||||||
# <a id="direct-debugging"></a> Direct Debugging
|
# <a id="direct-debugging"></a> Direct Debugging
|
||||||
|
|
||||||
1. Assign static IP address to Q7S
|
1. Assign static IP address to Q7S
|
||||||
|
@ -52,6 +52,16 @@ namespace gpioNames {
|
|||||||
static constexpr char EN_RW_4[] = "enable_rw_4";
|
static constexpr char EN_RW_4[] = "enable_rw_4";
|
||||||
static constexpr char SPI_MUX_SELECT[] = "spi_mux_select";
|
static constexpr char SPI_MUX_SELECT[] = "spi_mux_select";
|
||||||
static constexpr char RAD_SENSOR_CHIP_SELECT[] = "rad_sensor_chip_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";
|
||||||
|
static constexpr char RS485_EN_TX_CLOCK[] = "tx_clock_enable_ltc2872";
|
||||||
|
static constexpr char RS485_EN_TX_DATA[] = "tx_data_enable_ltc2872";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +98,15 @@ void initmission::initTasks() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if OBSW_USE_CCSDS_IP_CORE == 1
|
||||||
|
PeriodicTaskIF* ccsdsHandlerTask = factory->createPeriodicTask(
|
||||||
|
"UDP_POLLING", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
|
||||||
|
result = ccsdsHandlerTask->addComponent(objects::CCSDS_HANDLER);
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
initmission::printAddObjectError("CCSDS Handler", objects::CCSDS_HANDLER);
|
||||||
|
}
|
||||||
|
#endif /* OBSW_USE_CCSDS_IP_CORE == 1 */
|
||||||
|
|
||||||
# if BOARD_TE0720 == 0
|
# if BOARD_TE0720 == 0
|
||||||
// FS task, task interval does not matter because it runs in permanent loop, priority low
|
// FS task, task interval does not matter because it runs in permanent loop, priority low
|
||||||
// because it is a non-essential background task
|
// because it is a non-essential background task
|
||||||
@ -147,6 +156,10 @@ void initmission::initTasks() {
|
|||||||
tmtcPollingTask->startTask();
|
tmtcPollingTask->startTask();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if OBSW_USE_CCSDS_IP_CORE == 1
|
||||||
|
ccsdsHandlerTask->startTask();
|
||||||
|
#endif /* OBSW_USE_CCSDS_IP_CORE == 1 */
|
||||||
|
|
||||||
#if BOARD_TE0720 == 0
|
#if BOARD_TE0720 == 0
|
||||||
coreController->startTask();
|
coreController->startTask();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "ObjectFactory.h"
|
#include "ObjectFactory.h"
|
||||||
#include "OBSWConfig.h"
|
#include "OBSWConfig.h"
|
||||||
#include "devConf.h"
|
#include "devConf.h"
|
||||||
|
#include "ccsdsConfig.h"
|
||||||
#include "busConf.h"
|
#include "busConf.h"
|
||||||
#include "tmtc/apid.h"
|
#include "tmtc/apid.h"
|
||||||
#include "devices/addresses.h"
|
#include "devices/addresses.h"
|
||||||
@ -25,8 +25,6 @@
|
|||||||
#include "linux/devices/SusHandler.h"
|
#include "linux/devices/SusHandler.h"
|
||||||
#include "linux/csp/CspCookie.h"
|
#include "linux/csp/CspCookie.h"
|
||||||
#include "linux/csp/CspComIF.h"
|
#include "linux/csp/CspComIF.h"
|
||||||
#include "linux/obc/CCSDSIPCoreBridge.h"
|
|
||||||
|
|
||||||
#include "mission/core/GenericFactory.h"
|
#include "mission/core/GenericFactory.h"
|
||||||
#include "mission/devices/PDU1Handler.h"
|
#include "mission/devices/PDU1Handler.h"
|
||||||
#include "mission/devices/PDU2Handler.h"
|
#include "mission/devices/PDU2Handler.h"
|
||||||
@ -50,6 +48,8 @@
|
|||||||
#include "mission/devices/devicedefinitions/RwDefinitions.h"
|
#include "mission/devices/devicedefinitions/RwDefinitions.h"
|
||||||
#include "mission/devices/devicedefinitions/StarTrackerDefinitions.h"
|
#include "mission/devices/devicedefinitions/StarTrackerDefinitions.h"
|
||||||
#include "mission/devices/GPSHyperionHandler.h"
|
#include "mission/devices/GPSHyperionHandler.h"
|
||||||
|
#include "mission/tmtc/CCSDSHandler.h"
|
||||||
|
#include "mission/tmtc/VirtualChannel.h"
|
||||||
#include "mission/utility/TmFunnel.h"
|
#include "mission/utility/TmFunnel.h"
|
||||||
|
|
||||||
#include "fsfw_hal/linux/uart/UartComIF.h"
|
#include "fsfw_hal/linux/uart/UartComIF.h"
|
||||||
@ -75,6 +75,10 @@
|
|||||||
#include "linux/boardtest/LibgpiodTest.h"
|
#include "linux/boardtest/LibgpiodTest.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <linux/obc/Ptme.h>
|
||||||
|
#include <linux/obc/PapbVcInterface.h>
|
||||||
|
#include <linux/obc/PtmeConfig.h>
|
||||||
|
|
||||||
ResetArgs resetArgsGnss0;
|
ResetArgs resetArgsGnss0;
|
||||||
ResetArgs resetArgsGnss1;
|
ResetArgs resetArgsGnss1;
|
||||||
|
|
||||||
@ -91,7 +95,12 @@ void Factory::setStaticFrameworkObjectIds() {
|
|||||||
|
|
||||||
//DeviceHandlerBase::powerSwitcherId = objects::PCDU_HANDLER;
|
//DeviceHandlerBase::powerSwitcherId = objects::PCDU_HANDLER;
|
||||||
DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
|
DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
|
||||||
|
|
||||||
|
#if OBSW_TM_TO_PTME == 1
|
||||||
|
TmFunnel::downlinkDestination = objects::CCSDS_HANDLER;
|
||||||
|
#else
|
||||||
TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
|
TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
|
||||||
|
#endif /* OBSW_TM_TO_PTME == 1 */
|
||||||
// No storage object for now.
|
// No storage object for now.
|
||||||
TmFunnel::storageDestination = objects::NO_OBJECT;
|
TmFunnel::storageDestination = objects::NO_OBJECT;
|
||||||
|
|
||||||
@ -164,6 +173,10 @@ void ObjectFactory::produce(void* args) {
|
|||||||
|
|
||||||
#endif /* TE7020 != 0 */
|
#endif /* TE7020 != 0 */
|
||||||
|
|
||||||
|
#if OBSW_USE_CCSDS_IP_CORE == 1
|
||||||
|
createCcsdsComponents(gpioComIF);
|
||||||
|
#endif /* OBSW_USE_CCSDS_IP_CORE == 1 */
|
||||||
|
|
||||||
/* Test Task */
|
/* Test Task */
|
||||||
#if OBSW_ADD_TEST_CODE == 1
|
#if OBSW_ADD_TEST_CODE == 1
|
||||||
createTestComponents(gpioComIF);
|
createTestComponents(gpioComIF);
|
||||||
@ -863,6 +876,85 @@ void ObjectFactory::createReactionWheelComponents(LinuxLibgpioIF* gpioComIF) {
|
|||||||
rw4SpiCookie->setCallbackArgs(rwHandler4);
|
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(ccsds::VC2, config::VC2_QUEUE_SIZE);
|
||||||
|
ccsdsHandler->addVirtualChannel(ccsds::VC2, vc);
|
||||||
|
vc = new VirtualChannel(ccsds::VC3, config::VC3_QUEUE_SIZE);
|
||||||
|
ccsdsHandler->addVirtualChannel(ccsds::VC3, vc);
|
||||||
|
|
||||||
|
GpioCookie* gpioRS485Chip = new GpioCookie;
|
||||||
|
gpio = new GpiodRegularByLineName(q7s::gpioNames::RS485_EN_TX_CLOCK, "RS485 Transceiver",
|
||||||
|
gpio::Direction::OUT, gpio::HIGH);
|
||||||
|
gpioRS485Chip->addGpio(gpioIds::RS485_EN_TX_CLOCK, gpio);
|
||||||
|
gpio = new GpiodRegularByLineName(q7s::gpioNames::RS485_EN_TX_DATA, "RS485 Transceiver",
|
||||||
|
gpio::Direction::OUT, gpio::HIGH);
|
||||||
|
gpioRS485Chip->addGpio(gpioIds::RS485_EN_TX_DATA, gpio);
|
||||||
|
|
||||||
|
gpioComIF->addGpios(gpioRS485Chip);
|
||||||
|
}
|
||||||
|
|
||||||
void ObjectFactory::createTestComponents(LinuxLibgpioIF* gpioComIF) {
|
void ObjectFactory::createTestComponents(LinuxLibgpioIF* gpioComIF) {
|
||||||
|
|
||||||
#if BOARD_TE0720 == 0
|
#if BOARD_TE0720 == 0
|
||||||
@ -901,10 +993,10 @@ void ObjectFactory::createTestComponents(LinuxLibgpioIF* gpioComIF) {
|
|||||||
|
|
||||||
#if BOARD_TE0720 == 1 && OBSW_TEST_CCSDS_BRIDGE == 1
|
#if BOARD_TE0720 == 1 && OBSW_TEST_CCSDS_BRIDGE == 1
|
||||||
GpioCookie* gpioCookieCcsdsIp = new GpioCookie;
|
GpioCookie* gpioCookieCcsdsIp = new GpioCookie;
|
||||||
GpiodRegular* papbBusyN = new GpiodRegular(std::string("gpiochip0"), 0, std::string("PAPBBusy_N"));
|
GpiodRegular* papbBusyN = new GpiodRegular(std::string("gpiochip0"), 0, std::string("PAPBBusy_VC0"));
|
||||||
gpioCookieCcsdsIp->addGpio(gpioIds::PAPB_BUSY_N, papbBusyN);
|
gpioCookieCcsdsIp->addGpio(gpioIds::PAPB_BUSY_N, papbBusyN);
|
||||||
GpiodRegular* papbEmpty = new GpiodRegular(std::string("gpiochip0"), 1,
|
GpiodRegular* papbEmpty = new GpiodRegular(std::string("gpiochip0"), 1,
|
||||||
std::string("Chip Select Sus Sensor"));
|
std::string("PAPBEmpty_VC0"));
|
||||||
gpioCookieCcsdsIp->addGpio(gpioIds::PAPB_EMPTY, papbEmpty);
|
gpioCookieCcsdsIp->addGpio(gpioIds::PAPB_EMPTY, papbEmpty);
|
||||||
gpioComIF->addGpios(gpioCookieCcsdsIp);
|
gpioComIF->addGpios(gpioCookieCcsdsIp);
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ void createSolarArrayDeploymentComponents();
|
|||||||
void createSyrlinksComponents();
|
void createSyrlinksComponents();
|
||||||
void createRtdComponents(LinuxLibgpioIF* gpioComIF);
|
void createRtdComponents(LinuxLibgpioIF* gpioComIF);
|
||||||
void createReactionWheelComponents(LinuxLibgpioIF* gpioComIF);
|
void createReactionWheelComponents(LinuxLibgpioIF* gpioComIF);
|
||||||
|
void createCcsdsComponents(LinuxLibgpioIF *gpioComIF);
|
||||||
void createTestComponents(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_ */
|
@ -17,6 +17,7 @@ enum commonClassIds: uint8_t {
|
|||||||
PLOC_SUPERVISOR_HANDLER, //PLSV
|
PLOC_SUPERVISOR_HANDLER, //PLSV
|
||||||
SUS_HANDLER, //SUSS
|
SUS_HANDLER, //SUSS
|
||||||
CCSDS_IP_CORE_BRIDGE, //IPCI
|
CCSDS_IP_CORE_BRIDGE, //IPCI
|
||||||
|
PTME, //PTME
|
||||||
PLOC_UPDATER, //PLUD
|
PLOC_UPDATER, //PLUD
|
||||||
GOM_SPACE_HANDLER, //GOMS
|
GOM_SPACE_HANDLER, //GOMS
|
||||||
PLOC_MEMORY_DUMPER, //PLMEMDUMP
|
PLOC_MEMORY_DUMPER, //PLMEMDUMP
|
||||||
|
@ -9,6 +9,13 @@
|
|||||||
#define OBSW_ADD_TCPIP_BRIDGE 1
|
#define OBSW_ADD_TCPIP_BRIDGE 1
|
||||||
// Use TCP instead of UDP for the TMTC bridge. This allows using the TMTC client locally
|
// Use TCP instead of UDP for the TMTC bridge. This allows using the TMTC client locally
|
||||||
// because UDP packets are not allowed in the VPN
|
// because UDP packets are not allowed in the VPN
|
||||||
|
// This will cause the OBSW to initialize the TMTC bridge responsible for exchanging data with the
|
||||||
|
// CCSDS IP Cores.
|
||||||
|
#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 1
|
||||||
|
// Set to 1 if telecommands are received via the PDEC IP Core
|
||||||
|
#define OBSW_TC_FROM_PDEC 0
|
||||||
#define OBSW_USE_TCP_BRIDGE 1
|
#define OBSW_USE_TCP_BRIDGE 1
|
||||||
|
|
||||||
namespace common {
|
namespace common {
|
||||||
|
@ -11,6 +11,12 @@ enum commonObjects: uint32_t {
|
|||||||
TMTC_BRIDGE = 0x50000300,
|
TMTC_BRIDGE = 0x50000300,
|
||||||
TMTC_POLLING_TASK = 0x50000400,
|
TMTC_POLLING_TASK = 0x50000400,
|
||||||
FILE_SYSTEM_HANDLER = 0x50000500,
|
FILE_SYSTEM_HANDLER = 0x50000500,
|
||||||
|
PTME = 0x50000600,
|
||||||
|
PAPB_VC0 = 0x50000700,
|
||||||
|
PAPB_VC1 = 0x50000701,
|
||||||
|
PAPB_VC2 = 0x50000702,
|
||||||
|
PAPB_VC3 = 0x50000703,
|
||||||
|
CCSDS_HANDLER = 0x50000800,
|
||||||
|
|
||||||
/* 0x43 ('C') for Controllers */
|
/* 0x43 ('C') for Controllers */
|
||||||
THERMAL_CONTROLLER = 0x43400001,
|
THERMAL_CONTROLLER = 0x43400001,
|
||||||
|
2
fsfw
2
fsfw
@ -1 +1 @@
|
|||||||
Subproject commit 3d0ce1998114c5d7a43034233ee03a800c8821b0
|
Subproject commit a578f0390bce6c0a3d1d1e8d59764072f1075867
|
@ -1,7 +1,7 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include <linux/obc/CCSDSIPCoreBridge.h>
|
#include <linux/obc/Ptme.h>
|
||||||
|
|
||||||
CCSDSIPCoreBridge::CCSDSIPCoreBridge(object_id_t objectId, object_id_t tcDestination,
|
CCSDSIPCoreBridge::CCSDSIPCoreBridge(object_id_t objectId, object_id_t tcDestination,
|
||||||
object_id_t tmStoreId, object_id_t tcStoreId, LinuxLibgpioIF* gpioComIF,
|
object_id_t tmStoreId, object_id_t tcStoreId, LinuxLibgpioIF* gpioComIF,
|
@ -86,6 +86,7 @@ debugging. */
|
|||||||
#define OBSW_TEST_TE7020_HEATER 0
|
#define OBSW_TEST_TE7020_HEATER 0
|
||||||
#define OBSW_TEST_GPIO_OPEN_BY_LABEL 0
|
#define OBSW_TEST_GPIO_OPEN_BY_LABEL 0
|
||||||
#define OBSW_TEST_GPIO_OPEN_BY_LINE_NAME 0
|
#define OBSW_TEST_GPIO_OPEN_BY_LINE_NAME 0
|
||||||
|
#define OBSW_LINK_IS_UP 1
|
||||||
|
|
||||||
#define OBSW_DEBUG_P60DOCK 0
|
#define OBSW_DEBUG_P60DOCK 0
|
||||||
#define OBSW_DEBUG_PDU1 0
|
#define OBSW_DEBUG_PDU1 0
|
||||||
@ -123,6 +124,14 @@ namespace config {
|
|||||||
/* Add mission configuration flags here */
|
/* Add mission configuration flags here */
|
||||||
static constexpr uint32_t OBSW_FILESYSTEM_HANDLER_QUEUE_SIZE = 50;
|
static constexpr uint32_t OBSW_FILESYSTEM_HANDLER_QUEUE_SIZE = 50;
|
||||||
static constexpr uint32_t PLOC_UPDATER_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;
|
||||||
|
|
||||||
|
static constexpr uint8_t LIVE_TM = 0;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,20 @@ enum gpioId_t {
|
|||||||
|
|
||||||
EN_RW_CS,
|
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,
|
||||||
|
|
||||||
|
|
||||||
|
RS485_EN_TX_DATA,
|
||||||
|
RS485_EN_TX_CLOCK
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
target_sources(${TARGET_NAME} PUBLIC
|
target_sources(${TARGET_NAME} PUBLIC
|
||||||
CCSDSIPCoreBridge.cpp
|
PapbVcInterface.cpp
|
||||||
|
Ptme.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
104
linux/obc/PapbVcInterface.cpp
Normal file
104
linux/obc/PapbVcInterface.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#include <linux/obc/PapbVcInterface.h>
|
||||||
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
|
PapbVcInterface::PapbVcInterface(object_id_t objectId, LinuxLibgpioIF* gpioComIF,
|
||||||
|
gpioId_t papbBusyId, gpioId_t papbEmptyId, uint32_t vcOffset) :
|
||||||
|
SystemObject(objectId), gpioComIF(gpioComIF), papbBusyId(
|
||||||
|
papbBusyId), papbEmptyId(papbEmptyId), vcOffset(vcOffset) {
|
||||||
|
}
|
||||||
|
|
||||||
|
PapbVcInterface::~PapbVcInterface() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PapbVcInterface::setRegisterAddress(uint32_t* ptmeBaseAddress) {
|
||||||
|
vcBaseReg = ptmeBaseAddress + vcOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PapbVcInterface::write(const uint8_t * data, size_t size) {
|
||||||
|
|
||||||
|
if(pollPapbBusySignal() == RETURN_OK) {
|
||||||
|
startPacketTransfer();
|
||||||
|
}
|
||||||
|
|
||||||
|
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::write: Only written " << idx << " of "
|
||||||
|
<< size << " data" << std::endl;
|
||||||
|
return RETURN_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pollPapbBusySignal() == RETURN_OK) {
|
||||||
|
endPacketTransfer();
|
||||||
|
}
|
||||||
|
return RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PapbVcInterface::startPacketTransfer() {
|
||||||
|
*vcBaseReg = CONFIG_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PapbVcInterface::endPacketTransfer() {
|
||||||
|
*vcBaseReg = CONFIG_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PapbVcInterface::pollPapbBusySignal() {
|
||||||
|
int papbBusyState = 0;
|
||||||
|
ReturnValue_t result = RETURN_OK;
|
||||||
|
|
||||||
|
/** Check if PAPB interface is ready to receive data */
|
||||||
|
result = gpioComIF->readGpio(papbBusyId, &papbBusyState);
|
||||||
|
if (result != RETURN_OK) {
|
||||||
|
sif::warning << "PapbVcInterface::pollPapbBusySignal: Failed to read papb busy signal"
|
||||||
|
<< std::endl;
|
||||||
|
return RETURN_FAILED;
|
||||||
|
}
|
||||||
|
if (!papbBusyState) {
|
||||||
|
sif::warning << "PapbVcInterface::pollPapbBusySignal: PAPB busy" << std::endl;
|
||||||
|
return PAPB_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PapbVcInterface::isVcInterfaceBufferEmpty() {
|
||||||
|
ReturnValue_t result = RETURN_OK;
|
||||||
|
int papbEmptyState = 1;
|
||||||
|
|
||||||
|
result = gpioComIF->readGpio(papbEmptyId, &papbEmptyState);
|
||||||
|
|
||||||
|
if (result != RETURN_OK) {
|
||||||
|
sif::warning << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal"
|
||||||
|
<< std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (papbEmptyState == 1) {
|
||||||
|
sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is empty" << std::endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is not empty" << std::endl;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PapbVcInterface::sendTestFrame() {
|
||||||
|
/** Size of one complete transfer frame data field amounts to 1105 bytes */
|
||||||
|
uint8_t testPacket[1105];
|
||||||
|
|
||||||
|
/** Fill one test packet */
|
||||||
|
for(int idx = 0; idx < 1105; idx++) {
|
||||||
|
testPacket[idx] = static_cast<uint8_t>(idx & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t result = write(testPacket, 1105);
|
||||||
|
if(result != RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RETURN_OK;
|
||||||
|
}
|
112
linux/obc/PapbVcInterface.h
Normal file
112
linux/obc/PapbVcInterface.h
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
#ifndef LINUX_OBC_PAPBVCINTERFACE_H_
|
||||||
|
#define LINUX_OBC_PAPBVCINTERFACE_H_
|
||||||
|
|
||||||
|
#include "OBSWConfig.h"
|
||||||
|
#include "linux/obc/VcInterfaceIF.h"
|
||||||
|
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
|
||||||
|
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.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
|
||||||
|
* via the PAPB interface.
|
||||||
|
*
|
||||||
|
* @author J. Meier
|
||||||
|
*/
|
||||||
|
class PapbVcInterface: public SystemObject,
|
||||||
|
public VcInterfaceIF,
|
||||||
|
public HasReturnvaluesIF {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
*
|
||||||
|
* @param objectId
|
||||||
|
* @param papbBusyId The ID of the GPIO which is connected to the PAPBBusy_N signal of the
|
||||||
|
* VcInterface IP Core. A low logic level indicates the VcInterface is not
|
||||||
|
* ready to receive more data.
|
||||||
|
* @param papbEmptyId The ID of the GPIO which is connected to the PAPBEmpty signal of the
|
||||||
|
* VcInterface IP Core. The signal is high when there are no packets in the
|
||||||
|
* external buffer memory (BRAM).
|
||||||
|
*/
|
||||||
|
PapbVcInterface(object_id_t objectId, LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId,
|
||||||
|
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;
|
||||||
|
|
||||||
|
static const ReturnValue_t PAPB_BUSY = MAKE_RETURN_CODE(0xA0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration bits:
|
||||||
|
* bit[1:0]: Size of data (1,2,3 or 4 bytes). 1 Byte <=> b00
|
||||||
|
* bit[2]: Set this bit to 1 to abort a transfered packet
|
||||||
|
* bit[3]: Signals to VcInterface the start of a new telemetry packet
|
||||||
|
*/
|
||||||
|
static const uint32_t CONFIG_START = 0x8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writing this word to the VcInterface base address signals to the virtual channel interface
|
||||||
|
* that a complete tm packet has been transferred.
|
||||||
|
*/
|
||||||
|
static const uint32_t CONFIG_END = 0x0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writing to this offset within the memory space of a virtual channel will insert data for
|
||||||
|
* encoding to the external buffer memory of the PTME IP Core.
|
||||||
|
* The address offset is 0x400 (= 4 * 256)
|
||||||
|
*/
|
||||||
|
static const int DATA_REG_OFFSET = 256;
|
||||||
|
|
||||||
|
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||||
|
|
||||||
|
/** Pulled to low when virtual channel not ready to receive data */
|
||||||
|
gpioId_t papbBusyId = gpio::NO_GPIO;
|
||||||
|
/** High when external buffer memory of virtual channel is empty */
|
||||||
|
gpioId_t papbEmptyId = gpio::NO_GPIO;
|
||||||
|
|
||||||
|
uint32_t* vcBaseReg = nullptr;
|
||||||
|
|
||||||
|
uint32_t vcOffset = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function sends the config byte to the virtual channel of the PTME IP Core
|
||||||
|
* to initiate a packet transfer.
|
||||||
|
*/
|
||||||
|
void startPacketTransfer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function sends the config byte to the virtual channel interface of the PTME
|
||||||
|
* IP Core to signal the end of a packet transfer.
|
||||||
|
*/
|
||||||
|
void endPacketTransfer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function reads the papb busy signal indicating whether the virtual channel
|
||||||
|
* interface is ready to receive more data or not. PAPB is ready when
|
||||||
|
* PAPB_Busy_N == '1'.
|
||||||
|
*
|
||||||
|
* @return RETURN_OK when ready to receive data else PAPB_BUSY.
|
||||||
|
*/
|
||||||
|
ReturnValue_t pollPapbBusySignal();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function can be used for debugging to check whether there are packets in
|
||||||
|
* the packet buffer of the virtual channel or not.
|
||||||
|
*/
|
||||||
|
void isVcInterfaceBufferEmpty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function sends a complete telemetry transfer frame data field (1105 bytes)
|
||||||
|
* to the papb interface of the PTME IP Core. Can be used to test the implementation.
|
||||||
|
*/
|
||||||
|
ReturnValue_t sendTestFrame();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* LINUX_OBC_PAPBVCINTERFACE_H_ */
|
73
linux/obc/Ptme.cpp
Normal file
73
linux/obc/Ptme.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include <sys/mman.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <linux/obc/Ptme.h>
|
||||||
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
#include "PtmeConfig.h"
|
||||||
|
|
||||||
|
Ptme::Ptme(object_id_t objectId) :
|
||||||
|
SystemObject(objectId) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Ptme::~Ptme() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Ptme::initialize() {
|
||||||
|
|
||||||
|
int fd = open(PtmeConfig::UIO_DEVICE_FILE, O_RDWR);
|
||||||
|
if (fd < 1) {
|
||||||
|
sif::warning << "Ptme::initialize: Invalid UIO device file" << std::endl;
|
||||||
|
return RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map uio device in virtual address space
|
||||||
|
* PROT_WRITE: Map uio device in writable only mode
|
||||||
|
*/
|
||||||
|
ptmeBaseAddress = static_cast<uint32_t*>(mmap(NULL, MAP_SIZE, PROT_WRITE,
|
||||||
|
MAP_SHARED, fd, 0));
|
||||||
|
|
||||||
|
if (ptmeBaseAddress == MAP_FAILED) {
|
||||||
|
sif::error << "Ptme::initialize: Failed to map uio address" << std::endl;
|
||||||
|
return RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
VcInterfaceMapIter iter;
|
||||||
|
for (iter = vcInterfaceMap.begin(); iter != vcInterfaceMap.end(); iter++) {
|
||||||
|
iter->second->setRegisterAddress(ptmeBaseAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
return RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t * data, size_t size) {
|
||||||
|
ReturnValue_t result = RETURN_OK;
|
||||||
|
VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId);
|
||||||
|
if (vcInterfaceMapIter == vcInterfaceMap.end()) {
|
||||||
|
sif::warning << "Ptme::writeToVc: No virtual channel interface found for the virtual "
|
||||||
|
"channel with id " << static_cast<unsigned int>(vcId) << std::endl;
|
||||||
|
return UNKNOWN_VC_ID;
|
||||||
|
}
|
||||||
|
result = vcInterfaceMapIter->second->write(data, size);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ptme::addVcInterface(VcId_t vcId, VcInterfaceIF* vc) {
|
||||||
|
|
||||||
|
if (vcId > config::NUMBER_OF_VIRTUAL_CHANNELS) {
|
||||||
|
sif::warning << "Ptme::addVcInterface: Invalid virtual channel ID" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vc == nullptr) {
|
||||||
|
sif::warning << "Ptme::addVcInterface: Invalid virtual channel interface" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto status = vcInterfaceMap.emplace(vcId, vc);
|
||||||
|
if (status.second == false) {
|
||||||
|
sif::warning << "Ptme::addVcInterface: Failed to add virtual channel interface to "
|
||||||
|
"virtual channel map" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
91
linux/obc/Ptme.h
Normal file
91
linux/obc/Ptme.h
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#ifndef LINUX_OBC_PTME_H_
|
||||||
|
#define LINUX_OBC_PTME_H_
|
||||||
|
|
||||||
|
#include "OBSWConfig.h"
|
||||||
|
#include "linux/obc/PtmeIF.h"
|
||||||
|
#include "linux/obc/VcInterfaceIF.h"
|
||||||
|
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
|
||||||
|
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
|
||||||
|
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This class handles the interfacing to the telemetry (PTME) IP core responsible for the
|
||||||
|
* encoding of telemetry packets according to the CCSDS standards CCSDS 131.0-B-3 (TM Synchro-
|
||||||
|
* nization and channel coding) and CCSDS 132.0-B-2 (TM Space Data Link Protocoll).
|
||||||
|
* The IP cores are implemented on the programmable logic and are accessible through the
|
||||||
|
* linux UIO driver.
|
||||||
|
*/
|
||||||
|
class Ptme : public PtmeIF,
|
||||||
|
public SystemObject,
|
||||||
|
public HasReturnvaluesIF {
|
||||||
|
public:
|
||||||
|
|
||||||
|
using VcId_t = uint8_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
*
|
||||||
|
* @param objectId
|
||||||
|
*/
|
||||||
|
Ptme(object_id_t objectId);
|
||||||
|
virtual ~Ptme();
|
||||||
|
|
||||||
|
ReturnValue_t initialize() 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
|
||||||
|
* map.
|
||||||
|
*/
|
||||||
|
void addVcInterface(VcId_t vcId, VcInterfaceIF* vc);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static const uint8_t INTERFACE_ID = CLASS_ID::PTME;
|
||||||
|
|
||||||
|
static const ReturnValue_t UNKNOWN_VC_ID = MAKE_RETURN_CODE(0xA0);
|
||||||
|
|
||||||
|
#if BOARD_TE0720 == 1
|
||||||
|
/** Size of mapped address space */
|
||||||
|
static const int MAP_SIZE = 0x40000;
|
||||||
|
#else
|
||||||
|
/** Size of mapped address space */
|
||||||
|
static const int MAP_SIZE = 0x40000;
|
||||||
|
#endif /* BOARD_TE0720 == 1 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration bits:
|
||||||
|
* bit[1:0]: Size of data (1,2,3 or 4 bytes). 1 Byte <=> b00
|
||||||
|
* bit[2]: Set this bit to 1 to abort a transfered packet
|
||||||
|
* bit[3]: Signals to PTME the start of a new telemetry packet
|
||||||
|
*/
|
||||||
|
static const uint32_t PTME_CONFIG_START = 0x8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writing this word to the ptme base address signals to the PTME that a complete tm packet has
|
||||||
|
* been transferred.
|
||||||
|
*/
|
||||||
|
static const uint32_t PTME_CONFIG_END = 0x0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writing to this offset within the PTME memory space will insert data for encoding to the
|
||||||
|
* PTME IP core.
|
||||||
|
* The address offset is 0x400 (= 4 * 256)
|
||||||
|
*/
|
||||||
|
static const int PTME_DATA_REG_OFFSET = 256;
|
||||||
|
|
||||||
|
/** The file descriptor of the UIO driver */
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
uint32_t* ptmeBaseAddress = nullptr;
|
||||||
|
|
||||||
|
using VcInterfaceMap = std::unordered_map<VcId_t, VcInterfaceIF*>;
|
||||||
|
using VcInterfaceMapIter = VcInterfaceMap::iterator;
|
||||||
|
|
||||||
|
VcInterfaceMap vcInterfaceMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* LINUX_OBC_PTME_H_ */
|
26
linux/obc/PtmeConfig.h
Normal file
26
linux/obc/PtmeConfig.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef LINUX_OBC_PTMECONFIG_H_
|
||||||
|
#define LINUX_OBC_PTMECONFIG_H_
|
||||||
|
|
||||||
|
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configuration parameters derived from FPGA design and device tree.
|
||||||
|
*
|
||||||
|
* @author J. Meier
|
||||||
|
*/
|
||||||
|
namespace PtmeConfig {
|
||||||
|
/**
|
||||||
|
* Offset of virtual channels mapped into address space
|
||||||
|
* 0x10000 = (0x4000 * 4)
|
||||||
|
*/
|
||||||
|
static const uint32_t VC0_OFFSETT = 0;
|
||||||
|
static const uint32_t VC1_OFFSETT = 0x4000;
|
||||||
|
static const uint32_t VC2_OFFSETT = 0x8000;
|
||||||
|
static const uint32_t VC3_OFFSETT = 0xC000;
|
||||||
|
|
||||||
|
static const char UIO_DEVICE_FILE[] = "/dev/uio0";
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* LINUX_OBC_PTMECONFIG_H_ */
|
28
linux/obc/PtmeIF.h
Normal file
28
linux/obc/PtmeIF.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef LINUX_OBC_PTMEIF_H_
|
||||||
|
#define LINUX_OBC_PTMEIF_H_
|
||||||
|
|
||||||
|
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interface class for managing the PTME IP Core implemented in the programmable logic.
|
||||||
|
*
|
||||||
|
* @details PTME IP Core: https://www.esa.int/Enabling_Support/Space_Engineering_Technology/
|
||||||
|
* Microelectronics/PTME
|
||||||
|
* @author J. Meier
|
||||||
|
*/
|
||||||
|
class PtmeIF {
|
||||||
|
public:
|
||||||
|
virtual ~PtmeIF(){};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Implements to function to write to a specific virtual channel.
|
||||||
|
*
|
||||||
|
* @param vcId Virtual channel to write to
|
||||||
|
* @param data Pointer to buffer holding the data to write
|
||||||
|
* @param size Number of bytes to write
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* LINUX_OBC_PTMEIF_H_ */
|
29
linux/obc/VcInterfaceIF.h
Normal file
29
linux/obc/VcInterfaceIF.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef LINUX_OBC_VCINTERFACEIF_H_
|
||||||
|
#define LINUX_OBC_VCINTERFACEIF_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interface class for managing different virtual channels of the PTME IP core implemented
|
||||||
|
* in the programmable logic.
|
||||||
|
*
|
||||||
|
* @author J. Meier
|
||||||
|
*/
|
||||||
|
class VcInterfaceIF {
|
||||||
|
public:
|
||||||
|
virtual ~VcInterfaceIF(){};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Implememts the functionality to write data in the virtual channel of the PTME IP
|
||||||
|
* Core.
|
||||||
|
*
|
||||||
|
* @param data Pointer to buffer holding the data to write
|
||||||
|
* @param size Number of bytes to write
|
||||||
|
*/
|
||||||
|
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(devices)
|
||||||
add_subdirectory(utility)
|
add_subdirectory(utility)
|
||||||
add_subdirectory(memory)
|
add_subdirectory(memory)
|
||||||
|
add_subdirectory(tmtc)
|
||||||
|
122
mission/tmtc/CCSDSHandler.cpp
Normal file
122
mission/tmtc/CCSDSHandler.cpp
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
|
||||||
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
|
#include "fsfw/ipc/QueueFactory.h"
|
||||||
|
|
||||||
|
#include "CCSDSHandler.h"
|
||||||
|
|
||||||
|
CCSDSHandler::CCSDSHandler(object_id_t objectId, object_id_t ptmeId) :
|
||||||
|
SystemObject(objectId), ptmeId(ptmeId), parameterHelper(this) {
|
||||||
|
commandQueue = QueueFactory::instance()->createMessageQueue(QUEUE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
CCSDSHandler::~CCSDSHandler() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CCSDSHandler::performOperation(uint8_t operationCode) {
|
||||||
|
readCommandQueue();
|
||||||
|
handleTelemetry();
|
||||||
|
handleTelecommands();
|
||||||
|
return RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCSDSHandler::handleTelemetry() {
|
||||||
|
VirtualChannelMapIter iter;
|
||||||
|
for (iter = virtualChannelMap.begin(); iter != virtualChannelMap.end(); iter++) {
|
||||||
|
iter->second->performOperation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCSDSHandler::handleTelecommands() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CCSDSHandler::initialize() {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = parameterHelper.initialize();
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VirtualChannelMapIter iter;
|
||||||
|
for (iter = virtualChannelMap.begin(); iter != virtualChannelMap.end(); iter++) {
|
||||||
|
result = iter->second->initialize();
|
||||||
|
if (result != RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
iter->second->setPtmeObject(ptme);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCSDSHandler::readCommandQueue(void) {
|
||||||
|
CommandMessage commandMessage;
|
||||||
|
ReturnValue_t result = RETURN_FAILED;
|
||||||
|
|
||||||
|
result = commandQueue->receiveMessage(&commandMessage);
|
||||||
|
if (result == RETURN_OK) {
|
||||||
|
result = parameterHelper.handleParameterMessage(&commandMessage);
|
||||||
|
if (result == RETURN_OK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CommandMessage reply;
|
||||||
|
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND,
|
||||||
|
commandMessage.getCommand());
|
||||||
|
commandQueue->reply(&reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageQueueId_t CCSDSHandler::getCommandQueue() const {
|
||||||
|
return commandQueue->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virtualChannel == nullptr) {
|
||||||
|
sif::warning << "CCSDSHandler::addVirtualChannel: Invalid virtual channel interface" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto status = virtualChannelMap.emplace(vcId, virtualChannel);
|
||||||
|
if (status.second == false) {
|
||||||
|
sif::warning << "CCSDSHandler::addVirtualChannel: Failed to add virtual channel to "
|
||||||
|
"virtual channel map" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageQueueId_t CCSDSHandler::getReportReceptionQueue(uint8_t virtualChannel) {
|
||||||
|
if (virtualChannel < config::NUMBER_OF_VIRTUAL_CHANNELS) {
|
||||||
|
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,
|
||||||
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
|
uint16_t startAtIndex) {
|
||||||
|
return RETURN_OK;
|
||||||
|
}
|
75
mission/tmtc/CCSDSHandler.h
Normal file
75
mission/tmtc/CCSDSHandler.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#ifndef CCSDSHANDLER_H_
|
||||||
|
#define CCSDSHANDLER_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
|
||||||
|
* programmable logic of the Q7S.
|
||||||
|
*
|
||||||
|
* @author J. Meier
|
||||||
|
*/
|
||||||
|
class CCSDSHandler: public SystemObject,
|
||||||
|
public ExecutableObjectIF,
|
||||||
|
public AcceptsTelemetryIF,
|
||||||
|
public HasReturnvaluesIF,
|
||||||
|
public ReceivesParameterMessagesIF {
|
||||||
|
public:
|
||||||
|
|
||||||
|
using VcId_t = uint8_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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();
|
||||||
|
|
||||||
|
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||||
|
ReturnValue_t initialize();
|
||||||
|
MessageQueueId_t getCommandQueue() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function to add a virtual channel
|
||||||
|
*
|
||||||
|
* @param virtualChannelId ID of the virtual channel to add
|
||||||
|
* @param virtualChannel Pointer to virtual channel object
|
||||||
|
*/
|
||||||
|
void addVirtualChannel(VcId_t virtualChannelId, VirtualChannel* virtualChannel);
|
||||||
|
|
||||||
|
MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0);
|
||||||
|
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
|
||||||
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
|
uint16_t startAtIndex);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
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();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CCSDSHANDLER_H_ */
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
|
69
mission/tmtc/VirtualChannel.cpp
Normal file
69
mission/tmtc/VirtualChannel.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include "CCSDSHandler.h"
|
||||||
|
#include "VirtualChannel.h"
|
||||||
|
#include "OBSWConfig.h"
|
||||||
|
|
||||||
|
#include "fsfw/serviceinterface/ServiceInterfaceStream.h"
|
||||||
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
|
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||||
|
#include "fsfw/ipc/QueueFactory.h"
|
||||||
|
|
||||||
|
|
||||||
|
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<StorageManagerIF>(objects::TM_STORE);
|
||||||
|
if(tmStore == nullptr) {
|
||||||
|
sif::error << "VirtualChannel::initialize: Failed to get tm store" << std::endl;
|
||||||
|
return RETURN_FAILED;
|
||||||
|
}
|
||||||
|
return RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t VirtualChannel::performOperation() {
|
||||||
|
ReturnValue_t result = 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(vcId, 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;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptme = ptme_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VirtualChannel::setLinkState(bool linkIsUp) {
|
||||||
|
linkIsUp = linkIsUp;
|
||||||
|
}
|
58
mission/tmtc/VirtualChannel.h
Normal file
58
mission/tmtc/VirtualChannel.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#ifndef VIRTUALCHANNEL_H_
|
||||||
|
#define VIRTUALCHANNEL_H_
|
||||||
|
|
||||||
|
#include "OBSWConfig.h"
|
||||||
|
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
|
||||||
|
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||||
|
#include <fsfw/ipc/MessageQueueIF.h>
|
||||||
|
#include <linux/obc/PtmeIF.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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:
|
||||||
|
/**
|
||||||
|
* @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();
|
||||||
|
MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) override;
|
||||||
|
ReturnValue_t performOperation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the PTME object which handles access to the PTME IP Core.
|
||||||
|
*
|
||||||
|
* @param ptme Pointer to ptme object
|
||||||
|
*/
|
||||||
|
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 vcId;
|
||||||
|
|
||||||
|
#if OBSW_LINK_IS_UP == 1
|
||||||
|
bool linkIsUp = true;
|
||||||
|
#else
|
||||||
|
bool linkIsUp = false;
|
||||||
|
#endif /* OBSW_LINK_IS_UP == 1 */
|
||||||
|
|
||||||
|
StorageManagerIF* tmStore = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* VIRTUALCHANNEL_H_ */
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "OBSWConfig.h"
|
||||||
#include <fsfw/ipc/QueueFactory.h>
|
#include <fsfw/ipc/QueueFactory.h>
|
||||||
#include <fsfw/tmtcpacket/pus/tm.h>
|
#include <fsfw/tmtcpacket/pus/tm.h>
|
||||||
#include <fsfw/objectmanager/ObjectManager.h>
|
#include <fsfw/objectmanager/ObjectManager.h>
|
||||||
@ -45,7 +46,7 @@ ReturnValue_t TmFunnel::performOperation(uint8_t operationCode) {
|
|||||||
ReturnValue_t TmFunnel::handlePacket(TmTcMessage* message) {
|
ReturnValue_t TmFunnel::handlePacket(TmTcMessage* message) {
|
||||||
uint8_t* packetData = nullptr;
|
uint8_t* packetData = nullptr;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result = tmPool->modifyData(message->getStorageId(),
|
ReturnValue_t result = tmStore->modifyData(message->getStorageId(),
|
||||||
&packetData, &size);
|
&packetData, &size);
|
||||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||||
return result;
|
return result;
|
||||||
@ -59,7 +60,7 @@ ReturnValue_t TmFunnel::handlePacket(TmTcMessage* message) {
|
|||||||
|
|
||||||
result = tmQueue->sendToDefault(message);
|
result = tmQueue->sendToDefault(message);
|
||||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||||
tmPool->deleteData(message->getStorageId());
|
tmStore->deleteData(message->getStorageId());
|
||||||
sif::error << "TmFunnel::handlePacket: Error sending to downlink "
|
sif::error << "TmFunnel::handlePacket: Error sending to downlink "
|
||||||
"handler" << std::endl;
|
"handler" << std::endl;
|
||||||
return result;
|
return result;
|
||||||
@ -68,7 +69,7 @@ ReturnValue_t TmFunnel::handlePacket(TmTcMessage* message) {
|
|||||||
if(storageDestination != objects::NO_OBJECT) {
|
if(storageDestination != objects::NO_OBJECT) {
|
||||||
result = storageQueue->sendToDefault(message);
|
result = storageQueue->sendToDefault(message);
|
||||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||||
tmPool->deleteData(message->getStorageId());
|
tmStore->deleteData(message->getStorageId());
|
||||||
sif::error << "TmFunnel::handlePacket: Error sending to storage "
|
sif::error << "TmFunnel::handlePacket: Error sending to storage "
|
||||||
"handler" << std::endl;
|
"handler" << std::endl;
|
||||||
return result;
|
return result;
|
||||||
@ -79,8 +80,8 @@ ReturnValue_t TmFunnel::handlePacket(TmTcMessage* message) {
|
|||||||
|
|
||||||
ReturnValue_t TmFunnel::initialize() {
|
ReturnValue_t TmFunnel::initialize() {
|
||||||
|
|
||||||
tmPool = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
|
tmStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
|
||||||
if(tmPool == nullptr) {
|
if(tmStore == nullptr) {
|
||||||
sif::error << "TmFunnel::initialize: TM store not set."
|
sif::error << "TmFunnel::initialize: TM store not set."
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
sif::error << "Make sure the tm store is set up properly"
|
sif::error << "Make sure the tm store is set up properly"
|
||||||
@ -97,7 +98,13 @@ ReturnValue_t TmFunnel::initialize() {
|
|||||||
"properly and implements AcceptsTelemetryIF" << std::endl;
|
"properly and implements AcceptsTelemetryIF" << std::endl;
|
||||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OBSW_TM_TO_PTME == 1
|
||||||
|
// Live TM will be sent via the virtual channel 0
|
||||||
|
tmQueue->setDefaultDestination(tmTarget->getReportReceptionQueue(config::LIVE_TM));
|
||||||
|
#else
|
||||||
tmQueue->setDefaultDestination(tmTarget->getReportReceptionQueue());
|
tmQueue->setDefaultDestination(tmTarget->getReportReceptionQueue());
|
||||||
|
#endif /* OBSW_TM_TO_PTME == 1 */
|
||||||
|
|
||||||
// Storage destination is optional.
|
// Storage destination is optional.
|
||||||
if(storageDestination == objects::NO_OBJECT) {
|
if(storageDestination == objects::NO_OBJECT) {
|
||||||
|
@ -41,7 +41,7 @@ private:
|
|||||||
MessageQueueIF* tmQueue = nullptr;
|
MessageQueueIF* tmQueue = nullptr;
|
||||||
MessageQueueIF* storageQueue = nullptr;
|
MessageQueueIF* storageQueue = nullptr;
|
||||||
|
|
||||||
StorageManagerIF* tmPool = nullptr;
|
StorageManagerIF* tmStore = nullptr;
|
||||||
uint32_t messageDepth = 0;
|
uint32_t messageDepth = 0;
|
||||||
|
|
||||||
ReturnValue_t handlePacket(TmTcMessage* message);
|
ReturnValue_t handlePacket(TmTcMessage* message);
|
||||||
|
@ -7,5 +7,6 @@ echo "-L 1536:192.168.133.10:7301 for TMTC commanding"
|
|||||||
ssh -L 1534:192.168.133.10:1534 \
|
ssh -L 1534:192.168.133.10:1534 \
|
||||||
-L 1535:192.168.133.10:22 \
|
-L 1535:192.168.133.10:22 \
|
||||||
-L 1536:192.168.133.10:7301 \
|
-L 1536:192.168.133.10:7301 \
|
||||||
|
-L 1537:127.0.0.1:7100 \
|
||||||
eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 \
|
eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 \
|
||||||
-t 'CONSOLE_PREFIX="[Q7S Tunnel]" /bin/bash'
|
-t 'CONSOLE_PREFIX="[Q7S Tunnel]" /bin/bash'
|
||||||
|
2
tmtc
2
tmtc
@ -1 +1 @@
|
|||||||
Subproject commit 82495ad785c83440ee90846bce70be1659b66209
|
Subproject commit 1a176582883aed989870819e5e57e0ce0a78ecda
|
Loading…
Reference in New Issue
Block a user