diff --git a/README.md b/README.md
index 26adb303..fc218749 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,25 @@
+
+
EIVE On-Board Software
======
-# General information
+# Index
+
+1. [General](#general)
+2. [Prerequisites](#prereq)
+3. [Building the Software](#build)
+4. [Useful and Common Host Commands](#host-commands)
+5. [Setting up Prerequisites](#set-up-prereq)
+6. [Remote Debugging](#remote-debugging)
+7. [Direct Debugging](#direct-debugging)
+8. [Transfering Files to the Q7S](#file-transfer)
+9. [Q7S OBC](#q7s)
+10. [Static Code Analysis](#static-code-analysis)
+11. [Eclipse](#eclipse)
+12. [Running the OBSW on a Raspberry Pi](#rpi)
+13. [FSFW](#fsfw)
+
+# General information
Target systems:
@@ -36,16 +54,210 @@ 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
+# Prerequisites
-## Installing Vivado the the Xilinx development tools
+There is a separate [prerequisites](#set-up-prereq) which specifies how to set up all
+prerequisites.
+
+## Building the OBSW and flashing it on the Q7S
+
+1. ARM cross-compiler installed, either as part of [Vivado 2018.2 installation](#vivado) or
+ as a [separate download](#arm-toolchain)
+2. [Q7S sysroot](#q7s-sysroot) on local development machine
+3. Recommended: Eclipse or [Vivado 2018.2 SDK](#vivado) for OBSW development
+3. [TCF agent] running on Q7S
+
+## Hardware Design
+
+1. [Vivado 2018.2](#vivado) for programmable logic design
+
+# Building the software
+
+## CMake
+
+When using Windows, run theses steps in MSYS2.
+
+1. Clone the repository with
+
+ ```sh
+ git clone https://egit.irs.uni-stuttgart.de/eive/eive_obsw.git
+ ```
+
+2. Update all the submodules
+
+ ```sh
+ git submodule init
+ git submodule sync
+ git submodule update
+ ```
+
+3. Ensure that the cross-compiler is working with `arm-linux-gnueabihf-gcc --version`.
+ It is recommended to set up a shell script which takes care of setting up the environment
+ for convenience or to set up the
+ [PATH and the CROSS_COMPILE variable permanently](https://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path)
+ in the `.profile` file.
+
+4. Run the CMake configuration to create the build system in a `build-Debug-Q7S` folder.
+ Add `-G "MinGW Makefiles` in MinGW64 on Windows.
+
+ ```sh
+ mkdir build-Debug-Q7S && cd build-Debug-Q7S
+ cmake -DTGT_BSP="arm/q7s" -DCMAKE_BUILD_TYPE=Debug -DOS_FSFW=linux ..
+ cmake --build . -j
+ ```
+
+ You can also use provided shell scripts to perform these commands
+
+ ```sh
+ cd cmake/scripts/Q7S
+ ./make_debug_cfg.sh
+ cd ../../..
+ ```
+
+ This will invoke a Python script which in turn invokes CMake with the correct
+ arguments to configure CMake for Q7S cross-compilation.
+
+ You can build the hosted variant of the OBSW by replacing `-DOS_FSFW=linux` with
+ `-DOS_FSFW=host`. There are also different values for `-DTGT_BSP` to build for the Raspberry Pi
+ or the Beagle Bone Black: `arm/raspberrypi` and `arm/beagleboneblack`.
+
+5. Build the software with
+ ```sh
+ cd build-Debug-Q7S
+ cmake --build . -j
+ ```
+
+## Building in Xilinx SDK 2018.2
+
+1. Open Xilinx SDK 2018.2
+2. Import project
+ * File → Import → C/C++ → Existing Code as Makefile Project
+3. Set build command. Replace \ with either debug or release.
+ * When on Linux right click project → Properties → C/C++ Build → Set build command to `make -j`
+ * -j causes the compiler to use all available cores
+ * The target is used to either compile the debug or the optimized release build.
+ * On windows create a make target additionally (Windows → Show View → Make Target)
+ * Right click eive_obsw → New
+ * Target name: all
+ * Uncheck "Same as the target name"
+ * Uncheck "Use builder settings"
+ * As build command type: `cmake --build .`
+ * In the Behaviour tab, you can enable build acceleration
+4. Run build command by double clicking the created target or by right clicking
+ the project folder and selecting Build Project.
+
+# Useful and Common Commands (Host)
+
+## Connect to EIVE flatsat
+
+### DNS
+
+```sh
+ssh eive@flatsat.eive.absatvirt.lw
+```
+
+### IPv6
+```sh
+ssh eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5
+```
+
+### IPv4
+
+```sh
+ssh eive@192.168.199.227
+```
+
+## Connecting to the serial console or ssh console
+
+A serial console session is up permanently in a `tmux` session
+
+### Serial console
+
+You can check whether the sessions exist with `tmux ls`
+
+```sh
+tmux a -t q7s-serial
+```
+
+If the session does not exist, you can create it like this
+
+```sh
+tmux new -s q7s-serial
+/bin/bash
+q7s_serial
+```
+
+### SSH console
+
+You can use the following command to connect to the Q7S with `ssh`:
+
+```sh
+q7s_ssh
+```
+
+## Port forwarding for connection to TCF agent
+
+This is a required step to connect to the `tcf-agent` on the Q7S, which is required for convenient
+remote debugging. Assuming the IPv6
+
+```sh
+ssh -L 1534:192.168.133.10:1534 eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 -t /bin/bash
+```
+
+You then need to connect to `localhost` with port `1534`.
+
+## Port forwarding for file transfers with `scp`
+
+```sh
+ssh -L 1535:192.168.133.10:22 eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 -t /bin/bash
+```
+
+You then need to run `scp` with the `-P 1535` flag with `localhost` as the target IP address.
+
+## Port forwarding for TMTC commanding
+
+If you are using the UDP communication interface, you can use:
+
+```sh
+ssh -L 1536:192.168.133.10:7301 eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 -t /bin/bash
+```
+
+This forwards UDP TMTC packets on port `1536` of localhost to the TMTC reception port of the Q7S.
+
+For TCP, you can use
+
+```sh
+ssh -L 1537:192.168.133.10:7303 eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 -t /bin/bash
+```
+
+This forwards TCP TMTC packets on port `1537` of localhost to the TMTC reception port of the Q7S.
+
+## Set up all port forwarding at once
+
+You can specify the `-L` option multiple times to set up all port forwarding at once.
+Example for using the UDP communication interface:
+
+```sh
+ssh -L 1534:192.168.133.10:1534 \
+ -L 1535:192.168.133.10:22 \
+ -L 1536:192.168.133.10:7301 \
+ eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 \
+ -t 'export CONSOLE_PREFIX="[Q7S Tunnel] /bin/bash'
+```
+
+There is also a shell script called `q7s-port.sh` which can be used to achieve the same.
+
+# Setting up prerequisites
+
+## 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. 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 Vivado 2018.2 and
+ [Xilinx SDK](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.
@@ -85,7 +297,7 @@ 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
+## 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).
@@ -136,7 +348,7 @@ wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/2Fp2ag6NGnbtAsK/downloa
sudo apt-get install cmake
````
-## Getting the Q7S system root
+## Getting the Q7S system root
It is necessary to copy the Q7S system root to your local development machine for libraries
like `libgpio`. You can find the system root for the Q7S, the Raspberry Pi and the
@@ -151,102 +363,58 @@ 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
+## Setting up UNIX environment for real-time functionalities
-When using Windows, run theses steps in MSYS2.
+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.
-1. Clone the repository with
+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
- git clone https://egit.irs.uni-stuttgart.de/eive/eive_obsw.git
+ sudo nano /etc/sysctl.conf
```
-2. Update all the submodules
-
+ Append at end:
```sh
- git submodule init
- git submodule sync
- git submodule update
- ```
-
-3. Ensure that the cross-compiler is working with `arm-linux-gnueabihf-gcc --version`.
- It is recommended to run the shell script `win_path_helper_xilinx_tools.sh` in `cmake/scripts/Q7S`
- or to set up the [PATH and the CROSS_COMPILE variable permanently](https://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path)
- in the `.profile` file.
-
-4. Run the CMake configuration to create the build system in a `build-Debug-Q7S` folder.
- Add `-G "MinGW Makefiles` in MinGW64 on Windows.
-
- ```sh
- mkdir build-Debug-Q7S && cd build-Debug-Q7S
- cmake -DTGT_BSP="arm/q7s" -DCMAKE_BUILD_TYPE=Debug -DOS_FSFW=linux ..
- cmake --build . -j
- ```
-
- You can also use provided shell scripts to perform these commands
-
- ```sh
- cd cmake/scripts/Q7S
- ./make_debug_cfg.sh
- cd ../../..
- ```
-
- This will invoke a Python script which in turn invokes CMake with the correct
- arguments to configure CMake for Q7S cross-compilation.
-
- You can build the hosted variant of the OBSW by replacing `-DOS_FSFW=linux` with
- `-DOS_FSFW=host`. There are also different values for `-DTGT_BSP` to build for the Raspberry Pi
- or the Beagle Bone Black: `arm/raspberrypi` and `arm/beagleboneblack`.
-
-5. Build the software with
- ```sh
- cd Debug
- cmake --build . -j
+ fs/mqueue/msg_max =
```
-## Setting up default Eclipse for Q7S projects - TCF agent
+ Apply changes with:
+ ```sh
+ sudo sysctl -p
+ ```
-The [TCF agent](https://wiki.eclipse.org/TCF) can be used to perform remote debugging on the Q7S.
+ A possible solution which only persists for the current session is
+ ```sh
+ echo | sudo tee /proc/sys/fs/mqueue/msg_max
+ ```
-1. Install the TCF agent plugin in Eclipse from the [releases](https://www.eclipse.org/tcf/downloads.php). Go to Help → Install New Software and use the download page, for example https://download.eclipse.org/tools/tcf/releases/1.6/1.6.2/ to search for the plugin and install it.
+## TCF-Agent
-2. Go to Window → Perspective → Open Perspective and open the **Target Explorer Perspective**.
- Here, the Q7S should show up if the local port forwarding was set up as explained previously. Please note that you have to connect to `localhost` and port `1534` with port forwaring set up.
-
-3. A launch configuration was provided, but it might be necessary to adapt it for your own needs. Alternatively:
-
- - Create a new **TCF Remote Application** by pressing the cogs button at the top or going to Run → Debug Configurations → Remote Application and creating a new one there.
-
- - Set up the correct image in the main tab (it might be necessary to send the image to the Q7S manually once) and file transfer properties
-
- - It is also recommended to link the correct Eclipse project.
-
-After that, comfortable remote debugging should be possible with the Debug button.
-
-A build configuration and a shell helper script has been provided to set up the path variables and
-build the Q7S binary on Windows, but a launch configuration needs to be newly created because the
-IP address and path settings differ from machine to machine.
-
-## Building in Xilinx SDK 2018.2
-
-1. Open Xilinx SDK 2018.2
-2. Import project
- * File → Import → C/C++ → Existing Code as Makefile Project
-3. Set build command. Replace \ with either debug or release.
- * When on Linux right click project → Properties → C/C++ Build → Set build command to `make -j`
- * -j causes the compiler to use all available cores
- * The target is used to either compile the debug or the optimized release build.
- * On windows create a make target additionally (Windows → Show View → Make Target)
- * Right click eive_obsw → New
- * Target name: all
- * Uncheck "Same as the target name"
- * Uncheck "Use builder settings"
- * As build command type: `cmake --build .`
- * In the Behaviour tab, you can enable build acceleration
-4. Run build command by double clicking the created target or by right clicking
- the project folder and selecting Build Project.
-
-## TCF-Agent
+Most of the steps specified here were already automated
1. On reboot, some steps have to be taken on the Q7S. Set static IP address and netmask
@@ -264,7 +432,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
+# Remote Debugging
Open SSH connection to flatsat PC:
@@ -298,6 +466,7 @@ console of the Q7S like this to set it
picocom -b 115200 /dev/ttyUSB0
```
+The flatsat has the aliases and shell scripts `q7s_ssh` and `q7s_serial` for this task as well.
If the serial port is blocked for some reason, you can kill
the process using it with `q7s_kill`.
@@ -325,13 +494,68 @@ 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 needs to be done every time, so it is recommended to create an alias to do this quickly.
+192.168.133.10. This needs to be done every time, so it is recommended to create an
+alias or shell script to do this quickly.
Note: When now setting up a debug session in the Xilinx SDK or Eclipse, the host must be set
to localhost instead of the IP address of the Q7S.
-# Transfering files via SCP
+# Direct Debugging
+
+1. Assign static IP address to Q7S
+ * 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
+ * pw: root
+
+2. Connect Q7S to workstation via ethernet
+3. Make sure the netmask of the ehternet interface of the workstation matches the netmask of the Q7S
+ * When IP address is set to 192.168.133.10 and the netmask is 255.255.255.0, an example IP address for the workstation
+ is 192.168.133.2
+
+4. Run tcf-agent on Q7S
+
+ * Tcf-agent is not yet integrated in the rootfs of the Q7S. Therefore build tcf-agent manually
+
+ ```sh
+ git clone git://git.eclipse.org/gitroot/tcf/org.eclipse.tcf.agent.git
+ cd org.eclipse.tcf.agent/agent
+ make CC=arm-linux-gnueabihf-gcc LD=arm-linux-gnueabihf-ld MACHINE=arm NO_SSL=1 NO_UUID=1
+ ```
+
+ * Transfer executable agent from org.eclipse.tcf.agent/agent/obj/GNU/Linux/arm/Debug to /tmp of Q7S
+
+ ```sh
+ cd obj/GNU/Linux/arm/Debug
+ scp agent root@192.168.133.10:/tmp
+ ```
+
+ * On Q7S
+ ```sh
+ cd /tmp
+ chmod +x agent
+ ```
+
+ * Run agent
+ ```sh
+ ./agent
+ ```
+
+5. In Xilinx SDK 2018.2 right click on project → Debug As → Debug Configurations
+6. Right click Xilinx C/C++ applicaton (System Debugger) → New →
+7. Set Debug Type to Linux Application Debug and Connectin to Linux Agent
+8. Click New
+9. Give connection a name
+10. Set Host to static IP address of Q7S. e.g. 192.168.133.10
+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`
+
+# Transfering Files to the Q7S
To transfer files from the local machine to the Q7S, use port forwarding
@@ -355,7 +579,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
+More detailed information about the used q7s commands can be found in the Q7S user manual.
+
+# Q7S
+
+## 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.
@@ -420,58 +648,7 @@ creating directories. To do this, the parition needs to be mounted.
systemctl status example
```
-More detailed information about the used q7s commands can be found in the Q7S user manual.
-
-## 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
- ```
-
-# PCDU
+## PCDU
Connect to serial console of P60 Dock
````
@@ -496,102 +673,6 @@ p60-dock # param get out_en[0]
GET out_en[0] = 1
````
-# 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
- manual chapter 10.3)
- * Baudrate 115200
- * Login to Q7S:
- * user: root
- * pw: root
-
-2. Connect Q7S to workstation via ethernet
-3. Make sure the netmask of the ehternet interface of the workstation matches the netmask of the Q7S
- * When IP address is set to 192.168.133.10 and the netmask is 255.255.255.0, an example IP address for the workstation
- is 192.168.133.2
-
-4. Run tcf-agent on Q7S
-
- * Tcf-agent is not yet integrated in the rootfs of the Q7S. Therefore build tcf-agent manually
-
- ```sh
- git clone git://git.eclipse.org/gitroot/tcf/org.eclipse.tcf.agent.git
- cd org.eclipse.tcf.agent/agent
- make CC=arm-linux-gnueabihf-gcc LD=arm-linux-gnueabihf-ld MACHINE=arm NO_SSL=1 NO_UUID=1
- ```
-
- * Transfer executable agent from org.eclipse.tcf.agent/agent/obj/GNU/Linux/arm/Debug to /tmp of Q7S
-
- ```sh
- cd obj/GNU/Linux/arm/Debug
- scp agent root@192.168.133.10:/tmp
- ```
-
- * On Q7S
- ```sh
- cd /tmp
- chmod +x agent
- ```
-
- * Run agent
- ```sh
- ./agent
- ```
-
-5. In Xilinx SDK 2018.2 right click on project → Debug As → Debug Configurations
-6. Right click Xilinx C/C++ applicaton (System Debugger) → New →
-7. Set Debug Type to Linux Application Debug and Connectin to Linux Agent
-8. Click New
-9. Give connection a name
-10. Set Host to static IP address of Q7S. e.g. 192.168.133.10
-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`
-
-# 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.
-
-```sh
-pacman -S mingw-w64-x86_64-cppcheck
-```
-
-On Ubuntu, install with
-
-```sh
-sudo apt-get install cppcheck
-```
-
-You can use the Eclipse integration or you can perform the scanning manually from the command line.
-CMake will be used for this.
-
-Run the CMake build generation commands specified above but supply
-`-DCMAKE_EXPORT_COMPILE_COMMANDS=ON` to the build generation. Invoking the build command will
-generate a `compile_commands.json` file which can be used by cppcheck.
-
-```sh
-cppcheck --project=compile_commands.json --xml 2> report.xml
-```
-
-Finally, you can convert the generated `.xml` file to HTML with the following command
-
-```sh
-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
-
## Core commands
Display currently running image:
@@ -773,7 +854,10 @@ EIVE implementation
- Mount point `/mnt/sd0` created for SD card 0. Created with `mkdir`
- Mount point `/mnt/sd1` created for SD card 1. Created with `mkdir`
- Folder `scripts` in `/home/root` folder.
-- `scripts` folder currently contains `update_main_components.sh` script
+- `scripts` folder currently contains a few shell helper scripts
+- Folder `profile.d` in `/etc` folder which contains the `path-set.sh` script
+ which is sourced at software startup
+- Library `libwire.so` in `/usr/lib` folder
### SD Cards
@@ -783,7 +867,76 @@ EIVE implementation
- Folder `tm` for telemetry
- Folder `xdi` for XDI components (e.g. for firmware or device tree updates)
-# Running the EIVE OBSW on a Raspberry Pi
+# 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.
+
+```sh
+pacman -S mingw-w64-x86_64-cppcheck
+```
+
+On Ubuntu, install with
+
+```sh
+sudo apt-get install cppcheck
+```
+
+You can use the Eclipse integration or you can perform the scanning manually from the command line.
+CMake will be used for this.
+
+Run the CMake build generation commands specified above but supply
+`-DCMAKE_EXPORT_COMPILE_COMMANDS=ON` to the build generation. Invoking the build command will
+generate a `compile_commands.json` file which can be used by cppcheck.
+
+```sh
+cppcheck --project=compile_commands.json --xml 2> report.xml
+```
+
+Finally, you can convert the generated `.xml` file to HTML with the following command
+
+```sh
+cppcheck-htmlreport --file=report.xml --report-dir=cppcheck --source-dir=..
+```
+
+# 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.
+
+## Setting up default Eclipse for Q7S projects - TCF agent
+
+The [TCF agent](https://wiki.eclipse.org/TCF) can be used to perform remote debugging on the Q7S.
+
+1. Install the TCF agent plugin in Eclipse from
+ the [releases](https://www.eclipse.org/tcf/downloads.php). Go to
+ Help → Install New Software and use the download page, for
+ example https://download.eclipse.org/tools/tcf/releases/1.6/1.6.2/ to search for the plugin and install it.
+
+2. Go to Window → Perspective → Open Perspective and open the **Target Explorer Perspective**.
+ Here, the Q7S should show up if the local port forwarding was set up as explained previously.
+ Please note that you have to connect to `localhost` and port `1534` with port forwaring set up.
+
+3. A launch configuration was provided, but it might be necessary to adapt it for your own needs.
+ Alternatively:
+
+ - Create a new **TCF Remote Application** by pressing the cogs button at the top or going to
+ Run → Debug Configurations → Remote Application and creating a new one there.
+
+ - Set up the correct image in the main tab (it might be necessary to send the image to the
+ Q7S manually once) and file transfer properties
+
+ - It is also recommended to link the correct Eclipse project.
+
+After that, comfortable remote debugging should be possible with the Debug button.
+
+A build configuration and a shell helper script has been provided to set up the path variables and
+build the Q7S binary on Windows, but a launch configuration needs to be newly created because the
+IP address and path settings differ from machine to machine.
+
+# 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.
@@ -799,7 +952,7 @@ sudo apt-get install gpiod libgpiod-dev
to install the required GPIO libraries before cloning the system root folder.
-# Flight Software Framework (FSFW)
+# Flight Software Framework (FSFW)
An EIVE fork of the FSFW is submodules into this repository.
To add the master upstream branch and merge changes and updates from it
@@ -816,4 +969,5 @@ After that, an update can be merged by running
git merge upstream/master
```
-Alternatively, changes from other upstreams (forks) and branches can be merged like that in the same way.
+Alternatively, changes from other upstreams (forks) and branches can be merged like that
+in the same way.
diff --git a/bsp_hosted/InitMission.cpp b/bsp_hosted/InitMission.cpp
index 2743aa36..8ef40d06 100644
--- a/bsp_hosted/InitMission.cpp
+++ b/bsp_hosted/InitMission.cpp
@@ -72,13 +72,13 @@ void initmission::initTasks() {
/* UDP bridge */
PeriodicTaskIF* udpBridgeTask = factory->createPeriodicTask(
"UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
- result = udpBridgeTask->addComponent(objects::UDP_BRIDGE);
+ result = udpBridgeTask->addComponent(objects::TMTC_BRIDGE);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Unix Bridge failed" << std::endl;
}
PeriodicTaskIF* udpPollingTask = factory->createPeriodicTask(
"UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
- result = udpPollingTask->addComponent(objects::UDP_POLLING_TASK);
+ result = udpPollingTask->addComponent(objects::TMTC_POLLING_TASK);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Polling failed" << std::endl;
}
diff --git a/bsp_hosted/ObjectFactory.cpp b/bsp_hosted/ObjectFactory.cpp
index acc0be37..0933df5b 100644
--- a/bsp_hosted/ObjectFactory.cpp
+++ b/bsp_hosted/ObjectFactory.cpp
@@ -28,7 +28,7 @@ void Factory::setStaticFrameworkObjectIds(){
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
- TmFunnel::downlinkDestination = objects::UDP_BRIDGE;
+ TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
// No storage object for now.
TmFunnel::storageDestination = objects::NO_OBJECT;
@@ -40,7 +40,7 @@ void ObjectFactory::produce(void* args){
Factory::setStaticFrameworkObjectIds();
ObjectFactory::produceGenericObjects();
- new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
- new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
+ new UdpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
+ new UdpTcPollingTask(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE);
}
diff --git a/bsp_linux_board/InitMission.cpp b/bsp_linux_board/InitMission.cpp
index 9e7abd94..68423216 100644
--- a/bsp_linux_board/InitMission.cpp
+++ b/bsp_linux_board/InitMission.cpp
@@ -66,13 +66,13 @@ void initmission::initTasks() {
/* UDP bridge */
PeriodicTaskIF* udpBridgeTask = factory->createPeriodicTask(
"UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
- result = udpBridgeTask->addComponent(objects::UDP_BRIDGE);
+ result = udpBridgeTask->addComponent(objects::TMTC_BRIDGE);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Unix Bridge failed" << std::endl;
}
PeriodicTaskIF* udpPollingTask = factory->createPeriodicTask(
"UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
- result = udpPollingTask->addComponent(objects::UDP_POLLING_TASK);
+ result = udpPollingTask->addComponent(objects::TMTC_POLLING_TASK);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Polling failed" << std::endl;
}
diff --git a/bsp_linux_board/ObjectFactory.cpp b/bsp_linux_board/ObjectFactory.cpp
index 4f7dd59a..0d3e8ce5 100644
--- a/bsp_linux_board/ObjectFactory.cpp
+++ b/bsp_linux_board/ObjectFactory.cpp
@@ -45,7 +45,7 @@ void Factory::setStaticFrameworkObjectIds() {
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
- TmFunnel::downlinkDestination = objects::UDP_BRIDGE;
+ TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
// No storage object for now.
TmFunnel::storageDestination = objects::NO_OBJECT;
@@ -59,8 +59,8 @@ void ObjectFactory::produce(void* args){
Factory::setStaticFrameworkObjectIds();
ObjectFactory::produceGenericObjects();
- new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
- new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
+ new UdpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
+ new UdpTcPollingTask(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE);
GpioIF* gpioIF = new LinuxLibgpioIF(objects::GPIO_IF);
GpioCookie* gpioCookie = nullptr;
diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp
index dddc4c97..b72bbf62 100644
--- a/bsp_q7s/core/CoreController.cpp
+++ b/bsp_q7s/core/CoreController.cpp
@@ -1,9 +1,14 @@
#include "CoreController.h"
-#include "q7sConfig.h"
+#include "OBSWConfig.h"
#include "OBSWVersion.h"
#include "fsfw/FSFWVersion.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
+#if OBSW_USE_TMTC_TCP_BRIDGE == 0
+#include "fsfw/osal/common/UdpTmTcBridge.h"
+#else
+#include "fsfw/osal/common/TcpTmTcBridge.h"
+#endif
#include "bsp_q7s/memory/scratchApi.h"
#include "bsp_q7s/memory/SdCardManager.h"
@@ -188,6 +193,7 @@ ReturnValue_t CoreController::initializeAfterTaskCreation() {
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "CoreController::initialize: Version initialization failed" << std::endl;
}
+ initPrint();
return result;
}
@@ -269,7 +275,8 @@ ReturnValue_t CoreController::incrementAllocationFailureCount() {
ReturnValue_t CoreController::versionFileInit() {
std::string unameFileName = "/tmp/uname_version.txt";
- std::string unameCmd = "uname -a > " + unameFileName;
+ // TODO: No -v flag for now. If the kernel version is used, need to cut off first few letters
+ std::string unameCmd = "uname -mnrso > " + unameFileName;
int result = std::system(unameCmd.c_str());
if(result != 0) {
utility::handleSystemError(result, "CoreController::versionFileInit");
@@ -348,3 +355,15 @@ ReturnValue_t CoreController::versionFileInit() {
return HasReturnvaluesIF::RETURN_OK;
}
+
+void CoreController::initPrint() {
+#if OBSW_VERBOSE_LEVEL >= 1
+#if OBSW_USE_TMTC_TCP_BRIDGE == 0
+ sif::info << "Created UDP server for TMTC commanding with listener port " <<
+ TcpTmTcBridge::DEFAULT_UDP_SERVER_PORT << std::endl;
+#else
+ sif::info << "Created TCP server for TMTC commanding with listener port " <<
+ TcpTmTcBridge::DEFAULT_TCP_SERVER_PORT << std::endl;
+#endif
+#endif
+}
diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h
index d815f302..88415949 100644
--- a/bsp_q7s/core/CoreController.h
+++ b/bsp_q7s/core/CoreController.h
@@ -41,6 +41,7 @@ private:
SdCardManager::SdStatusPair& statusPair);
ReturnValue_t versionFileInit();
+ void initPrint();
};
diff --git a/bsp_q7s/core/InitMission.cpp b/bsp_q7s/core/InitMission.cpp
index 712cf9c8..a619da5a 100644
--- a/bsp_q7s/core/InitMission.cpp
+++ b/bsp_q7s/core/InitMission.cpp
@@ -82,19 +82,20 @@ void initmission::initTasks() {
}
/* UDP bridge */
- PeriodicTaskIF* udpBridgeTask = factory->createPeriodicTask(
+ PeriodicTaskIF* tmtcBridgeTask = factory->createPeriodicTask(
"UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
- result = udpBridgeTask->addComponent(objects::UDP_BRIDGE);
+ result = tmtcBridgeTask->addComponent(objects::TMTC_BRIDGE);
if(result != HasReturnvaluesIF::RETURN_OK) {
- initmission::printAddObjectError("UDP_BRIDGE", objects::UDP_BRIDGE);
+ initmission::printAddObjectError("UDP_BRIDGE", objects::TMTC_BRIDGE);
}
- PeriodicTaskIF* udpPollingTask = factory->createPeriodicTask(
+ PeriodicTaskIF* tmtcPollingTask = factory->createPeriodicTask(
"UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
- result = udpPollingTask->addComponent(objects::UDP_POLLING_TASK);
+ result = tmtcPollingTask->addComponent(objects::TMTC_POLLING_TASK);
if(result != HasReturnvaluesIF::RETURN_OK) {
- initmission::printAddObjectError("UDP_POLLING", objects::UDP_POLLING_TASK);
+ initmission::printAddObjectError("UDP_POLLING", objects::TMTC_POLLING_TASK);
}
+
// FS task, task interval does not matter because it runs in permanent loop, priority low
// because it is a non-essential background task
PeriodicTaskIF* fsTask = factory->createPeriodicTask(
@@ -133,8 +134,8 @@ void initmission::initTasks() {
sif::info << "Starting tasks.." << std::endl;
tmTcDistributor->startTask();
- udpBridgeTask->startTask();
- udpPollingTask->startTask();
+ tmtcBridgeTask->startTask();
+ tmtcPollingTask->startTask();
coreController->startTask();
taskStarter(pstTasks, "PST task vector");
diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp
index 3e36e63d..53da02c5 100644
--- a/bsp_q7s/core/ObjectFactory.cpp
+++ b/bsp_q7s/core/ObjectFactory.cpp
@@ -63,9 +63,16 @@
#include "fsfw/tmtcservices/PusServiceBase.h"
#include "fsfw/tmtcpacket/pus/tm.h"
-/* UDP server includes */
+#if OBSW_USE_TMTC_TCP_BRIDGE == 0
+// UDP server includes
#include "fsfw/osal/common/UdpTmTcBridge.h"
#include "fsfw/osal/common/UdpTcPollingTask.h"
+#else
+// TCP server includes
+#include "fsfw/osal/common/TcpTmTcBridge.h"
+#include "fsfw/osal/common/TcpTmTcServer.h"
+#endif
+
#include "linux/boardtest/SpiTestClass.h"
#if TEST_LIBGPIOD == 1
@@ -83,7 +90,7 @@ void Factory::setStaticFrameworkObjectIds() {
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
- TmFunnel::downlinkDestination = objects::UDP_BRIDGE;
+ TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
// No storage object for now.
TmFunnel::storageDestination = objects::NO_OBJECT;
@@ -131,8 +138,13 @@ void ObjectFactory::produce(void* args){
createReactionWheelComponents(gpioComIF);
#endif /* TE7020 != 0 */
- new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
- new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
+#if OBSW_USE_TMTC_TCP_BRIDGE == 0
+ new UdpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
+ new UdpTcPollingTask(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE);
+#else
+ new TcpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
+ new TcpTmTcServer(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE);
+#endif
/* Test Task */
#if OBSW_ADD_TEST_CODE == 1
diff --git a/common/config/commonConfig.h.in b/common/config/commonConfig.h.in
index 6c5cb4c4..3d741bcf 100644
--- a/common/config/commonConfig.h.in
+++ b/common/config/commonConfig.h.in
@@ -3,5 +3,4 @@
#define OBSW_ADD_LWGPS_TEST 0
-
#endif /* COMMON_CONFIG_COMMONCONFIG_H_ */
diff --git a/common/config/commonObjects.h b/common/config/commonObjects.h
index 0505e570..8c9a83b9 100644
--- a/common/config/commonObjects.h
+++ b/common/config/commonObjects.h
@@ -8,8 +8,8 @@ enum commonObjects: uint32_t {
/* First Byte 0x50-0x52 reserved for PUS Services **/
CCSDS_PACKET_DISTRIBUTOR = 0x50000100,
PUS_PACKET_DISTRIBUTOR = 0x50000200,
- UDP_BRIDGE = 0x50000300,
- UDP_POLLING_TASK = 0x50000400,
+ TMTC_BRIDGE = 0x50000300,
+ TMTC_POLLING_TASK = 0x50000400,
FILE_SYSTEM_HANDLER = 0x50000500,
/* 0x43 ('C') for Controllers */
diff --git a/doc/img/eive-logo.png b/doc/img/eive-logo.png
new file mode 100644
index 00000000..0ce27fef
Binary files /dev/null and b/doc/img/eive-logo.png differ
diff --git a/fsfw b/fsfw
index b8325959..1f6a5e63 160000
--- a/fsfw
+++ b/fsfw
@@ -1 +1 @@
-Subproject commit b83259592a1f0ae5af20b00d1aef813fa26cd350
+Subproject commit 1f6a5e635fcd6bd812e262cc65a15a8a054f7ecf
diff --git a/linux/fsfwconfig/OBSWConfig.h.in b/linux/fsfwconfig/OBSWConfig.h.in
index ab55537d..7a798717 100644
--- a/linux/fsfwconfig/OBSWConfig.h.in
+++ b/linux/fsfwconfig/OBSWConfig.h.in
@@ -17,6 +17,11 @@
/* These defines should be disabled for mission code but are useful for
debugging. */
#define OBSW_VERBOSE_LEVEL 1
+
+// Use TCP instead of UDP for the TMTC bridge. This allows using the TMTC client locally
+// because UDP packets are not allowed in the VPN
+#define OBSW_USE_TMTC_TCP_BRIDGE 0
+
#define OBSW_PRINT_MISSED_DEADLINES 1
#define OBSW_ADD_TEST_CODE 1
#define OBSW_ADD_TEST_PST 1
diff --git a/scripts/q7s-cp.py b/scripts/q7s-cp.py
new file mode 100755
index 00000000..9de9d661
--- /dev/null
+++ b/scripts/q7s-cp.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python3
+import argparse
+import os
+
+
+def main():
+ args = handle_args()
+ cmd = build_cmd(args)
+ # Run the command
+ print(f'Running command: {cmd}')
+ os.system(cmd)
+
+
+def handle_args():
+ help_string = 'This script copies files to the Q7S as long as port forwarding is active.\n'
+ help_string += 'You can set up port forwarding with ' \
+ '"ssh -L 1535:192.168.133.10:22 " -t /bin/bash'
+ parser = argparse.ArgumentParser(
+ description=help_string
+ )
+ # Optional arguments
+ parser.add_argument('-r', '--recursive', dest='recursive', default=False, action='store_true')
+ parser.add_argument('-t', '--target', help='Target destination', default='/tmp')
+ parser.add_argument('-P', '--port', help='Target port', default=1535)
+ # Positional argument(s)
+ parser.add_argument('source', help='Source files to copy')
+ return parser.parse_args()
+
+
+def build_cmd(args):
+ # Build run command
+ cmd = 'scp '
+ if args.recursive:
+ cmd += '-r '
+ cmd += f'-P {args.port} {args.source} root@localhost:'
+ if args.target:
+ cmd += args.target
+ return cmd
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/q7s-port-tcp.sh b/scripts/q7s-port-tcp.sh
new file mode 100755
index 00000000..9d370670
--- /dev/null
+++ b/scripts/q7s-port-tcp.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+echo "Setting up all Q7S ports"
+echo "-L 1534:192.168.133.10:1534 for connection to TCF agent"
+echo "-L 1535:192.168.133.10:22 for file transfers"
+echo "-L 1537:192.168.133.10:7303 to TMTC commanding using TCP"
+
+ssh -L 1534:192.168.133.10:1534 \
+ -L 1535:192.168.133.10:22 \
+ -L 1537:192.168.133.10:7303 \
+ eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 \
+ -t 'CONSOLE_PREFIX="[Q7S Tunnel]" /bin/bash'
diff --git a/scripts/q7s-port-udp.sh b/scripts/q7s-port-udp.sh
new file mode 100755
index 00000000..21393083
--- /dev/null
+++ b/scripts/q7s-port-udp.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+echo "Setting up all Q7S ports"
+echo "-L 1534:192.168.133.10:1534 for connection to TCF agent"
+echo "-L 1535:192.168.133.10:22 for file transfers"
+echo "-L 1536:192.168.133.10:7301 to TMTC commanding using UDP"
+
+ssh -L 1534:192.168.133.10:1534 \
+ -L 1535:192.168.133.10:22 \
+ -L 1536:192.168.133.10:7301 \
+ eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 \
+ -t 'CONSOLE_PREFIX="[Q7S Tunnel]" /bin/bash'
diff --git a/thirdparty/arcsec_star_tracker b/thirdparty/arcsec_star_tracker
index f596c533..c468400a 160000
--- a/thirdparty/arcsec_star_tracker
+++ b/thirdparty/arcsec_star_tracker
@@ -1 +1 @@
-Subproject commit f596c53315f1f81facb28faec3150612a5ad2ca0
+Subproject commit c468400aaf8470a31e393f53c858d2bf2c361273