more similar to example now

This commit is contained in:
Robin Müller 2020-09-30 17:17:01 +02:00
parent ffcb6e0213
commit 7ce3e7dd1a
21 changed files with 456 additions and 454 deletions

100
README.md
View File

@ -1,4 +1,98 @@
EIVE On-Board Software
======
# <a id="top"></a> <a name="linux"></a> EIVE On-Board Software
## Linux
These steps were tested for Ubuntu 20.04.
If not done yet, install the full C++ build chain:
```sh
sudo apt-get install build-essential
```
Linux has a limit to message queue message. Please see the section
to set up UNIX environment for more information.
Sometimes, special steps are necessary so the real-time functionalities can be used
without root privileges. Instructions are contained in the setup section
for UNIX as well.
### Building the software
1. Clone the repository with
```sh
git clone https://egit.irs.uni-stuttgart.de/fsfw/fsfw_example.git
```
2. Update all the submodules
```sh
git submodule init
git submodule sync
git submodule update
```
3. After that, the linux binary can be built with:
```sh
make -j all
```
to compile for Linux. All will build the debug version,
which can also be built with the target `debug`. The optimized
release version can be built with the target `release`.
4. Run the binary located inside the `_bin` folder.
### Setting up UNIX environment for real-time functionalities
Please note that on most UNIX environments (e.g. Ubuntu), the real time functionalities
used by the UNIX pthread module are restricted, which will lead to permission errors when creating these tasks
and configuring real-time properites like scheduling priorities.
To solve this issues, try following steps:
1. Edit the /etc/security/limits.conf
file and add following lines at the end:
```sh
<username> hard rtprio 99
<username> soft rtprio 99
```
The soft limit can also be set in the console with `ulimit -Sr` if the hard
limit has been increased, but it is recommended to add it to the file as well for convenience.
If adding the second line is not desired for security reasons,
the soft limit needs to be set for each session. If using an IDE like eclipse
in that case, the IDE needs to be started from the console after setting
the soft limit higher there. After adding the two lines to the file,
the computer needs to be restarted.
It is also recommended to perform the following change so that the unlockRealtime
script does not need to be run anymore each time. The following steps
raise the maximum allowed message queue length to a higher number permanently, which is
required for some framework components. The recommended values for the new message
length is 130.
2. Edit the /etc/sysctl.conf file
```sh
sudo nano /etc/sysctl.conf
```
Append at end:
```sh
fs/mqueue/msg_max = <newMsgMaxLen>
```
Apply changes with:
```sh
sudo sysctl -p
```
A possible solution which only persists for the current session is
```sh
echo <newMsgMax> | sudo tee /proc/sys/fs/mqueue/msg_max
```
or running the `unlockRealtime` script.
3. Run the shell script inside the linux folder
```sh
./unlockRealtime
```
This script executes the `sudo setcap 'cap_sys_nice=eip' \<application\>`
command on the binaries, increases the soft real time limit of the current
session and increases the maximum number of message queues by setting
`/proc/sys/fs/mqueue/msg_max`.
All changes are only applied for the current session (read 2. and 3. for
a permanent solution). If running the script before executing the binary does
not help or an warning is issue that the soft real time value is invalid,
the hard real-time limit of the system might not be high enough (see step 1).
## General Information

View File

@ -1,168 +0,0 @@
#include <PollingSequenceFactory.h>
#include <dataPoolInit.h>
#include <Factory.h>
#include <systemObjectList.h>
#include <fsfw/datapool/DataPool.h>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/tasks/PeriodicTaskIF.h>
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
#include <ostream>
/* Declare global object manager */
ObjectManagerIF* objectManager;
/* Initialize Data Pool */
DataPool dataPool(datapool::dataPoolInit);
/* Set up output streams */
namespace sif {
ServiceInterfaceStream debug("DEBUG");
ServiceInterfaceStream info("INFO");
ServiceInterfaceStream warning("WARNING");
ServiceInterfaceStream error("ERROR", false, true, true);
}
void initTask();
void initMission() {
sif::info << "Initiating mission specific code." << std::endl;
// Allocate object manager here, as global constructors might not be
// executed, depending on buildchain
sif::info << "Creating objects" << std::endl;
objectManager = new ObjectManager(Factory::produce);
objectManager -> initialize();
initTask();
}
void initTask() {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
/* Packet Distributor Taks */
PeriodicTaskIF* PacketDistributorTask =
TaskFactory::instance()-> createPeriodicTask(
"PACKET_DIST_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE,
0.4, nullptr);
result = PacketDistributorTask->
addComponent(objects::CCSDS_PACKET_DISTRIBUTOR);
if(result != HasReturnvaluesIF::RETURN_OK){
sif::error << "Add component CCSDS Packet Distributor failed"
<< std::endl;
}
result = PacketDistributorTask->
addComponent(objects::PUS_PACKET_DISTRIBUTOR);
if(result != HasReturnvaluesIF::RETURN_OK){
sif::error << "Add component PUS Packet Distributor failed"
<< std::endl;
}
result = PacketDistributorTask->addComponent(objects::PUS_FUNNEL);
if(result != HasReturnvaluesIF::RETURN_OK){
sif::error << "Add component PUS Funnel failed" << std::endl;
}
/* UDP bridge */
PeriodicTaskIF* UdpBridgeTask = TaskFactory::instance()->createPeriodicTask(
"UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE,
0.2, nullptr);
result = UdpBridgeTask->addComponent(objects::UDP_BRIDGE);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Unix Bridge failed" << std::endl;
}
PeriodicTaskIF* UdpPollingTask = TaskFactory::instance()->
createPeriodicTask("UDP_POLLING", 80,
PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, nullptr);
result = UdpPollingTask->addComponent(objects::UDP_POLLING_TASK);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Polling failed" << std::endl;
}
/* PUS Services */
PeriodicTaskIF* PusService1 = TaskFactory::instance()->createPeriodicTask(
"PUS_SRV_1", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE,
0.4, nullptr);
result = PusService1->addComponent(objects::PUS_SERVICE_1);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component Verification Reporter failed" << std::endl;
}
PeriodicTaskIF* PusService2 = TaskFactory::instance()->createPeriodicTask(
"PUS_SRV_2", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE,
0.2, nullptr);
result = PusService2->addComponent(objects::PUS_SERVICE_2);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component Device Access failed" << std::endl;
}
PeriodicTaskIF* PusService5 = TaskFactory::instance()->createPeriodicTask(
"PUS_SRV_5", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE,
0.4, nullptr);
result = PusService5->addComponent(objects::PUS_SERVICE_5);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component Event Service failed" << std::endl;
}
PeriodicTaskIF* PusService8 = TaskFactory::instance()->createPeriodicTask(
"PUS_SRV_8", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE,
0.4, nullptr);
result = PusService2->addComponent(objects::PUS_SERVICE_8);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component Function MGMT failed" << std::endl;
}
PeriodicTaskIF* PusService17 = TaskFactory::instance()->createPeriodicTask(
"PUS_SRV_17", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE,
0.4, nullptr);
result = PusService17->addComponent(objects::PUS_SERVICE_17);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component Test Service failed" << std::endl;
}
PeriodicTaskIF* PusService200 = TaskFactory::instance()->createPeriodicTask(
"PUS_SRV_200", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE,
0.4, nullptr);
result = PusService200->addComponent(objects::PUS_SERVICE_200);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component Mode MGMT failed" << std::endl;
}
/* Test Task */
// PeriodicTaskIF* TestTask = TaskFactory::instance()->
// createPeriodicTask("TEST_TASK", 80,
// PeriodicTaskIF::MINIMUM_STACK_SIZE, 5.0, nullptr);
// result = TestTask->addComponent(objects::TEST_TASK);
// if (result != HasReturnvaluesIF::RETURN_OK) {
// sif::error << "Add component Test Task failed" << std::endl;
// }
/* Polling Sequence Table Default */
// FixedTimeslotTaskIF * PollingSequenceTableTaskDefault =
// TaskFactory::instance()-> createFixedTimeslotTask(
// "PST_DEFAULT", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0,
// nullptr);
// result = pst::pollingSequenceInitDefault(PollingSequenceTableTaskDefault);
// if (result != HasReturnvaluesIF::RETURN_OK) {
// sif::error << "creating PST failed" << std::endl;
// }
//TestTask->startTask();
PacketDistributorTask->startTask();
//PollingSequenceTableTaskDefault->startTask();
UdpBridgeTask->startTask();
UdpPollingTask->startTask();
PusService1->startTask();
PusService2->startTask();
PusService5->startTask();
PusService8->startTask();
PusService17->startTask();
PusService200->startTask();
}

View File

@ -2,20 +2,14 @@
#include <boardconfig/gcov.h>
#endif
#include <mission/core/InitMission.h>
#include <fsfw/tasks/TaskFactory.h>
#include <iostream>
#include <version.h>
#include <unistd.h>
// This will be the entry to the mission specific code
void initMission();
#ifndef SW_VERSION
#define SW_VERSION 0
#endif
#ifndef SW_SUBVERSION
#define SW_SUBVERSION 0
#endif
/**
* @brief This is the main program for the hosted build. It can be run for
@ -29,10 +23,12 @@ int main(void)
std::cout << "-- Software version v" << SW_VERSION << "." << SW_SUBVERSION
<< " -- " << std::endl;
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
initMission();
InitMission::initMission();
for(;;) {
// suspend main thread by sleeping it.
sleep(5);
TaskFactory::delayTask(5000);
}
}

14
config/OBSWConfig.h Normal file
View File

@ -0,0 +1,14 @@
/**
* @brief This file can be used to add preprocessor define for conditional
* code inclusion exclusion or various other project constants and
* properties in one place.
*/
#ifndef CONFIG_OBSWCONFIG_H_
#define CONFIG_OBSWCONFIG_H_
#define ADD_TEST_FOLDER 1
// Define not used yet, PUS stack and TMTC tasks are always started
#define ADD_PUS_STACK 1
#endif /* CONFIG_OBSWCONFIG_H_ */

View File

@ -1,48 +0,0 @@
#include "dataPoolInit.h"
void datapool::dataPoolInit(std::map<uint32_t, PoolEntryIF*>* poolMap) {
uint8_t UINT8T_INIT[1] = {0};
uint16_t UINT16T_INIT[1] = {0};
uint32_t UINT32T_INIT[1] = {0};
float FLOAT_INIT[2] = {0.0, 0.0};
/* FSFW */
poolMap->emplace(datapool::INTERNAL_ERROR_STORE_FULL,
new PoolEntry<uint32_t>(UINT32T_INIT,1));
poolMap->emplace(datapool::INTERNAL_ERROR_MISSED_LIVE_TM,
new PoolEntry<uint32_t>(UINT32T_INIT,1));
poolMap->emplace(datapool::INTERNAL_ERROR_FULL_MSG_QUEUES,
new PoolEntry<uint32_t>(UINT32T_INIT,1));
/* TEST */
poolMap->emplace(datapool::TEST_UINT8,
new PoolEntry<uint8_t>(UINT8T_INIT,1));
poolMap->emplace(datapool::TEST_UINT16,
new PoolEntry<uint16_t>(UINT16T_INIT,1));
poolMap->emplace(datapool::TEST_UINT32,
new PoolEntry<uint32_t>(UINT32T_INIT,1));
poolMap->emplace(datapool::TEST_FLOAT_VECTOR,
new PoolEntry<float>(FLOAT_INIT,2));
// With new initializer list feature and boolean entries.
// /* FSFW */
// poolMap->emplace(datapool::INTERNAL_ERROR_STORE_FULL,
// new PoolEntry<uint32_t>({0},1));
// poolMap->emplace(datapool::INTERNAL_ERROR_MISSED_LIVE_TM,
// new PoolEntry<uint32_t>({0},1));
// poolMap->emplace(datapool::INTERNAL_ERROR_FULL_MSG_QUEUES,
// new PoolEntry<uint32_t>({0},1));
//
// /* TEST */
// poolMap->emplace(datapool::TEST_BOOLEAN,
// new PoolEntry<bool>({0},1));
// poolMap->emplace(datapool::TEST_UINT8,
// new PoolEntry<uint8_t>({0},1));
// poolMap->emplace(datapool::TEST_UINT16,
// new PoolEntry<uint16_t>({0},1));
// poolMap->emplace(datapool::TEST_UINT32,
// new PoolEntry<uint32_t>({0},1));
// poolMap->emplace(datapool::TEST_FLOAT_VECTOR,
// new PoolEntry<float>({0, 0},2));
}

View File

@ -1,29 +0,0 @@
#ifndef HOSTED_CONFIG_CDATAPOOL_DATAPOOLINIT_H_
#define HOSTED_CONFIG_CDATAPOOL_DATAPOOLINIT_H_
#include <fsfw/datapool/DataPool.h>
#include <fsfw/datapool/PoolEntryIF.h>
#include <map>
#include <cstdint>
namespace datapool {
void dataPoolInit(std::map<uint32_t, PoolEntryIF*>* poolMap);
enum datapoolvariables {
NO_PARAMETER = 0,
/** [EXPORT] : [GROUP] FSFW */
INTERNAL_ERROR_STORE_FULL = 0xEE000001, //!< [EXPORT] : [NAME] Internal Error Store Entry [UNIT] (-) [SIZE] 1 [TYPE] uint32_t
INTERNAL_ERROR_MISSED_LIVE_TM = 0xEE000001, //!< [EXPORT] : [NAME] Internal Error Missed Live Tm [UNIT] (-) [SIZE] 1 [TYPE] uint32_t
INTERNAL_ERROR_FULL_MSG_QUEUES = 0xEE000001, //!< [EXPORT] : [NAME] Internal Error Full Msg Queue [UNIT] (-) [SIZE] 1 [TYPE] uint32_t
/** [EXPORT] : [GROUP] TEST */
TEST_BOOLEAN = 0x01010102, //!< [EXPORT] : [NAME] Test Boolean [UNIT] (-) [SIZE] 1 [TYPE] bool
TEST_UINT8 = 0x02020204, //!< [EXPORT] : [NAME] Test Byte [UNIT] (-) [SIZE] 1 [TYPE] uint8_t
TEST_UINT16 = 0x03030306, //!< [EXPORT] : [NAME] Test UINT16 [UNIT] (-) [SIZE] 1 [TYPE] uint16_t
TEST_UINT32 = 0x04040408, //!< [EXPORT] : [NAME] Test UINT32 [UNIT] (-) [SIZE] 1 [TYPE] uint32_t
TEST_FLOAT_VECTOR = 0x05050510, //!< [EXPORT] : [NAME] Test Float [UNIT] (-) [SIZE] 2 [TYPE] float
};
}
#endif /* CONFIG_CDATAPOOL_DATAPOOLINIT_H_ */

View File

@ -1,116 +0,0 @@
#include <Factory.h>
#include <systemObjectList.h>
#include <dataPoolInit.h>
#include <apid.h>
#include <pusIds.h>
#include <mission/utility/TimeStamper.h>
#include <mission/utility/TmFunnel.h>
#include <fsfw/events/EventManager.h>
#include <fsfw/health/HealthTable.h>
#include <fsfw/internalError/InternalErrorReporter.h>
#include <fsfw/objectmanager/frameworkObjects.h>
#include <fsfw/storagemanager/PoolManager.h>
#include <fsfw/tcdistribution/CCSDSDistributor.h>
#include <fsfw/tcdistribution/PUSDistributor.h>
#include <fsfw/tmtcpacket/pus/TmPacketStored.h>
#include <fsfw/tmtcservices/PusServiceBase.h>
#include <fsfw/pus/Service1TelecommandVerification.h>
#include <fsfw/pus/Service2DeviceAccess.h>
#include <fsfw/pus/Service5EventReporting.h>
#include <fsfw/pus/Service8FunctionManagement.h>
#include <fsfw/pus/CService200ModeCommanding.h>
#include <fsfw/osal/linux/TmTcUnixUdpBridge.h>
#include <fsfw/osal/linux/TcUnixUdpPollingTask.h>
#include <fsfw/pus/Service17Test.h>
#include <test/testtasks/TestTask.h>
#include <cstdint>
/**
* @brief Produces system objects.
* @details
* Build tasks by using SystemObject Interface (Interface).
* Header files of all tasks must be included
* Please note that an object has to implement the system object interface
* if the interface validity is checked or retrieved later by using the
* get<TargetInterface>(object_id) function from the ObjectManagerIF.
*
* Framework objects are created first.
*
* @ingroup init
*/
void Factory::produce(void) {
setStaticFrameworkObjectIds();
new EventManager(objects::EVENT_MANAGER);
new HealthTable(objects::HEALTH_TABLE);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER,
datapool::INTERNAL_ERROR_FULL_MSG_QUEUES,
datapool::INTERNAL_ERROR_MISSED_LIVE_TM,
datapool::INTERNAL_ERROR_STORE_FULL);
/* Pool manager handles storage und mutexes */
/* Data Stores. Currently reserving 9600 bytes of memory */
uint16_t numberOfElements[4] = {100, 30, 20, 10};
uint16_t sizeOfElements[4] = {32, 64, 128, 256};
new PoolManager<4>(objects::IPC_STORE, sizeOfElements, numberOfElements);
new PoolManager<4>(objects::TM_STORE, sizeOfElements, numberOfElements);
new PoolManager<4>(objects::TC_STORE, sizeOfElements, numberOfElements);
new TimeStamper(objects::PUS_TIME);
/* Distributor Tasks */
new CCSDSDistributor(apid::EIVE_OBSW, objects::CCSDS_PACKET_DISTRIBUTOR);
new PUSDistributor(apid::EIVE_OBSW, objects::PUS_PACKET_DISTRIBUTOR,
objects::CCSDS_PACKET_DISTRIBUTOR);
/* TM Destination */
new TmFunnel(objects::PUS_FUNNEL);
new TmTcUnixUdpBridge(objects::UDP_BRIDGE,
objects::CCSDS_PACKET_DISTRIBUTOR, objects::TM_STORE,
objects::TC_STORE);
new TcUnixUdpPollingTask(objects::UDP_POLLING_TASK,
objects::UDP_BRIDGE);
/* PUS Service Base Services */
new Service1TelecommandVerification(objects::PUS_SERVICE_1,
apid::EIVE_OBSW, pus::PUS_SERVICE_1, objects::PUS_FUNNEL);
new Service5EventReporting(objects::PUS_SERVICE_5, apid::EIVE_OBSW,
pus::PUS_SERVICE_5);
new Service17Test(objects::PUS_SERVICE_17, apid::EIVE_OBSW,
pus::PUS_SERVICE_17);
/* Commanding Service Base Services */
new Service2DeviceAccess(objects::PUS_SERVICE_2, apid::EIVE_OBSW,
pus::PUS_SERVICE_2);
new Service8FunctionManagement(objects::PUS_SERVICE_8, apid::EIVE_OBSW,
pus::PUS_SERVICE_8);
new CService200ModeCommanding(objects::PUS_SERVICE_200, apid::EIVE_OBSW,
pus::PUS_SERVICE_200);
/* Test Tasks */
// CookieIF* dummyCookie = new DummyCookie(0);
// new DummyEchoComIF(objects::DUMMY_INTERFACE);
// new TestDevice(objects::DUMMY_HANDLER, objects::DUMMY_INTERFACE,
// dummyCookie, true);
new TestTask(objects::TEST_TASK);
}
void Factory::setStaticFrameworkObjectIds() {
PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR;
PusServiceBase::packetDestination = objects::PUS_FUNNEL;
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::PUS_FUNNEL;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1;
//DeviceHandlerBase::rawDataReceiverId = objects::PUS_SERVICE_2;
//DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
TmPacketStored::timeStamperId = objects::PUS_TIME;
TmFunnel::downlinkDestination = objects::UDP_BRIDGE;
}

View File

@ -1,16 +0,0 @@
#ifndef FACTORY_H_
#define FACTORY_H_
#include <fsfw/objectmanager/SystemObjectIF.h>
namespace Factory {
/**
* @brief Creates all SystemObject elements which are persistent
* during execution.
*/
void produce();
void setStaticFrameworkObjectIds();
}
#endif /* FACTORY_H_ */

View File

@ -12,20 +12,15 @@ namespace objects {
UDP_BRIDGE = 0x50000300,
UDP_POLLING_TASK = 0x50000400,
PUS_SERVICE_1 = 0x51000100,
PUS_SERVICE_2 = 0x51000200,
PUS_SERVICE_3 = 0x51000300,
PUS_SERVICE_5 = 0x51000400,
PUS_SERVICE_6 = 0x51000500,
PUS_SERVICE_8 = 0x51000800,
PUS_SERVICE_9 = 0x51000900,
PUS_SERVICE_17 = 0x51001700,
PUS_SERVICE_23 = 0x51002300,
PUS_SERVICE_200 = 0x51020000,
PUS_SERVICE_201 = 0x51020100,
PUS_TIME = 0x52000001,
PUS_FUNNEL = 0x52000002,
TIME_STAMPER = 0x52000001,
TM_FUNNEL = 0x52000002,
/* Test Task */
TEST_TASK = 0x42694269,

View File

@ -19,8 +19,6 @@ enum: uint8_t {
PUS_SERVICE_5 = 85,
PUS_SERVICE_6 = 86,
PUS_SERVICE_8 = 88,
PUS_SERVICE_9 = 89,
PUS_SERVICE_17 = 82,
PUS_SERVICE_23 = 91,
DUMMY_DEVICE = 90,
/**

2
fsfw

@ -1 +1 @@
Subproject commit 62508132c0c248d6851fd88207828c7f12c38e50
Subproject commit 5340b9c58e78f2154fa8291c69bf887c252fe25f

View File

@ -0,0 +1,155 @@
#include "InitMission.h"
#include <OBSWConfig.h>
#include <config/objects/systemObjectList.h>
#include <mission/core/ObjectFactory.h>
#include <fsfw/objectmanager/ObjectManagerIF.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
#include <fsfw/datapool/DataPool.h>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
#include <fsfw/tasks/PeriodicTaskIF.h>
#include <fsfw/tasks/TaskFactory.h>
#include <iostream>
// This is configured for linux without \cr
ServiceInterfaceStream sif::debug("DEBUG", false);
ServiceInterfaceStream sif::info("INFO", false);
ServiceInterfaceStream sif::warning("WARNING", false);
ServiceInterfaceStream sif::error("ERROR", false, false, true);
ObjectManagerIF *objectManager = nullptr;
//Initialize Data Pool
DataPool dataPool(nullptr);
void InitMission::initMission() {
sif::info << "Building global objects.." << std::endl;
/* Instantiate global object manager and also create all objects */
objectManager = new ObjectManager(ObjectFactory::produce);
sif::info << "Initializing all objects.." << std::endl;
objectManager->initialize();
/* This function creates and starts all tasks */
initTasks();
}
void InitMission::initTasks(){
/* TMTC Distribution */
PeriodicTaskIF* TmTcDistributor = TaskFactory::instance()->
createPeriodicTask("DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE,
0.100, nullptr);
ReturnValue_t result = TmTcDistributor->addComponent(
objects::CCSDS_PACKET_DISTRIBUTOR);
if(result!=HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
result = TmTcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR);
if(result!=HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
result = TmTcDistributor->addComponent(objects::TM_FUNNEL);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
/* UDP bridge */
PeriodicTaskIF* UdpBridgeTask = TaskFactory::instance()->createPeriodicTask(
"UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE,
0.2, nullptr);
result = UdpBridgeTask->addComponent(objects::UDP_BRIDGE);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Unix Bridge failed" << std::endl;
}
PeriodicTaskIF* UdpPollingTask = TaskFactory::instance()->
createPeriodicTask("UDP_POLLING", 80,
PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, nullptr);
result = UdpPollingTask->addComponent(objects::UDP_POLLING_TASK);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Polling failed" << std::endl;
}
/* PUS Services */
PeriodicTaskIF* PusVerification = TaskFactory::instance()->
createPeriodicTask("PUS_VERIF_1", 40,
PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, nullptr);
result = PusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
if(result != HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
PeriodicTaskIF* PusEvents = TaskFactory::instance()->
createPeriodicTask("PUS_VERIF_1", 60,
PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, nullptr);
result = PusVerification->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING);
if(result != HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
PeriodicTaskIF* PusHighPrio = TaskFactory::instance()->
createPeriodicTask("PUS_HIGH_PRIO", 50,
PeriodicTaskIF::MINIMUM_STACK_SIZE,
0.200, nullptr);
result = PusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
if(result!=HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
result = PusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
if(result!=HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
PeriodicTaskIF* PusMedPrio = TaskFactory::instance()->
createPeriodicTask("PUS_HIGH_PRIO", 40,
PeriodicTaskIF::MINIMUM_STACK_SIZE,
0.8, nullptr);
result = PusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
if(result!=HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
result = PusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
if(result!=HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
PeriodicTaskIF* PusLowPrio = TaskFactory::instance()->
createPeriodicTask("PUSB", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE,
1.6, nullptr);
result = PusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
if(result!=HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
#if ADD_TEST_CODE == 1
FixedTimeslotTaskIF* TestTimeslotTask = TaskFactory::instance()->
createFixedTimeslotTask("PST_TEST_TASK", 10,
PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr);
result = pst::pollingSequenceTestFunction(TestTimeslotTask);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::createTasks: Test PST initialization "
<< "failed!" << std::endl;
}
#endif
//Main thread sleep
sif::info << "Starting tasks.." << std::endl;
TmTcDistributor->startTask();
UdpBridgeTask->startTask();
UdpPollingTask->startTask();
PusVerification->startTask();
PusEvents->startTask();
PusHighPrio->startTask();
PusMedPrio->startTask();
PusLowPrio->startTask();
#if ADD_TEST_CODE == 1
TestTimeslotTask->startTask();
#endif
sif::info << "Tasks started.." << std::endl;
}

View File

@ -0,0 +1,9 @@
#ifndef MISSION_CORE_INITMISSION_H_
#define MISSION_CORE_INITMISSION_H_
namespace InitMission {
void initMission();
void initTasks();
};
#endif /* MISSION_CORE_INITMISSION_H_ */

View File

@ -0,0 +1,124 @@
#include "ObjectFactory.h"
#include <config/OBSWConfig.h>
#include <config/objects/systemObjectList.h>
#include <config/tmtc/apid.h>
#include <config/tmtc/pusIds.h>
#include <mission/utility/TmFunnel.h>
#include <fsfw/health/HealthTable.h>
#include <fsfw/storagemanager/PoolManager.h>
#include <fsfw/events/EventManager.h>
#include <fsfw/timemanager/TimeStamper.h>
#include <fsfw/internalError/InternalErrorReporter.h>
#include <fsfw/monitoring/MonitoringMessageContent.h>
#include <fsfw/tcdistribution/CCSDSDistributor.h>
#include <fsfw/tcdistribution/PUSDistributor.h>
#include <fsfw/pus/Service1TelecommandVerification.h>
#include <fsfw/pus/Service2DeviceAccess.h>
#include <fsfw/pus/Service5EventReporting.h>
#include <fsfw/pus/Service8FunctionManagement.h>
#include <fsfw/pus/Service9TimeManagement.h>
#include <fsfw/pus/Service17Test.h>
#include <fsfw/pus/CService200ModeCommanding.h>
#include <fsfw/osal/linux/TcUnixUdpPollingTask.h>
#include <fsfw/osal/linux/TmTcUnixUdpBridge.h>
#include <fsfw/tmtcpacket/pus/TmPacketStored.h>
#if ADD_TEST_CODE == 1
#include <test/TestCookie.h>
#include <test/TestDeviceHandler.h>
#include <mission/test/TestTask.h>
#include <test/TestEchoComIF.h>
#endif
void Factory::setStaticFrameworkObjectIds(){
PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR;
PusServiceBase::packetDestination = objects::TM_FUNNEL;
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
TmFunnel::downlinkDestination = objects::UDP_BRIDGE;
// No storage object for now.
TmFunnel::storageDestination = objects::NO_OBJECT;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
TmPacketStored::timeStamperId = objects::TIME_STAMPER;
}
void ObjectFactory::produce(){
Factory::setStaticFrameworkObjectIds();
/* Framework objects */
new EventManager(objects::EVENT_MANAGER);
new HealthTable(objects::HEALTH_TABLE);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER, 0, 0, 0);
new TimeStamper(objects::TIME_STAMPER);
{
static constexpr uint8_t NUMBER_OF_POOLS = 5;
const uint16_t element_sizes[NUMBER_OF_POOLS] = {16, 32, 64, 128, 1024};
const uint16_t n_elements[NUMBER_OF_POOLS] = {100, 50, 25, 15, 5};
new PoolManager<NUMBER_OF_POOLS>(objects::TC_STORE, element_sizes,
n_elements);
}
{
static constexpr uint8_t NUMBER_OF_POOLS = 5;
const uint16_t element_sizes[NUMBER_OF_POOLS] = {16, 32, 64, 128, 1024};
const uint16_t n_elements[NUMBER_OF_POOLS] = {100, 50, 25, 15, 5};
new PoolManager<NUMBER_OF_POOLS>(objects::TM_STORE, element_sizes,
n_elements);
}
{
static constexpr uint8_t NUMBER_OF_POOLS = 6;
const uint16_t element_sizes[NUMBER_OF_POOLS] = {32, 64, 512,
1024, 2048, 4096};
const uint16_t n_elements[NUMBER_OF_POOLS] = {200, 100, 50, 25, 15, 5};
new PoolManager<NUMBER_OF_POOLS>(objects::IPC_STORE, element_sizes,
n_elements);
}
new CCSDSDistributor(apid::EIVE_OBSW, objects::CCSDS_PACKET_DISTRIBUTOR);
new PUSDistributor(apid::EIVE_OBSW, objects::PUS_PACKET_DISTRIBUTOR,
objects::CCSDS_PACKET_DISTRIBUTOR);
/* TMTC Reception via UDP socket */
new TmFunnel(objects::TM_FUNNEL);
new TmTcUnixUdpBridge(objects::UDP_BRIDGE,
objects::CCSDS_PACKET_DISTRIBUTOR,
objects::TM_STORE, objects::TC_STORE);
new TcUnixUdpPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
/* PUS stack */
new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION,
apid::EIVE_OBSW, pus::PUS_SERVICE_1, objects::TM_FUNNEL);
new Service2DeviceAccess(objects::PUS_SERVICE_2_DEVICE_ACCESS,
apid::EIVE_OBSW, pus::PUS_SERVICE_2, 3, 10);
new Service5EventReporting(objects::PUS_SERVICE_5_EVENT_REPORTING,
apid::EIVE_OBSW, pus::PUS_SERVICE_5, 50);
new Service8FunctionManagement(objects::PUS_SERVICE_8_FUNCTION_MGMT,
apid::EIVE_OBSW, pus::PUS_SERVICE_8, 3, 10);
new Service9TimeManagement(objects::PUS_SERVICE_9_TIME_MGMT,
apid::EIVE_OBSW, pus::PUS_SERVICE_9);
new Service17Test(objects::PUS_SERVICE_17_TEST, apid::EIVE_OBSW,
pus::PUS_SERVICE_17);
new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT,
apid::EIVE_OBSW, pus::PUS_SERVICE_200);
/* Test Device Handler */
#if ADD_TEST_CODE == 1
CookieIF* testCookie = new TestCookie(0);
new TestEchoComIF(objects::TEST_ECHO_COM_IF);
new TestDevice(objects::TEST_DEVICE_HANDLER, objects::TEST_ECHO_COM_IF,
testCookie, true);
#endif
}

View File

@ -0,0 +1,17 @@
/*
* ObjectFactory.h
*
* Created on: Sep 22, 2020
* Author: steffen
*/
#ifndef MISSION_CORE_OBJECTFACTORY_H_
#define MISSION_CORE_OBJECTFACTORY_H_
namespace ObjectFactory {
void setStatics();
void produce();
};
#endif /* MISSION_CORE_OBJECTFACTORY_H_ */

View File

@ -1,2 +1,17 @@
# add main and others
CXXSRC += $(wildcard $(CURRENTPATH)/*.cpp)
CSRC += $(wildcard $(CURRENTPATH)/*.c)
CSRC += $(wildcard $(CURRENTPATH)/core/*.c)
CXXSRC += $(wildcard $(CURRENTPATH)/core/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/devices/*.cpp)
CSRC += $(wildcard $(CURRENTPATH)/devices/*.c)
CXXSRC += $(wildcard $(CURRENTPATH)/utility/*.cpp)
CSRC += $(wildcard $(CURRENTPATH)/utility/*.c)
CSRC += $(wildcard $(CURRENTPATH)/utility/*.c)
CXXSRC += $(wildcard $(CURRENTPATH)/test/*.cpp)
CSRC += $(wildcard $(CURRENTPATH)/test/*.c)

View File

@ -1,23 +0,0 @@
#include <fsfw/timemanager/Clock.h>
#include <mission/utility/TimeStamper.h>
#include <cstring>
TimeStamper::TimeStamper(object_id_t objectId): SystemObject(objectId) {}
ReturnValue_t TimeStamper::addTimeStamp(uint8_t* buffer,
const uint8_t maxSize) {
if(maxSize < TimeStamperIF::MISSION_TIMESTAMP_SIZE) {
return HasReturnvaluesIF::RETURN_FAILED;
}
timeval now;
Clock::getClock_timeval(&now);
CCSDSTime::CDS_short cds;
ReturnValue_t result = CCSDSTime::convertToCcsds(&cds,&now);
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
std::memcpy(buffer,&cds,sizeof(cds));
return result;
}

View File

@ -1,18 +0,0 @@
#ifndef MISSION_UTILITY_TIMESTAMPER_H_
#define MISSION_UTILITY_TIMESTAMPER_H_
#include <fsfw/timemanager/TimeStamperIF.h>
#include <fsfw/timemanager/CCSDSTime.h>
#include <fsfw/objectmanager/SystemObject.h>
/**
* @brief
* @ingroup utility
*/
class TimeStamper: public TimeStamperIF, public SystemObject {
public:
TimeStamper(object_id_t objectId);
virtual ReturnValue_t addTimeStamp(uint8_t* buffer, const uint8_t maxSize);
};
#endif /* MISSION_UTILITY_TIMESTAMPER_H_ */

View File

@ -1,15 +1,14 @@
#include <mission/utility/TmFunnel.h>
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/tmtcpacket/pus/TmPacketBase.h>
#include <fsfw/tmtcpacket/pus/TmPacketStored.h>
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
#include <mission/utility/TmFunnel.h>
object_id_t TmFunnel::downlinkDestination = objects::NO_OBJECT;
object_id_t TmFunnel::storageDestination = objects::NO_OBJECT;
TmFunnel::TmFunnel(object_id_t objectId_): SystemObject(objectId_),
sourceSequenceCount(0), storageTargetSet(false) {
TmFunnel::TmFunnel(object_id_t objectId, uint32_t messageDepth):
SystemObject(objectId), messageDepth(messageDepth) {
tmQueue = QueueFactory::instance()->createMessageQueue(messageDepth,
MessageQueueMessage::MAX_MESSAGE_SIZE);
storageQueue = QueueFactory::instance()->createMessageQueue(messageDepth,
@ -66,7 +65,7 @@ ReturnValue_t TmFunnel::handlePacket(TmTcMessage* message) {
return result;
}
if(storageTargetSet) {
if(storageDestination != objects::NO_OBJECT) {
result = storageQueue->sendToDefault(message);
if(result != HasReturnvaluesIF::RETURN_OK){
tmPool->deleteData(message->getStorageId());
@ -100,10 +99,14 @@ ReturnValue_t TmFunnel::initialize() {
}
tmQueue->setDefaultDestination(tmTarget->getReportReceptionQueue());
// Storage destination is optional.
if(storageDestination == objects::NO_OBJECT) {
return SystemObject::initialize();
}
AcceptsTelemetryIF* storageTarget =
objectManager->get<AcceptsTelemetryIF>(storageDestination);
if(storageTarget != nullptr) {
storageTargetSet = true;
storageQueue->setDefaultDestination(
storageTarget->getReportReceptionQueue());
}

View File

@ -24,7 +24,7 @@ class TmFunnel: public AcceptsTelemetryIF,
public SystemObject {
friend void (Factory::setStaticFrameworkObjectIds)();
public:
TmFunnel(object_id_t objectId);
TmFunnel(object_id_t objectId, uint32_t messageDepth = 20);
virtual ~TmFunnel();
virtual MessageQueueId_t getReportReceptionQueue(
@ -37,14 +37,12 @@ protected:
static object_id_t storageDestination;
private:
uint16_t sourceSequenceCount;
bool storageTargetSet;
uint16_t sourceSequenceCount = 0;
MessageQueueIF* tmQueue = nullptr;
MessageQueueIF* storageQueue = nullptr;
StorageManagerIF* tmPool = nullptr;
uint32_t messageDepth = 10;
uint32_t messageDepth = 0;
ReturnValue_t handlePacket(TmTcMessage* message);
};

View File

@ -5,9 +5,11 @@
#include <test/testtasks/PusTcInjector.h>
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
#include <fsfw/objectmanager/ObjectManagerIF.h>
#include <fsfw/timemanager/Stopwatch.h>
#include <fsfw/globalfunctions/arrayprinter.h>
#include <etl/vector.h>
#include <array>
#include <cstring>