diff --git a/README.md b/README.md index 1a9112cc..8a361e7b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,98 @@ -EIVE On-Board Software -====== +# 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 + hard rtprio 99 + 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 = +``` +Apply changes with: +```sh +sudo sysctl -p +``` + +A possible solution which only persists for the current session is +```sh +echo | 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' \` +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 diff --git a/bsp_linux/InitMission.cpp b/bsp_linux/InitMission.cpp deleted file mode 100644 index bc3d1f83..00000000 --- a/bsp_linux/InitMission.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -/* 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(); -} diff --git a/bsp_linux/main.cpp b/bsp_linux/main.cpp index 4c34e501..98198838 100644 --- a/bsp_linux/main.cpp +++ b/bsp_linux/main.cpp @@ -2,20 +2,14 @@ #include #endif +#include +#include + #include #include #include -// 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); } } diff --git a/config/OBSWConfig.h b/config/OBSWConfig.h new file mode 100644 index 00000000..9e11424b --- /dev/null +++ b/config/OBSWConfig.h @@ -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_ */ diff --git a/config/cdatapool/dataPoolInit.cpp b/config/cdatapool/dataPoolInit.cpp deleted file mode 100644 index b37ed0ac..00000000 --- a/config/cdatapool/dataPoolInit.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "dataPoolInit.h" - -void datapool::dataPoolInit(std::map* 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(UINT32T_INIT,1)); - poolMap->emplace(datapool::INTERNAL_ERROR_MISSED_LIVE_TM, - new PoolEntry(UINT32T_INIT,1)); - poolMap->emplace(datapool::INTERNAL_ERROR_FULL_MSG_QUEUES, - new PoolEntry(UINT32T_INIT,1)); - - /* TEST */ - poolMap->emplace(datapool::TEST_UINT8, - new PoolEntry(UINT8T_INIT,1)); - poolMap->emplace(datapool::TEST_UINT16, - new PoolEntry(UINT16T_INIT,1)); - poolMap->emplace(datapool::TEST_UINT32, - new PoolEntry(UINT32T_INIT,1)); - poolMap->emplace(datapool::TEST_FLOAT_VECTOR, - new PoolEntry(FLOAT_INIT,2)); - - // With new initializer list feature and boolean entries. - -// /* FSFW */ -// poolMap->emplace(datapool::INTERNAL_ERROR_STORE_FULL, -// new PoolEntry({0},1)); -// poolMap->emplace(datapool::INTERNAL_ERROR_MISSED_LIVE_TM, -// new PoolEntry({0},1)); -// poolMap->emplace(datapool::INTERNAL_ERROR_FULL_MSG_QUEUES, -// new PoolEntry({0},1)); -// -// /* TEST */ -// poolMap->emplace(datapool::TEST_BOOLEAN, -// new PoolEntry({0},1)); -// poolMap->emplace(datapool::TEST_UINT8, -// new PoolEntry({0},1)); -// poolMap->emplace(datapool::TEST_UINT16, -// new PoolEntry({0},1)); -// poolMap->emplace(datapool::TEST_UINT32, -// new PoolEntry({0},1)); -// poolMap->emplace(datapool::TEST_FLOAT_VECTOR, -// new PoolEntry({0, 0},2)); - -} diff --git a/config/cdatapool/dataPoolInit.h b/config/cdatapool/dataPoolInit.h deleted file mode 100644 index 9da940b5..00000000 --- a/config/cdatapool/dataPoolInit.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef HOSTED_CONFIG_CDATAPOOL_DATAPOOLINIT_H_ -#define HOSTED_CONFIG_CDATAPOOL_DATAPOOLINIT_H_ - -#include -#include -#include -#include - - -namespace datapool { - void dataPoolInit(std::map* 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_ */ diff --git a/config/objects/Factory.cpp b/config/objects/Factory.cpp deleted file mode 100644 index be709414..00000000 --- a/config/objects/Factory.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/** - * @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(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; -} - - diff --git a/config/objects/Factory.h b/config/objects/Factory.h deleted file mode 100644 index 84f9207e..00000000 --- a/config/objects/Factory.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef FACTORY_H_ -#define FACTORY_H_ - -#include - -namespace Factory { - /** - * @brief Creates all SystemObject elements which are persistent - * during execution. - */ - void produce(); - void setStaticFrameworkObjectIds(); - -} - -#endif /* FACTORY_H_ */ diff --git a/config/objects/systemObjectList.h b/config/objects/systemObjectList.h index e2a76311..5e6062d4 100644 --- a/config/objects/systemObjectList.h +++ b/config/objects/systemObjectList.h @@ -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, diff --git a/config/tmtc/subsystemIdRanges.h b/config/tmtc/subsystemIdRanges.h index 10d34250..6b73d412 100644 --- a/config/tmtc/subsystemIdRanges.h +++ b/config/tmtc/subsystemIdRanges.h @@ -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, /** diff --git a/fsfw b/fsfw index 62508132..5340b9c5 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 62508132c0c248d6851fd88207828c7f12c38e50 +Subproject commit 5340b9c58e78f2154fa8291c69bf887c252fe25f diff --git a/mission/core/InitMission.cpp b/mission/core/InitMission.cpp new file mode 100644 index 00000000..3eae5123 --- /dev/null +++ b/mission/core/InitMission.cpp @@ -0,0 +1,155 @@ +#include "InitMission.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// 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; +} + + diff --git a/mission/core/InitMission.h b/mission/core/InitMission.h new file mode 100644 index 00000000..8e4471ce --- /dev/null +++ b/mission/core/InitMission.h @@ -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_ */ diff --git a/mission/core/ObjectFactory.cpp b/mission/core/ObjectFactory.cpp new file mode 100644 index 00000000..66ff33a9 --- /dev/null +++ b/mission/core/ObjectFactory.cpp @@ -0,0 +1,124 @@ +#include "ObjectFactory.h" + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if ADD_TEST_CODE == 1 +#include +#include +#include +#include +#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(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(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(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 +} diff --git a/mission/core/ObjectFactory.h b/mission/core/ObjectFactory.h new file mode 100644 index 00000000..9bf0d688 --- /dev/null +++ b/mission/core/ObjectFactory.h @@ -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_ */ diff --git a/mission/mission.mk b/mission/mission.mk index c3399b0f..028b9c13 100644 --- a/mission/mission.mk +++ b/mission/mission.mk @@ -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) \ No newline at end of file +CSRC += $(wildcard $(CURRENTPATH)/utility/*.c) + +CXXSRC += $(wildcard $(CURRENTPATH)/test/*.cpp) +CSRC += $(wildcard $(CURRENTPATH)/test/*.c) + + diff --git a/mission/utility/TimeStamper.cpp b/mission/utility/TimeStamper.cpp deleted file mode 100644 index c0cccbd6..00000000 --- a/mission/utility/TimeStamper.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include - -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; -} diff --git a/mission/utility/TimeStamper.h b/mission/utility/TimeStamper.h deleted file mode 100644 index d2122546..00000000 --- a/mission/utility/TimeStamper.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef MISSION_UTILITY_TIMESTAMPER_H_ -#define MISSION_UTILITY_TIMESTAMPER_H_ - -#include -#include -#include - -/** - * @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_ */ diff --git a/mission/utility/TmFunnel.cpp b/mission/utility/TmFunnel.cpp index 16753b36..263aff8d 100644 --- a/mission/utility/TmFunnel.cpp +++ b/mission/utility/TmFunnel.cpp @@ -1,15 +1,14 @@ -#include - #include #include #include #include +#include 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(storageDestination); if(storageTarget != nullptr) { - storageTargetSet = true; storageQueue->setDefaultDestination( storageTarget->getReportReceptionQueue()); } diff --git a/mission/utility/TmFunnel.h b/mission/utility/TmFunnel.h index 0490b194..2d4575a0 100644 --- a/mission/utility/TmFunnel.h +++ b/mission/utility/TmFunnel.h @@ -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); }; diff --git a/test/testtasks/TestTask.cpp b/test/testtasks/TestTask.cpp index a9d6626b..a618454c 100644 --- a/test/testtasks/TestTask.cpp +++ b/test/testtasks/TestTask.cpp @@ -5,9 +5,11 @@ #include #include +#include #include #include #include + #include #include