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