diff --git a/CMakeLists.txt b/CMakeLists.txt
index 10c3a349..cbf38410 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,6 +51,7 @@ set(LIB_CSP_NAME libcsp)
set(LIB_FSFW_HAL_NAME fsfw_hal)
set(LIB_LWGPS_NAME lwgps)
set(THIRD_PARTY_FOLDER thirdparty)
+set(LIB_CXX_FS -lstdc++fs)
# Set path names
set(FSFW_PATH fsfw)
@@ -164,6 +165,7 @@ if(NOT Q7S_SIMPLE_MODE)
${LIB_OS_NAME}
${LIB_LWGPS_NAME}
${LIB_FSFW_HAL_NAME}
+ ${LIB_CXX_FS}
)
endif()
diff --git a/README.md b/README.md
index 69aa4dc1..ee2f62f2 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,26 @@
-# EIVE On-Board Software
+ EIVE On-Board Software
+======
-## General information
+# General information
Target systems:
* OBC with Linux OS
- * Xiphos Q7S
- * Based on Zynq-7020 SoC (xc7z020clg484-2)
- * Dual-core ARM Cortex-A9
- * 766 MHz
- * Artix-7 FPGA (85K pogrammable logic cells)
- * Datasheet at https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Arbeitsdaten/08_Used%20Components/Q7S&fileid=340648
- * Also a lot of informatin about the Q7S can be found on the xiphos trac platform: https://trac.xiphos.com/trac/eive-q7/wiki/Q7RevB
- * Linux OS built with Yocto 2.5
- * Linux Kernel https://github.com/XiphosSystemsCorp/linux-xlnx.git
+ * Xiphos Q7S
+ * Based on Zynq-7020 SoC (xc7z020clg484-2)
+ * Dual-core ARM Cortex-A9
+ * 766 MHz
+ * Artix-7 FPGA (85K pogrammable logic cells)
+ * Datasheet at https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Arbeitsdaten/08_Used%20Components/Q7S&fileid=340648
+ * Also a lot of information about the Q7S can be found on
+ the [Xiphos Traq Platform](https://trac2.xiphos.ca/eive-q7). Press on index to find all
+ relevant pages.
+ * Linux OS built with Yocto 2.5
+ * Linux Kernel https://github.com/XiphosSystemsCorp/linux-xlnx.git . EIVE version can be found
+ [here](https://github.com/spacefisch/linux-xlnx) . Pre-compiled files can be
+ found [here](https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Software/q7s-linux-components&fileid=777299).
+ * Q7S base project can be found [here](https://egit.irs.uni-stuttgart.de/eive/q7s-base)
+ * Minimal base project files can be found [here](https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Software/xiphos-q7s-sdk&fileid=510908)
* Host System
* Generic software components which are not dependant on hardware can also
be run on a host system. All host code is contained in the `bsp_hosted` folder
@@ -28,30 +35,56 @@ The CMake build system can be used to generate build systems as well (see helper
- Linux Host: Uses the `bsp_hosted` BSP folder and the CMake Unix Makefiles generator.
- Windows Host: Uses the `bsp_hosted` BSP folder, the CMake MinGW Makefiles generator and MSYS2.
-## Setting up development environment
+# Setting up development environment
-### Installing Vivado the the Xilinx development tools
+## Installing Vivado the the Xilinx development tools
It's also possible to perform debugging with a normal Eclipse installation by installing
-the TCF plugin and downloading the cross-compiler as specified in the section below.
+the TCF plugin and downloading the cross-compiler as specified in the section below. However,
+if you want to generate the `*.xdi` files necessary to update the firmware, you need to
+installed Vivado with the SDK core tools.
* Install Vivado 2018.2 and Xilinx SDK from https://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/vivado-design-tools/archive.html.
- Install the Vivado Design Suite - HLx Editions - 2018.2 Full Product Installation instead of the updates. It is recommended to use the installer.
+ Install the Vivado Design Suite - HLx Editions - 2018.2 Full Product Installation instead of
+ the updates. It is recommended to use the installer.
* Install settings. In the Devices selection, it is sufficient to pick SoC → Zynq-7000:
-
+
-
+
-
+
-* For supported OS refer to https://www.xilinx.com/support/documentation/sw_manuals/xilinx2018_2/ug973-vivado-release-notes-install-license.pdf
-* Add path of linux cross-compiler to permanent environment variables (`.profile` file in Linux):
+* For supported OS refer to https://www.xilinx.com/support/documentation/sw_manuals/xilinx2018_2/ug973-vivado-release-notes-install-license.pdf .
+ Installation was tested on Windows and Ubuntu 21.04.
+* Add path of linux cross-compiler to permanent environment variables (`.bashrc` file in Linux):
`\SDK\2018.2\gnu\aarch32\nt\gcc-arm-linux-gnueabi\bin`
or set up path each time before debugging.
-### Installing toolchain without Vivado
+### Installing on Linux - Device List Issue
+
+When installing on Ubuntu, the installer might get stuck at the `Generating installed device list`
+step. When this happens, you can kill the installation process (might be necessara to kill a process
+twice) and generate this list manually with the following commands, according to
+[this forum entry](https://forums.xilinx.com/t5/Installation-and-Licensing/Vivado-2018-3-Final-Processing-hangs-at-Generating-installed/m-p/972114#M25861).
+
+1. Install the following library
+ ```sh
+ sudo apt install libncurses5
+ ```
+
+2. ```sh
+ sudo /Vivado/2018.2/bin/vivado -nolog -nojournal -mode batch -source
+ /.xinstall/Vivado_2018.2/scripts/xlpartinfo.tcl -tclargs
+ /Vivado/2018.2/data/parts/installed_devices.txt
+ ```
+
+For Linux, you can also download a more recent version of the
+[Linaro 8.3.0 cross-compiler](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads)
+from [here](https://developer.arm.com/-/media/Files/downloads/gnu-a/8.3-2019.03/binrel/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf.tar.xz?revision=e09a1c45-0ed3-4a8e-b06b-db3978fd8d56&la=en&hash=93ED4444B8B3A812B893373B490B90BBB28FD2E3)
+
+## Installing toolchain without Vivado
You can download the toolchains for Windows and Linux
[from the EIVE cloud](https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files?dir=/EIVE_IRS/Software/tools&fileid=831898).
@@ -69,7 +102,7 @@ or the following command for Linux (could be useful for CI/CD)
wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/2Fp2ag6NGnbtAsK/download/gcc-arm-linux-gnueabi.tar.gz
```
-### Installing CMake and MSYS2 on Windows
+## Installing CMake and MSYS2 on Windows
1. Install [MSYS2](https://www.msys2.org/) and [CMake](https://cmake.org/download/) first.
@@ -94,7 +127,7 @@ wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/2Fp2ag6NGnbtAsK/downloa
pacman -S mingw-w64-x86_64-cmake mingw-w64-x86_64-make mingw-w64-x86_64-gcc mingw-w64-x86_64-gdb python3
```
-### Installing CMake on Linux
+## Installing CMake on Linux
1. Run the following command
@@ -117,7 +150,7 @@ wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/agnJGYeRf6fw2ci/downloa
Then, create a new environmental variables `Q7S_SYSROOT` and set it to the local system root path.
-## Building the software with CMake
+# Building the software with CMake
When using Windows, run theses steps in MSYS2.
@@ -153,7 +186,7 @@ When using Windows, run theses steps in MSYS2.
```sh
cd cmake/scripts/Q7S
- ./create_cmake_debug.sh
+ ./make_debug_cfg.sh
cd ../../..
```
@@ -230,7 +263,7 @@ IP address and path settings differ from machine to machine.
You can run it manually there. To perform auto-start on boot, have a look at the start-up
application section.
-## Debugging the software via Flatsat PC
+# Debugging the software via Flatsat PC
Open SSH connection to flatsat PC:
@@ -269,7 +302,8 @@ the process using it with `q7s_kill`.
You can use `AltGr` + `X` to exit the picocom session.
-To debug an application, first make sure a static IP address is assigned to the Q7S. Run ifconfig on the Q7S serial console.
+To debug an application, first make sure a static IP address is assigned to the Q7S. Run ifconfig
+on the Q7S serial console.
```sh
ifconfig
@@ -289,12 +323,14 @@ To launch application from Xilinx SDK setup port fowarding on the development ma
ssh -L 1534:192.168.133.10:1534 eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 -t bash
```
-This forwards any requests to localhost:1534 to the port 1534 of the Q7S with the IP address 192.168.133.10.
+This forwards any requests to localhost:1534 to the port 1534 of the Q7S with the IP address
+192.168.133.10.
This needs to be done every time, so it is recommended to create an alias to do this quickly.
-Note: When now setting up a debug session in the Xilinx SDK, the host must be set to localhost instead of the IP address of the Q7S.
+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.
-## Transfering files via SCP
+# Transfering files via SCP
To transfer files from the local machine to the Q7S, use port forwarding
@@ -318,11 +354,11 @@ From a windows machine files can be copied with putty tools (note: use IPv4 addr
pscp -scp -P 22 eive@192.168.199.227:/example-file
````
-## Launching an application at start-up
+# Launching an application at start-up
-Load the root partiton from the flash memory (there are to nor-flash memories and each flash holds two xdi images).
-Note: It is not possible to modify the currently loaded root partition, e.g. creating directories. To do this,
-the parition needs to be mounted.
+Load the root partiton from the flash memory (there are to nor-flash memories and each flash holds
+two xdi images). Note: It is not possible to modify the currently loaded root partition, e.g.
+creating directories. To do this, the parition needs to be mounted.
1. Disable write protection of the desired root partition
@@ -340,11 +376,13 @@ the parition needs to be mounted.
3. Copy the executable to `/usr/bin`
4. Make sure the permissions to execute the application are set
+
```sh
chmod +x application
```
5. Create systemd service in /lib/systemd/system. The following shows an example service.
+
```sh
cat > example.service
[Unit]
@@ -361,8 +399,8 @@ the parition needs to be mounted.
[Install]
WantedBy=multi-user.target
```
-6. Enable the service. This is normally done with systemctl enable. However, this is not possible when the service is
- created for a mounted root partition. Therefore create a symlink as follows.
+6. Enable the service. This is normally done with systemctl enable. However, this is not possible
+ when the service is created for a mounted root partition. Therefore create a symlink as follows.
```sh
ln -s '/tmp/the-mounted-xdi-image/lib/systemd/system/example.service' '/tmp/the-mounted-xdi-image/etc/systemd/system/multi-user.target.wants/example.service'
```
@@ -380,37 +418,14 @@ the parition needs to be mounted.
```sh
systemctl status example
```
+
More detailed information about the used q7s commands can be found in the Q7S user manual.
-### Bringing up CAN
-
- ```sh
- ip link set can0 down
- ip link set can0 type can loopback off
- ip link set can0 up type can bitrate 1000000
- ```
-
-Following command sends 8 bytes to device with id 99 (for petalinux)
-````
-cansend can0 -i99 99 88 77 11 33 11 22 99
-````
-For Q7S use this:
-````
-cansend can0 5A1#11.22.33.44.55.66.77.88
-````
-Turn loopback mode on:
-````
-ip link set can0 type can bitrate 1000000 loopback on
-````
-Reading data from CAN:
-````
-candump can0
-````
-
## 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.
+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:
@@ -435,58 +450,27 @@ required for some framework components. The recommended values for the new messa
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.
+ ```sh
+ sudo nano /etc/sysctl.conf
+ ```
-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).
+ Append at end:
+ ```sh
+ fs/mqueue/msg_max =
+ ```
+
+ Apply changes with:
+ ```sh
+ sudo sysctl -p
+ ```
-## Flight Software Framework (FSFW)
+ A possible solution which only persists for the current session is
+ ```sh
+ echo | sudo tee /proc/sys/fs/mqueue/msg_max
+ ```
-An EIVE fork of the FSFW is submodules into this repository.
-To add the master upstream branch and merge changes and updates from it
-into the fork, run the following command in the fsfw folder first:
-
-```sh
-git remote add upstream https://egit.irs.uni-stuttgart.de/fsfw/fsfw.git
-git remote update --prune
-```
-
-After that, an update can be merged by running
-
-```sh
-git merge upstream/master
-```
-
-Alternatively, changes from other upstreams (forks) and branches can be merged like that in
-the same way.
-
-## PCDU
+# PCDU
Connect to serial console of P60 Dock
````
@@ -511,10 +495,11 @@ p60-dock # param get out_en[0]
GET out_en[0] = 1
````
-## Debugging the software (when workstation is directly conncected to Q7S)
+# Debugging the software (when workstation is directly conncected to Q7S)
1. Assign static IP address to Q7S
- * Open serial console of Q7S (Accessible via the micro-USB of the PIM, see also Q7S user maunal chapter 10.3)
+ * Open serial console of Q7S (Accessible via the micro-USB of the PIM, see also Q7S user
+ manual chapter 10.3)
* Baudrate 115200
* Login to Q7S:
* user: root
@@ -562,10 +547,10 @@ GET out_en[0] = 1
11. Test connection (This ensures the TCF Agent is running on the Q7S)
12. Select Application tab
* Project Name: eive_obsw
- * Local File Path: Path to eiveobsw-linux.elf (in _bin\linux\devel)
- * Remote File Path: /tmp/eive_obsw.elf
+ * Local File Path: Path to eiveobsw-linux.elf (in `_bin\linux\devel`)
+ * Remote File Path: `/tmp/eive_obsw.elf`
-## Running cppcheck on the Software
+# Running cppcheck on the Software
Static code analysis can be useful to find bugs.
`cppcheck` can be used for this purpose. On Windows you can use MinGW64 to do this.
@@ -597,6 +582,47 @@ Finally, you can convert the generated `.xml` file to HTML with the following co
cppcheck-htmlreport --file=report.xml --report-dir=cppcheck --source-dir=..
```
+# Special notes on Eclipse
+
+When using Eclipse, there are two special build variables in the project properties
+→ C/C++ Build → Build Variables called `Q7S_SYSROOT` or `RPI_SYSROOT`. You can set
+the sysroot path in those variables to get any additional includes like `gpiod.h` in the
+Eclipse indexer.
+
+# Q7S Utilities and Troubleshooting
+
+## pa3tool Host Tool
+
+The `pa3tool` is a host tool to interface with the ProASIC3 on the Q7S board. It was
+installed on the clean room PC but it can also be found
+[on the Traq platform](https://trac2.xiphos.ca/manual/attachment/wiki/WikiStart/libpa3-1.3.4.tar.gz).
+
+For more information, see Q7S datasheet.
+
+## Creating files with cat and echo
+
+The only folder which can be written in the root filesystem is the `tmp` folder.
+
+You can create a simple file with initial content with `echo`
+
+```sh
+echo "Hallo Welt" > /tmp/test.txt
+cat /tmp/test.txt
+```
+
+For more useful combinations, see this [link](https://www.freecodecamp.org/news/the-cat-command-in-linux-how-to-create-a-text-file-with-cat-or-touch/).
+
+## Using `system` when debugging
+
+Please note that when using a `system` call in C++/C code and debugging, a new thread will be
+spawned which will appear on the left in Eclipse or Xilinx SDK as a `sh` program.
+The debugger might attach to this child process automatically, depending on debugger configuration,
+and the process needs to be selected and continued/started manually. You can enable or disable
+this behaviour by selecting or deselecting the `Attach Process Children` option in the Remote
+Application Configuration for the TCF plugin like shown in the following picture
+
+
+
## Libgpiod
Detect all gpio device files:
@@ -626,10 +652,64 @@ gpioget
Example to get state:
gpioget gpiochip7 14
-Both the MIOs and EMIOs can be accessed via the zynq_gpio instance which comprises 118 pins
-(54 MIOs and 64 EMIOs).
+Both the MIOs and EMIOs can be accessed via the zynq_gpio instance which
+comprises 118 pins (54 MIOs and 64 EMIOs).
-## Running the EIVE OBSW on a Raspberry Pi
+## Xilinx UARTLIE
+
+Get info about ttyUL* devices
+````
+cat /proc/tty/driver
+````
+
+## I2C
+
+Getting information about I2C device
+````
+ls /sys/class/i2c-dev/i2c-0/device/device/driver
+````
+This shows the memory mapping of /dev/i2c-0
+
+## CAN
+
+```sh
+ip link set can0 down
+ip link set can0 type can loopback off
+ip link set can0 up type can bitrate 1000000
+```
+
+Following command sends 8 bytes to device with id 99 (for petalinux)
+````
+cansend can0 -i99 99 88 77 11 33 11 22 99
+````
+For Q7S use this:
+````
+cansend can0 5A1#11.22.33.44.55.66.77.88
+````
+Turn loopback mode on:
+````
+ip link set can0 type can bitrate 1000000 loopback on
+````
+Reading data from CAN:
+````
+candump can0
+````
+
+## Useful Q7S Linux Commands
+
+Display currently running image:
+
+```sh
+xsc_boot_copy
+```
+
+Rebooting currently running image:
+
+```sh
+xsc_boot_copy -r
+```
+
+# Running the EIVE OBSW on a Raspberry Pi
Special section for running the EIVE OBSW on the Raspberry Pi.
The Raspberry Pi build uses the `bsp_rpi` BSP folder, and a very similar cross-compiler.
@@ -645,28 +725,21 @@ sudo apt-get install gpiod libgpiod-dev
to install the required GPIO libraries before cloning the system root folder.
-## Special notes on Eclipse
+# Flight Software Framework (FSFW)
-When using Eclipse, there are two special build variables in the project properties
-→ C/C++ Build → Build Variables called `Q7S_SYSROOT` or `RPI_SYSROOT`. You can set
-the sysroot path in those variables to get any additional includes like `gpiod.h` in the
-Eclipse indexer.
+An EIVE fork of the FSFW is submodules into this repository.
+To add the master upstream branch and merge changes and updates from it
+into the fork, run the following command in the fsfw folder first:
-## Xilinx UARTLIE
-Get info about ttyUL* devices
-````
-cat /proc/tty/driver
-````
+```sh
+git remote add upstream https://egit.irs.uni-stuttgart.de/fsfw/fsfw.git
+git remote update --prune
+```
-## I2C
-Getting information about I2C device
-````
-ls /sys/class/i2c-dev/i2c-0/device/device/driver
-````
-This shows the memory mapping of /dev/i2c-0
+After that, an update can be merged by running
-## Useful Q7S Linux Commands
-Rebooting currently running image:
-````
-xsc_boot_copy -r
-````
+```sh
+git merge upstream/master
+```
+
+Alternatively, changes from other upstreams (forks) and branches can be merged like that in the same way.
diff --git a/bsp_q7s/CMakeLists.txt b/bsp_q7s/CMakeLists.txt
index f739ad2c..3bc9aa4e 100644
--- a/bsp_q7s/CMakeLists.txt
+++ b/bsp_q7s/CMakeLists.txt
@@ -2,13 +2,15 @@ target_sources(${TARGET_NAME} PUBLIC
main.cpp
)
+add_subdirectory(boardtest)
+
if(Q7S_SIMPLE_MODE)
add_subdirectory(simple)
else()
add_subdirectory(boardconfig)
add_subdirectory(comIF)
- add_subdirectory(boardtest)
add_subdirectory(gpio)
add_subdirectory(core)
+ add_subdirectory(memory)
add_subdirectory(spiCallbacks)
endif()
diff --git a/bsp_q7s/boardconfig/q7sConfig.h.in b/bsp_q7s/boardconfig/q7sConfig.h.in
index 6ee84821..9bed2a4a 100644
--- a/bsp_q7s/boardconfig/q7sConfig.h.in
+++ b/bsp_q7s/boardconfig/q7sConfig.h.in
@@ -1,6 +1,8 @@
#ifndef BSP_Q7S_BOARDCONFIG_Q7S_CONFIG_H_
#define BSP_Q7S_BOARDCONFIG_Q7S_CONFIG_H_
+#include
+
#cmakedefine01 Q7S_SIMPLE_MODE
#define Q7S_ADD_RTD_DEVICES 0
@@ -11,4 +13,12 @@
#define Q7S_ADD_SPI_TEST 0
#endif
+#define Q7S_SIMPLE_ADD_FILE_SYSTEM_TEST 0
+
+namespace config {
+
+static const uint32_t SD_CARD_ACCESS_MUTEX_TIMEOUT = 50;
+
+}
+
#endif /* BSP_Q7S_BOARDCONFIG_Q7S_CONFIG_H_ */
diff --git a/bsp_q7s/boardtest/CMakeLists.txt b/bsp_q7s/boardtest/CMakeLists.txt
index 0599b73f..1cda38ca 100644
--- a/bsp_q7s/boardtest/CMakeLists.txt
+++ b/bsp_q7s/boardtest/CMakeLists.txt
@@ -1,4 +1,6 @@
target_sources(${TARGET_NAME} PRIVATE
+ FileSystemTest.cpp
+ Q7STestTask.cpp
)
diff --git a/bsp_q7s/boardtest/FileSystemTest.cpp b/bsp_q7s/boardtest/FileSystemTest.cpp
new file mode 100644
index 00000000..1de5bb7a
--- /dev/null
+++ b/bsp_q7s/boardtest/FileSystemTest.cpp
@@ -0,0 +1,21 @@
+#include "FileSystemTest.h"
+#include "fsfw/timemanager/Stopwatch.h"
+
+#include
+#include
+
+FileSystemTest::FileSystemTest() {
+ using namespace std;
+ SdCard sdCard = SdCard::SDC0;
+ cout << "SD Card Test for SD card " << static_cast(sdCard) << std::endl;
+ //Stopwatch stopwatch;
+ std::system("q7hw sd info all > /tmp/sd_status.txt");
+ //stopwatch.stop(true);
+ std::system("q7hw sd set 0 on > /tmp/sd_set.txt");
+ //stopwatch.stop(true);
+ std::system("q7hw sd set 0 off > /tmp/sd_set.txt");
+ //stopwatch.stop(true);
+}
+
+FileSystemTest::~FileSystemTest() {
+}
diff --git a/bsp_q7s/boardtest/FileSystemTest.h b/bsp_q7s/boardtest/FileSystemTest.h
new file mode 100644
index 00000000..907c86ca
--- /dev/null
+++ b/bsp_q7s/boardtest/FileSystemTest.h
@@ -0,0 +1,18 @@
+#ifndef BSP_Q7S_BOARDTEST_FILESYSTEMTEST_H_
+#define BSP_Q7S_BOARDTEST_FILESYSTEMTEST_H_
+
+enum SdCard {
+ SDC0,
+ SDC1
+};
+
+class FileSystemTest {
+public:
+ FileSystemTest();
+ virtual~ FileSystemTest();
+private:
+};
+
+
+
+#endif /* BSP_Q7S_BOARDTEST_FILESYSTEMTEST_H_ */
diff --git a/bsp_q7s/boardtest/Q7STestTask.cpp b/bsp_q7s/boardtest/Q7STestTask.cpp
new file mode 100644
index 00000000..a1470b79
--- /dev/null
+++ b/bsp_q7s/boardtest/Q7STestTask.cpp
@@ -0,0 +1,67 @@
+#include "Q7STestTask.h"
+
+#include "fsfw/timemanager/Stopwatch.h"
+#include "fsfw/tasks/TaskFactory.h"
+
+#include "bsp_q7s/memory/scratchApi.h"
+
+#include
+#include
+#include
+
+Q7STestTask::Q7STestTask(object_id_t objectId): TestTask(objectId) {
+}
+
+ReturnValue_t Q7STestTask::performOneShotAction() {
+ //sdCardTests();
+ testScratchApi();
+ return TestTask::performOneShotAction();
+}
+
+void Q7STestTask::sdCardTests() {
+ using namespace std;
+ Stopwatch stopwatch;
+ int result = std::system("q7hw sd info all > /tmp/sd_status.txt");
+ if(result != 0) {
+ sif::debug << "system call failed with " << result << endl;
+ }
+ ifstream sdStatus("/tmp/sd_status.txt");
+ string line;
+ uint8_t idx = 0;
+ while (std::getline(sdStatus, line)) {
+ std::istringstream iss(line);
+ string word;
+ while(iss >> word) {
+ if(word == "on") {
+ sif::info << "SD card " << static_cast(idx) << " is on" << endl;
+ }
+ else if(word == "off") {
+ sif::info << "SD card " << static_cast(idx) << " is off" << endl;
+ }
+ }
+ idx++;
+ }
+ std::remove("/tmp/sd_status.txt");
+}
+
+void Q7STestTask::fileTests() {
+ using namespace std;
+ ofstream testFile("/tmp/test.txt");
+ testFile << "Hallo Welt" << endl;
+ testFile.close();
+
+ system("echo \"Hallo Welt\" > /tmp/test2.txt");
+ system("echo \"Hallo Welt\"");
+}
+
+void Q7STestTask::testScratchApi() {
+ ReturnValue_t result = scratch::writeNumber("TEST", 1);
+ if(result != HasReturnvaluesIF::RETURN_OK) {
+ sif::debug << "Q7STestTask::scratchApiTest: Writing number failed" << std::endl;
+ }
+ int number = 0;
+ result = scratch::readNumber("TEST", number);
+ if(result != HasReturnvaluesIF::RETURN_OK) {
+ sif::debug << "Q7STestTask::scratchApiTest: Reading number failed" << std::endl;
+ }
+}
diff --git a/bsp_q7s/boardtest/Q7STestTask.h b/bsp_q7s/boardtest/Q7STestTask.h
new file mode 100644
index 00000000..664a8fa2
--- /dev/null
+++ b/bsp_q7s/boardtest/Q7STestTask.h
@@ -0,0 +1,20 @@
+#ifndef BSP_Q7S_BOARDTEST_Q7STESTTASK_H_
+#define BSP_Q7S_BOARDTEST_Q7STESTTASK_H_
+
+#include "test/testtasks/TestTask.h"
+
+class Q7STestTask: public TestTask {
+public:
+ Q7STestTask(object_id_t objectId);
+private:
+ ReturnValue_t performOneShotAction() override;
+
+ void sdCardTests();
+ void fileTests();
+
+ void testScratchApi();
+
+};
+
+
+#endif /* BSP_Q7S_BOARDTEST_Q7STESTTASK_H_ */
diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp
index 253efd91..98ddb347 100644
--- a/bsp_q7s/core/CoreController.cpp
+++ b/bsp_q7s/core/CoreController.cpp
@@ -1,4 +1,5 @@
#include "CoreController.h"
+#include "../memory/SdCardManager.h"
CoreController::CoreController(object_id_t objectId):
ExtendedControllerBase(objectId, objects::NO_OBJECT, 5) {
@@ -20,6 +21,39 @@ LocalPoolDataSetBase* CoreController::getDataSetHandle(sid_t sid) {
return nullptr;
}
+ReturnValue_t CoreController::initialize() {
+ // Find a way to store this non-volatile outside of SD cards (ProASIC?)
+ sd::SdCard preferredSdCard = sd::SdCard::SLOT_0;
+ std::string printoutString;
+ if(preferredSdCard == sd::SdCard::SLOT_0) {
+ printoutString = "0";
+ }
+ else {
+ printoutString = "1";
+ }
+ // Creator or update status file
+ ReturnValue_t result = SdCardManager::instance()->updateSdCardStateFile();
+ if(result != HasReturnvaluesIF::RETURN_OK) {
+ sif::warning << "CoreController::initialize: Updating SD card state file failed"
+ << std::endl;
+ }
+
+ sif::info << "Switching on SD card " << printoutString << ".." << std::endl;
+
+ result = SdCardManager::instance()->switchOnSdCard(preferredSdCard);
+ if(result == SdCardManager::ALREADY_ON) {
+ sif::info << "SD card " << printoutString << " is already on" << std::endl;
+ }
+ else if(result != HasReturnvaluesIF::RETURN_OK) {
+ sif::warning << "CoreController::initialize: Turning SD card on failed"
+ << std::endl;
+ }
+ else {
+ sif::info << "SD card " << printoutString << " was switched on" << std::endl;
+ }
+ return HasReturnvaluesIF::RETURN_OK;
+}
+
ReturnValue_t CoreController::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) {
return HasReturnvaluesIF::RETURN_OK;
diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h
index bc8a1581..674ed073 100644
--- a/bsp_q7s/core/CoreController.h
+++ b/bsp_q7s/core/CoreController.h
@@ -7,6 +7,8 @@ class CoreController: public ExtendedControllerBase {
public:
CoreController(object_id_t objectId);
+ ReturnValue_t initialize() override;
+
ReturnValue_t handleCommandMessage(CommandMessage *message) override;
void performControlOperation() override;
private:
diff --git a/bsp_q7s/core/InitMission.cpp b/bsp_q7s/core/InitMission.cpp
index 3e655255..2bc334b9 100644
--- a/bsp_q7s/core/InitMission.cpp
+++ b/bsp_q7s/core/InitMission.cpp
@@ -44,6 +44,7 @@ void initmission::initMission() {
void initmission::initTasks() {
TaskFactory* factory = TaskFactory::instance();
+ ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if(factory == nullptr) {
/* Should never happen ! */
return;
@@ -54,11 +55,18 @@ void initmission::initTasks() {
void (*missedDeadlineFunc) (void) = nullptr;
#endif
+ PeriodicTaskIF* coreController = factory->createPeriodicTask(
+ "CORE_CTRL", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc);
+ result = coreController->addComponent(objects::CORE_CONTROLLER);
+ if(result != HasReturnvaluesIF::RETURN_OK) {
+ initmission::printAddObjectError("CORE_CTRL", objects::CORE_CONTROLLER);
+
+ }
+
/* TMTC Distribution */
PeriodicTaskIF* tmTcDistributor = factory->createPeriodicTask(
"DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
- ReturnValue_t result = tmTcDistributor->addComponent(
- objects::CCSDS_PACKET_DISTRIBUTOR);
+ result = tmTcDistributor->addComponent(objects::CCSDS_PACKET_DISTRIBUTOR);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("CCSDS_DISTRIB", objects::CCSDS_PACKET_DISTRIBUTOR);
}
@@ -229,6 +237,7 @@ void initmission::initTasks() {
tmTcDistributor->startTask();
udpBridgeTask->startTask();
udpPollingTask->startTask();
+ coreController->startTask();
#if TE0720 == 0
uartPst->startTask();
diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp
index 991cd8b2..5f015ff1 100644
--- a/bsp_q7s/core/ObjectFactory.cpp
+++ b/bsp_q7s/core/ObjectFactory.cpp
@@ -1,3 +1,4 @@
+#include
#include "ObjectFactory.h"
#include "OBSWConfig.h"
#include "tmtc/apid.h"
@@ -621,6 +622,11 @@ void ObjectFactory::produce(void* args){
new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
+ /* Test Task */
+#if OBSW_ADD_TEST_CODE == 1
+ new Q7STestTask(objects::TEST_TASK);
+#endif
+
#if TE0720 == 1 && TEST_LIBGPIOD == 1
/* Configure MIO0 as input */
GpiodRegular gpioConfigMio0(std::string("gpiochip0"), 0,
@@ -695,4 +701,5 @@ void ObjectFactory::produce(void* args){
#if Q7S_ADD_SPI_TEST == 1
new SpiTestClass(objects::SPI_TEST, gpioComIF);
#endif
+
}
diff --git a/bsp_q7s/main.cpp b/bsp_q7s/main.cpp
index 93968b76..9ce0dca2 100644
--- a/bsp_q7s/main.cpp
+++ b/bsp_q7s/main.cpp
@@ -6,12 +6,15 @@
#include "simple/simple.h"
#endif
+#include
+
/**
* @brief This is the main program for the target hardware.
* @return
*/
int main(void)
{
+ using namespace std;
#if Q7S_SIMPLE_MODE == 0
return obsw::obsw();
#else
diff --git a/bsp_q7s/memory/CMakeLists.txt b/bsp_q7s/memory/CMakeLists.txt
index 2ccdc7e2..ada948fb 100644
--- a/bsp_q7s/memory/CMakeLists.txt
+++ b/bsp_q7s/memory/CMakeLists.txt
@@ -1,4 +1,6 @@
target_sources(${TARGET_NAME} PRIVATE
- FileSystemManager.cpp
+ FileSystemHandler.cpp
SdCardAccess.cpp
+ SdCardManager.cpp
+ scratchApi.cpp
)
\ No newline at end of file
diff --git a/bsp_q7s/memory/FileSystemHandler.cpp b/bsp_q7s/memory/FileSystemHandler.cpp
new file mode 100644
index 00000000..5f7e0435
--- /dev/null
+++ b/bsp_q7s/memory/FileSystemHandler.cpp
@@ -0,0 +1,65 @@
+#include "FileSystemHandler.h"
+
+#include "fsfw/tasks/TaskFactory.h"
+#include "fsfw/memory/GenericFileSystemMessage.h"
+#include "fsfw/ipc/QueueFactory.h"
+
+FileSystemHandler::FileSystemHandler(object_id_t fileSystemHandler):
+ SystemObject(fileSystemHandler) {
+ mq = QueueFactory::instance()->createMessageQueue(50);
+}
+
+FileSystemHandler::~FileSystemHandler() {
+ QueueFactory::instance()->deleteMessageQueue(mq);
+}
+
+ReturnValue_t FileSystemHandler::performOperation(uint8_t unsignedChar) {
+ while(true) {
+ CommandMessage filemsg;
+ ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
+ while(true) {
+ result = mq->receiveMessage(&filemsg);
+ if(result == MessageQueueIF::EMPTY) {
+ break;
+ }
+ else if(result != HasReturnvaluesIF::RETURN_FAILED) {
+ sif::warning << "FileSystemHandler::performOperation: Message reception failed!"
+ << std::endl;
+ break;
+ }
+ Command_t command = filemsg.getCommand();
+ switch(command) {
+ case(GenericFileSystemMessage::CMD_CREATE_DIRECTORY): {
+ break;
+ }
+ case(GenericFileSystemMessage::CMD_CREATE_FILE): {
+ break;
+ }
+ }
+ }
+
+ // This task will have a low priority and will run permanently in the background
+ // so we will just run in a permanent loop here and check file system
+ // messages permanently
+ TaskFactory::instance()->delayTask(1000);
+ }
+}
+
+MessageQueueId_t FileSystemHandler::getCommandQueue() const {
+ return mq->getId();
+}
+
+ReturnValue_t FileSystemHandler::appendToFile(const char *repositoryPath, const char *filename,
+ const uint8_t *data, size_t size, uint16_t packetNumber, void *args) {
+ return HasReturnvaluesIF::RETURN_OK;
+}
+
+ReturnValue_t FileSystemHandler::createFile(const char *repositoryPath, const char *filename,
+ const uint8_t *data, size_t size, void *args) {
+ return HasReturnvaluesIF::RETURN_OK;
+}
+
+ReturnValue_t FileSystemHandler::deleteFile(const char *repositoryPath, const char *filename,
+ void *args) {
+ return HasReturnvaluesIF::RETURN_OK;
+}
diff --git a/bsp_q7s/memory/FileSystemHandler.h b/bsp_q7s/memory/FileSystemHandler.h
new file mode 100644
index 00000000..04cea3dc
--- /dev/null
+++ b/bsp_q7s/memory/FileSystemHandler.h
@@ -0,0 +1,39 @@
+#ifndef BSP_Q7S_MEMORY_FILESYSTEMHANDLER_H_
+#define BSP_Q7S_MEMORY_FILESYSTEMHANDLER_H_
+
+#include "fsfw/ipc/MessageQueueIF.h"
+#include "fsfw/tasks/ExecutableObjectIF.h"
+#include "fsfw/objectmanager/SystemObject.h"
+#include "fsfw/memory/HasFileSystemIF.h"
+
+class FileSystemHandler: public SystemObject,
+ public ExecutableObjectIF,
+ public HasFileSystemIF {
+public:
+ FileSystemHandler(object_id_t fileSystemHandler);
+ virtual~ FileSystemHandler();
+
+ ReturnValue_t performOperation(uint8_t) override;
+
+ /**
+ * Function to get the MessageQueueId_t of the implementing object
+ * @return MessageQueueId_t of the object
+ */
+ MessageQueueId_t getCommandQueue() const override;
+
+private:
+ MessageQueueIF* mq = nullptr;
+
+ ReturnValue_t appendToFile(const char* repositoryPath,
+ const char* filename, const uint8_t* data, size_t size,
+ uint16_t packetNumber, void* args = nullptr) override;
+ ReturnValue_t createFile(const char* repositoryPath,
+ const char* filename, const uint8_t* data = nullptr,
+ size_t size = 0, void* args = nullptr) override;
+ ReturnValue_t deleteFile(const char* repositoryPath,
+ const char* filename, void* args = nullptr) override;
+};
+
+
+
+#endif /* BSP_Q7S_MEMORY_FILESYSTEMMANAGER_H_ */
diff --git a/bsp_q7s/memory/FileSystemManager.cpp b/bsp_q7s/memory/FileSystemManager.cpp
deleted file mode 100644
index 40c8e58a..00000000
--- a/bsp_q7s/memory/FileSystemManager.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "FileSystemManager.h"
-
-class FileSystemManager {
-public:
-
-private:
-};
diff --git a/bsp_q7s/memory/FileSystemManager.h b/bsp_q7s/memory/FileSystemManager.h
deleted file mode 100644
index 4fc8dc52..00000000
--- a/bsp_q7s/memory/FileSystemManager.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef BSP_Q7S_MEMORY_FILESYSTEMMANAGER_H_
-#define BSP_Q7S_MEMORY_FILESYSTEMMANAGER_H_
-
-
-
-
-
-#endif /* BSP_Q7S_MEMORY_FILESYSTEMMANAGER_H_ */
diff --git a/bsp_q7s/memory/SdCardAccess.cpp b/bsp_q7s/memory/SdCardAccess.cpp
index 3d5f12b9..92837787 100644
--- a/bsp_q7s/memory/SdCardAccess.cpp
+++ b/bsp_q7s/memory/SdCardAccess.cpp
@@ -1,4 +1,7 @@
#include "SdCardAccess.h"
-SdCardAccess::SdCardAccess() {
+#include "fsfw/ipc/MutexGuard.h"
+
+SdCardAccess::SdCardAccess(sd::SdCard sdCard) {
+
}
diff --git a/bsp_q7s/memory/SdCardAccess.h b/bsp_q7s/memory/SdCardAccess.h
index ba273d09..8128b122 100644
--- a/bsp_q7s/memory/SdCardAccess.h
+++ b/bsp_q7s/memory/SdCardAccess.h
@@ -1,9 +1,11 @@
#ifndef BSP_Q7S_MEMORY_SDCARDACCESS_H_
#define BSP_Q7S_MEMORY_SDCARDACCESS_H_
+#include "definitions.h"
+
class SdCardAccess {
public:
- SdCardAccess();
+ SdCardAccess(sd::SdCard sdCard);
private:
};
diff --git a/bsp_q7s/memory/SdCardManager.cpp b/bsp_q7s/memory/SdCardManager.cpp
new file mode 100644
index 00000000..af963180
--- /dev/null
+++ b/bsp_q7s/memory/SdCardManager.cpp
@@ -0,0 +1,150 @@
+#include "SdCardManager.h"
+#include "fsfw/ipc/MutexFactory.h"
+#include "fsfw/serviceinterface/ServiceInterface.h"
+
+#include
+#include
+
+SdCardManager* SdCardManager::factoryInstance = nullptr;
+
+SdCardManager::SdCardManager() {
+}
+
+SdCardManager::~SdCardManager() {
+}
+
+void SdCardManager::create() {
+ if(factoryInstance == nullptr) {
+ factoryInstance = new SdCardManager();
+ }
+}
+
+SdCardManager* SdCardManager::instance() {
+ SdCardManager::create();
+ return SdCardManager::factoryInstance;
+}
+
+ReturnValue_t SdCardManager::switchOnSdCard(sd::SdCard sdCard) {
+ std::pair active;
+ ReturnValue_t result = sdCardActive(active);
+ if(result != HasReturnvaluesIF::RETURN_OK) {
+ return result;
+ }
+ if((sdCard == sd::SdCard::SLOT_0 and active.first) or
+ (sdCard == sd::SdCard::SLOT_1 and active.second)) {
+ return ALREADY_ON;
+ }
+ return setSdCardState(sdCard, true);
+}
+
+ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard) {
+ std::pair active;
+ ReturnValue_t result = sdCardActive(active);
+ if(result != HasReturnvaluesIF::RETURN_OK) {
+ return result;
+ }
+ if((sdCard == sd::SdCard::SLOT_0 and not active.first) or
+ (sdCard == sd::SdCard::SLOT_1 and not active.second)) {
+ return ALREADY_OFF;
+ }
+ return setSdCardState(sdCard, false);
+}
+
+ReturnValue_t SdCardManager::setSdCardState(sd::SdCard sdCard, bool on) {
+ std::string sdstring = "";
+ std::string statestring = "";
+ if(sdCard == sd::SdCard::SLOT_0) {
+ sdstring = "0";
+ }
+ else if(sdCard == sd::SdCard::SLOT_1) {
+ sdstring = "1";
+ }
+ if(on) {
+ statestring = "on";
+ }
+ else {
+ statestring = "off";
+ }
+ std::ostringstream command;
+ command << "q7hw sd set " << sdstring << " " << statestring;
+ int result = std::system(command.str().c_str());
+ if(result == 0) {
+ return HasReturnvaluesIF::RETURN_OK;
+ }
+ sif::warning << "SdCardManager::setSdCardState: system call failed with code " <<
+ result << std::endl;
+ return SYSTEM_CALL_ERROR;
+}
+
+ReturnValue_t SdCardManager::sdCardActive(std::pair& active) {
+ using namespace std;
+ if(not filesystem::exists("/tmp/sd_status.txt")) {
+ return STATUS_FILE_NEXISTS;
+ }
+
+ // Now the file should exist in any case. Still check whether it exists.
+ fstream sdStatus("/tmp/sd_status.txt");
+ if (not sdStatus.good()) {
+ return STATUS_FILE_NEXISTS;
+ }
+ string line;
+ uint8_t idx = 0;
+
+ while (std::getline(sdStatus, line)) {
+ istringstream iss(line);
+ string word;
+ sd::SdCard currentSd = sd::SdCard::SLOT_0;
+ while(iss >> word) {
+ if (word == "1:") {
+ currentSd = sd::SdCard::SLOT_1;
+ }
+
+ if(word == "on") {
+ if(currentSd == sd::SdCard::SLOT_0) {
+ active.first = true;
+ }
+ else {
+ active.second = true;
+ }
+ }
+ else if (word == "off") {
+ if(currentSd == sd::SdCard::SLOT_0) {
+ active.first = false;
+ }
+ else {
+ active.second = false;
+ }
+ }
+ else {
+ continue;
+ }
+
+ if(idx > 3) {
+ sif::warning << "SdCardManager::sdCardActive: Status file has more "
+ "than 4 lines!" << std::endl;
+ return STATUS_FILE_FORMAT_INVALID;
+ }
+ }
+ idx++;
+ }
+ return HasReturnvaluesIF::RETURN_OK;
+}
+
+sd::SdCard SdCardManager::getPreferredSdCard() const {
+ //int result = std::system("xsc_scratch read PREFSD > /tmp/pref_sd.txt");
+ return preferredSdCard;
+}
+
+void SdCardManager::setPreferredSdCard(sd::SdCard sdCard) {
+ preferredSdCard = sdCard;
+}
+
+ReturnValue_t SdCardManager::updateSdCardStateFile() {
+ int result = std::system("q7hw sd info all > /tmp/sd_status.txt");
+ if(result == 0) {
+ return HasReturnvaluesIF::RETURN_OK;
+ }
+ sif::warning << "SdCardManager::updateSdCardStateFile: system call failed with code " <<
+ result << std::endl;
+ return HasReturnvaluesIF::RETURN_FAILED;
+}
diff --git a/bsp_q7s/memory/SdCardManager.h b/bsp_q7s/memory/SdCardManager.h
new file mode 100644
index 00000000..0c9c664d
--- /dev/null
+++ b/bsp_q7s/memory/SdCardManager.h
@@ -0,0 +1,94 @@
+#ifndef BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_
+#define BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_
+
+#include "definitions.h"
+#include "returnvalues/classIds.h"
+
+#include "fsfw/returnvalues/HasReturnvaluesIF.h"
+
+#include
+#include
+
+class MutexIF;
+
+/**
+ * @brief Manages handling of SD cards like switching them on or off or getting the current
+ * state
+ */
+class SdCardManager {
+ friend class SdCardAccess;
+public:
+ static constexpr uint8_t INTERFACE_ID = CLASS_ID::SD_CARD_MANAGER;
+
+ static constexpr ReturnValue_t ALREADY_ON = HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 0);
+ static constexpr ReturnValue_t ALREADY_OFF = HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 1);
+ static constexpr ReturnValue_t STATUS_FILE_NEXISTS =
+ HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 2);
+ static constexpr ReturnValue_t STATUS_FILE_FORMAT_INVALID =
+ HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 3);
+ static constexpr ReturnValue_t SYSTEM_CALL_ERROR =
+ HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 4);
+
+ virtual ~SdCardManager();
+
+ static void create();
+
+ /**
+ * Returns the single instance of the SD card manager.
+ */
+ static SdCardManager* instance();
+
+ void setPreferredSdCard(sd::SdCard sdCard);
+
+ sd::SdCard getPreferredSdCard() const;
+
+ /**
+ * Switch on the specified SD card
+ * @param sdCard
+ * @return - RETURN_OK on success, ALREADY_ON if it is already on,
+ * SYSTEM_CALL_ERROR on system error
+ */
+ ReturnValue_t switchOnSdCard(sd::SdCard sdCard);
+
+ /**
+ * Switch off the specified SD card
+ * @param sdCard
+ * @return - RETURN_OK on success, ALREADY_ON if it is already on,
+ * SYSTEM_CALL_ERROR on system error
+ */
+ ReturnValue_t switchOffSdCard(sd::SdCard sdCard);
+
+ /**
+ * Updated the state file or creates one if it does not exist. You need to call this
+ * function before calling #sdCardActiv
+ * @return - RETURN_OK if the state file was updated successfully
+ * - SYSTEM_CALL_ERROR if the call to create the status file failed
+ */
+ ReturnValue_t updateSdCardStateFile();
+
+ /**
+ * Get the state of the SD cards. If the state file does not exist, this function will
+ * take care of updating it. If it does not, the function will use the state file to get
+ * the status of the SD cards and set the field of the provided boolean pair.
+ * @param active Pair of booleans, where the first entry is the state of the first SD card
+ * and the second one the state of the second SD card
+ * @return - RETURN_OK if the state was read successfully
+ * - STATUS_FILE_FORMAT_INVALID if there was an issue with the state file. The user
+ * should call #updateSdCardStateFile again in that case
+ * - STATUS_FILE_NEXISTS if the status file does not exist
+ */
+ ReturnValue_t sdCardActive(std::pair& active);
+
+ sd::SdCard getPreferedSdCard() const;
+
+private:
+ SdCardManager();
+
+ ReturnValue_t setSdCardState(sd::SdCard sdCard, bool on);
+
+ sd::SdCard preferredSdCard = sd::SdCard::SLOT_0;
+
+ static SdCardManager* factoryInstance;
+};
+
+#endif /* BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_ */
diff --git a/bsp_q7s/memory/definitions.h b/bsp_q7s/memory/definitions.h
new file mode 100644
index 00000000..9a998dcc
--- /dev/null
+++ b/bsp_q7s/memory/definitions.h
@@ -0,0 +1,16 @@
+#ifndef BSP_Q7S_MEMORY_DEFINITIONS_H_
+#define BSP_Q7S_MEMORY_DEFINITIONS_H_
+
+namespace sd {
+
+enum SdCard {
+ SLOT_0,
+ SLOT_1,
+ BOTH
+};
+
+}
+
+
+
+#endif /* BSP_Q7S_MEMORY_DEFINITIONS_H_ */
diff --git a/bsp_q7s/memory/scratchApi.cpp b/bsp_q7s/memory/scratchApi.cpp
new file mode 100644
index 00000000..0b159775
--- /dev/null
+++ b/bsp_q7s/memory/scratchApi.cpp
@@ -0,0 +1,12 @@
+#include "scratchApi.h"
+
+ReturnValue_t scratch::writeString(std::string name, std::string string) {
+ std::ostringstream oss;
+ oss << "xsc_scratch write " << name << " \"" << string << "\"";
+ int result = std::system(oss.str().c_str());
+ if(result != 0) {
+ utility::handleSystemError(result, "scratch::String");
+ return HasReturnvaluesIF::RETURN_FAILED;
+ }
+ return HasReturnvaluesIF::RETURN_OK;
+}
diff --git a/bsp_q7s/memory/scratchApi.h b/bsp_q7s/memory/scratchApi.h
new file mode 100644
index 00000000..09bf6bab
--- /dev/null
+++ b/bsp_q7s/memory/scratchApi.h
@@ -0,0 +1,70 @@
+#ifndef BSP_Q7S_MEMORY_SCRATCHAPI_H_
+#define BSP_Q7S_MEMORY_SCRATCHAPI_H_
+
+#include "fsfw/returnvalues/HasReturnvaluesIF.h"
+#include "fsfw/serviceinterface/ServiceInterface.h"
+#include "linux/utility/utility.h"
+
+#include
+#include
+#include
+#include
+#include
+
+/**
+ * @brief API for the scratch buffer
+ */
+namespace scratch {
+
+namespace {
+static uint8_t counter = 0;
+}
+
+template::value>::type>
+inline ReturnValue_t writeNumber(std::string name, T num) noexcept {
+ std::ostringstream oss;
+ oss << "xsc_scratch write " << name << " " << num;
+ int result = std::system(oss.str().c_str());
+ if(result != 0) {
+ utility::handleSystemError(result, "scratch::writeNumber");
+ return HasReturnvaluesIF::RETURN_FAILED;
+ }
+ return HasReturnvaluesIF::RETURN_OK;
+}
+
+template::value>::type>
+inline ReturnValue_t readNumber(std::string name, T& num) noexcept {
+ using namespace std;
+ string filename = "/tmp/sro" + std::to_string(counter++);
+ ostringstream oss;
+ oss << "xsc_scratch read " << name << " > " << filename;
+
+ int result = std::system(oss.str().c_str());
+ if(result != 0) {
+ utility::handleSystemError(result, "scratch::writeNumber");
+ return HasReturnvaluesIF::RETURN_FAILED;
+ }
+ ifstream file(filename);
+ string line;
+ if (not std::getline(file, line)) {
+ return HasReturnvaluesIF::RETURN_FAILED;
+ }
+
+ size_t pos = line.find("=");
+ std::string valueAsString = line.substr(pos + 1);
+ try {
+ num = std::stoi(valueAsString);
+ }
+ catch(std::invalid_argument& e) {
+ sif::warning << "scratch::readNumber: stoi call failed with " << e.what() << std::endl;
+ }
+
+ std::remove(filename.c_str());
+ return HasReturnvaluesIF::RETURN_OK;
+}
+
+ReturnValue_t writeString(std::string name, std::string string);
+
+}
+
+#endif /* BSP_Q7S_MEMORY_SCRATCHAPI_H_ */
diff --git a/bsp_q7s/simple/simple.cpp b/bsp_q7s/simple/simple.cpp
index 6261bfe3..a6bb9fdf 100644
--- a/bsp_q7s/simple/simple.cpp
+++ b/bsp_q7s/simple/simple.cpp
@@ -1,5 +1,17 @@
#include "simple.h"
+#include "q7sConfig.h"
+
+#if Q7S_SIMPLE_ADD_FILE_SYSTEM_TEST == 1
+#include "../boardtest/FileSystemTest.h"
+#endif
int simple::simple() {
+ cout << "-- Q7S Simple Application --" << endl;
+#if Q7S_SIMPLE_ADD_FILE_SYSTEM_TEST == 1
+ {
+ FileSystemTest fileSystemTest;
+ }
+#endif
return 0;
}
+
diff --git a/cmake/scripts/Linux/create_cmake_debug_cfg.sh b/cmake/scripts/Linux/make_debug_cfg.sh
similarity index 99%
rename from cmake/scripts/Linux/create_cmake_debug_cfg.sh
rename to cmake/scripts/Linux/make_debug_cfg.sh
index 8c626bf4..dc21896d 100755
--- a/cmake/scripts/Linux/create_cmake_debug_cfg.sh
+++ b/cmake/scripts/Linux/make_debug_cfg.sh
@@ -29,3 +29,4 @@ set -x # Print command
${python} cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug" -l "${builddir}"
# Use this if commands are added which should not be printed
# set +x
+
diff --git a/cmake/scripts/Linux/create_cmake_release_cfg.sh b/cmake/scripts/Linux/make_release_cfg.sh
similarity index 100%
rename from cmake/scripts/Linux/create_cmake_release_cfg.sh
rename to cmake/scripts/Linux/make_release_cfg.sh
diff --git a/cmake/scripts/Linux/ninja_debug_cfg.sh b/cmake/scripts/Linux/ninja_debug_cfg.sh
new file mode 100755
index 00000000..9627ccf6
--- /dev/null
+++ b/cmake/scripts/Linux/ninja_debug_cfg.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+counter=0
+while [ ${counter} -lt 5 ]
+do
+ cd ..
+ if [ -f "cmake_build_config.py" ];then
+ break
+ fi
+ counter=$((counter=counter + 1))
+done
+
+if [ "${counter}" -ge 5 ];then
+ echo "create_cmake_cfg.sh not found in upper directories!"
+ exit 1
+fi
+
+build_generator="Ninja"
+os_fsfw="linux"
+builddir="build-Debug-Host"
+if [ "${OS}" = "Windows_NT" ]; then
+ python="py"
+# Could be other OS but this works for now.
+else
+ python="python3"
+fi
+
+echo "Running command (without the leading +):"
+set -x # Print command
+${python} cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug" -l "${builddir}"
+# Use this if commands are added which should not be printed
+# set +x
+
diff --git a/cmake/scripts/Q7S/simple/simple_make_debug_cfg.sh b/cmake/scripts/Q7S/simple/simple_make_debug_cfg.sh
index b692184a..8a6c7b3f 100755
--- a/cmake/scripts/Q7S/simple/simple_make_debug_cfg.sh
+++ b/cmake/scripts/Q7S/simple/simple_make_debug_cfg.sh
@@ -31,5 +31,5 @@ fi
echo "Running command (without the leading +):"
set -x # Print command
${python} cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug" -t "${tgt_bsp}" \
- -l"${build_dir}" -d "${definitions}"
+ -l "${build_dir}" -d "${definitions}"
# set +x
diff --git a/cmake/scripts/Q7S/simple/simple_ninja_debug_cfg.sh b/cmake/scripts/Q7S/simple/simple_ninja_debug_cfg.sh
index a3a55521..965aae45 100755
--- a/cmake/scripts/Q7S/simple/simple_ninja_debug_cfg.sh
+++ b/cmake/scripts/Q7S/simple/simple_ninja_debug_cfg.sh
@@ -29,6 +29,6 @@ fi
echo "Running command (without the leading +):"
set -x # Print command
${python} cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug" -t "${tgt_bsp}" \
- -l"${build_dir}" -d "${definitions}"
+ -l "${build_dir}" -d "${definitions}"
# set +x
diff --git a/cmake/scripts/cmake_build_config.py b/cmake/scripts/cmake_build_config.py
old mode 100644
new mode 100755
diff --git a/common/config/OBSWVersion.h b/common/config/OBSWVersion.h
index 7ac812e6..b796f146 100644
--- a/common/config/OBSWVersion.h
+++ b/common/config/OBSWVersion.h
@@ -4,7 +4,7 @@
const char* const SW_NAME = "eive";
#define SW_VERSION 1
-#define SW_SUBVERSION 2
+#define SW_SUBVERSION 3
#define SW_SUBSUBVERSION 0
#endif /* COMMON_CONFIG_OBSWVERSION_H_ */
diff --git a/doc/img/ProcessSettings.png b/doc/img/ProcessSettings.png
new file mode 100644
index 00000000..5a8c3c99
Binary files /dev/null and b/doc/img/ProcessSettings.png differ
diff --git a/fsfw b/fsfw
index 38f2f69c..eef2fd3b 160000
--- a/fsfw
+++ b/fsfw
@@ -1 +1 @@
-Subproject commit 38f2f69c784c74cd87a10dce6c968325cf1cb472
+Subproject commit eef2fd3b7ac764f06ed5d9a3c97c894d92a515fa
diff --git a/fsfw_hal b/fsfw_hal
index 2e243e3b..8ff09c95 160000
--- a/fsfw_hal
+++ b/fsfw_hal
@@ -1 +1 @@
-Subproject commit 2e243e3b294870b0c93f85c6b8ff0c74f4f9cce7
+Subproject commit 8ff09c95a69f1f43fec6104d6cce1e788b2b870d
diff --git a/linux/csp/CspComIF.cpp b/linux/csp/CspComIF.cpp
index a8f13963..07fe63d3 100644
--- a/linux/csp/CspComIF.cpp
+++ b/linux/csp/CspComIF.cpp
@@ -24,6 +24,8 @@ ReturnValue_t CspComIF::initializeInterface(CookieIF *cookie) {
/* Perform CAN and CSP initialization only once */
if(cspDeviceMap.empty()){
+ sif::info << "Performing " << canInterface << " initialization.." << std::endl;
+
/* Define the memory to allocate for the CSP stack */
int buf_count = 10;
int buf_size = 300;
@@ -57,6 +59,7 @@ ReturnValue_t CspComIF::initializeInterface(CookieIF *cookie) {
sif::error << "Failed to start csp route task" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
+ sif::info << canInterface << " initialized successfully" << std::endl;
}
uint8_t cspAddress = cspCookie->getCspAddress();
diff --git a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp
index 4b201f2b..a213ca06 100644
--- a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp
+++ b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp
@@ -453,7 +453,7 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) {
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
-#if OBSW_ADD_GPS == 1
+#if OBSW_ADD_ACS_BOARD == 1
thisSequence->addSlot(objects::GPS0_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GPS1_HANDLER, length * 0,
@@ -464,7 +464,7 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) {
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.2,
DeviceHandlerIF::SEND_WRITE);
-#if OBSW_ADD_GPS == 1
+#if OBSW_ADD_ACS_BOARD == 1
thisSequence->addSlot(objects::GPS0_HANDLER, length * 0.2,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GPS1_HANDLER, length * 0.2,
@@ -475,7 +475,7 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) {
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.4,
DeviceHandlerIF::GET_WRITE);
-#if OBSW_ADD_GPS == 1
+#if OBSW_ADD_ACS_BOARD == 1
thisSequence->addSlot(objects::GPS0_HANDLER, length * 0.4,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GPS1_HANDLER, length * 0.4,
@@ -486,7 +486,7 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) {
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.6,
DeviceHandlerIF::SEND_READ);
-#if OBSW_ADD_GPS == 1
+#if OBSW_ADD_ACS_BOARD == 1
thisSequence->addSlot(objects::GPS0_HANDLER, length * 0.6,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GPS1_HANDLER, length * 0.6,
@@ -497,7 +497,7 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) {
DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.8,
DeviceHandlerIF::GET_READ);
-#if OBSW_ADD_GPS == 1
+#if OBSW_ADD_ACS_BOARD == 1
thisSequence->addSlot(objects::GPS0_HANDLER, length * 0.8,
DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::GPS1_HANDLER, length * 0.8,
diff --git a/linux/fsfwconfig/returnvalues/classIds.h b/linux/fsfwconfig/returnvalues/classIds.h
index d1bfe7e2..79f1a175 100644
--- a/linux/fsfwconfig/returnvalues/classIds.h
+++ b/linux/fsfwconfig/returnvalues/classIds.h
@@ -13,6 +13,7 @@ namespace CLASS_ID {
enum {
CLASS_ID_START = COMMON_CLASS_ID_END,
SA_DEPL_HANDLER, //SADPL
+ SD_CARD_MANAGER, //SDMA
CLASS_ID_END // [EXPORT] : [END]
};
}
diff --git a/linux/utility/CMakeLists.txt b/linux/utility/CMakeLists.txt
index 45a7edcc..a3387531 100644
--- a/linux/utility/CMakeLists.txt
+++ b/linux/utility/CMakeLists.txt
@@ -1,4 +1,5 @@
target_sources(${TARGET_NAME} PUBLIC
+ utility.cpp
)
diff --git a/linux/utility/utility.cpp b/linux/utility/utility.cpp
new file mode 100644
index 00000000..69a3d08f
--- /dev/null
+++ b/linux/utility/utility.cpp
@@ -0,0 +1,11 @@
+#include "OBSWConfig.h"
+#include "FSFWConfig.h"
+#include "utility.h"
+
+#include "fsfw/serviceinterface/ServiceInterface.h"
+
+void utility::handleSystemError(int retcode, std::string function) {
+#if OBSW_VERBOSE_LEVEL >= 1
+ sif::warning << function << ": System call failed with code " << retcode;
+#endif
+}
diff --git a/linux/utility/utility.h b/linux/utility/utility.h
new file mode 100644
index 00000000..3eb17a9b
--- /dev/null
+++ b/linux/utility/utility.h
@@ -0,0 +1,13 @@
+#ifndef LINUX_UTILITY_UTILITY_H_
+#define LINUX_UTILITY_UTILITY_H_
+
+#include "fsfw/returnvalues/HasReturnvaluesIF.h"
+#include
+
+namespace utility {
+
+void handleSystemError(int retcode, std::string function);
+
+}
+
+#endif /* LINUX_UTILITY_UTILITY_H_ */
diff --git a/misc/eclipse/.cproject b/misc/eclipse/.cproject
index a562e7b2..16bd992b 100644
--- a/misc/eclipse/.cproject
+++ b/misc/eclipse/.cproject
@@ -19,25 +19,25 @@
-
+
-
+
@@ -77,19 +77,23 @@
-
+
@@ -127,7 +131,7 @@
-
+