merged develop

This commit is contained in:
Jakob.Meier 2021-07-26 12:13:00 +02:00
commit f0dc1279c4
18 changed files with 531 additions and 276 deletions

648
README.md
View File

@ -1,7 +1,25 @@
<img align="center" src="./doc/img/eive-logo.png" width="20%">
<a id="top"></a> <a name="linux"></a> 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)
# <a id="general"></a> 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
# <a id="prereq"></a> 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
# <a id="build"></a> 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 &rarr; Import &rarr; C/C++ &rarr; Existing Code as Makefile Project
3. Set build command. Replace \<target\> with either debug or release.
* When on Linux right click project &rarr; Properties &rarr; C/C++ Build &rarr; Set build command to `make <target> -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 &rarr; Show View &rarr; Make Target)
* Right click eive_obsw &rarr; 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.
# <a id="host-commands"></a> 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.
# <a id="set-up-prereq"></a> Setting up prerequisites
## <a id="vivado"></a> 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
## <a id="arm-toolchain"></a> 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
## <a id="q7s-sysroot"></a> 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
<username> hard rtprio 99
<username> soft rtprio 99
```
The soft limit can also be set in the console with `ulimit -Sr` if the hard
limit has been increased, but it is recommended to add it to the file as well for convenience.
If adding the second line is not desired for security reasons,
the soft limit needs to be set for each session. If using an IDE like eclipse
in that case, the IDE needs to be started from the console after setting
the soft limit higher there. After adding the two lines to the file,
the computer needs to be restarted.
It is also recommended to perform the following change so that the unlockRealtime
script does not need to be run anymore each time. The following steps
raise the maximum allowed message queue length to a higher number permanently, which is
required for some framework components. The recommended values for the new message
length is 130.
2. Edit the /etc/sysctl.conf file
```sh
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 = <newMsgMaxLen>
```
## 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 <newMsgMax> | 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 &rarr; 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.
## <a id="tcf-agent"></a> TCF-Agent
2. Go to Window &rarr; Perspective &rarr; 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 &rarr; Debug Configurations &rarr; 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 &rarr; Import &rarr; C/C++ &rarr; Existing Code as Makefile Project
3. Set build command. Replace \<target\> with either debug or release.
* When on Linux right click project &rarr; Properties &rarr; C/C++ Build &rarr; Set build command to `make <target> -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 &rarr; Show View &rarr; Make Target)
* Right click eive_obsw &rarr; 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
# <a id="remote-debugging"></a> 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
# <a id="direct-debugging"></a> 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 &rarr; Debug As &rarr; Debug Configurations
6. Right click Xilinx C/C++ applicaton (System Debugger) &rarr; New &rarr;
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`
# <a id="file-transfer"></a> 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:</directory-to-example-file/>/example-file </windows-machine-path/>
````
# Launching an application at start-up
More detailed information about the used q7s commands can be found in the Q7S user manual.
# <a id="q7s"></a> 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
<username> hard rtprio 99
<username> soft rtprio 99
```
The soft limit can also be set in the console with `ulimit -Sr` if the hard
limit has been increased, but it is recommended to add it to the file as well for convenience.
If adding the second line is not desired for security reasons,
the soft limit needs to be set for each session. If using an IDE like eclipse
in that case, the IDE needs to be started from the console after setting
the soft limit higher there. After adding the two lines to the file,
the computer needs to be restarted.
It is also recommended to perform the following change so that the unlockRealtime
script does not need to be run anymore each time. The following steps
raise the maximum allowed message queue length to a higher number permanently, which is
required for some framework components. The recommended values for the new message
length is 130.
2. Edit the /etc/sysctl.conf file
```sh
sudo nano /etc/sysctl.conf
```
Append at end:
```sh
fs/mqueue/msg_max = <newMsgMaxLen>
```
Apply changes with:
```sh
sudo sysctl -p
```
A possible solution which only persists for the current session is
```sh
echo <newMsgMax> | sudo tee /proc/sys/fs/mqueue/msg_max
```
# 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 &rarr; Debug As &rarr; Debug Configurations
6. Right click Xilinx C/C++ applicaton (System Debugger) &rarr; New &rarr;
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
&rarr; C/C++ Build &rarr; 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
# <a id="static-code-analysis"></a> 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=..
```
# <a id="eclipse"></a> Eclipse
When using Eclipse, there are two special build variables in the project properties
&rarr; C/C++ Build &rarr; 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 &rarr; 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 &rarr; Perspective &rarr; 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 &rarr; Debug Configurations &rarr; 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.
# <a id="rpi"></a> 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)
# <a id="fsfw"></a> 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.

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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
}

View File

@ -41,6 +41,7 @@ private:
SdCardManager::SdStatusPair& statusPair);
ReturnValue_t versionFileInit();
void initPrint();
};

View File

@ -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");

View File

@ -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

View File

@ -3,5 +3,4 @@
#define OBSW_ADD_LWGPS_TEST 0
#endif /* COMMON_CONFIG_COMMONCONFIG_H_ */

View File

@ -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 */

BIN
doc/img/eive-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

2
fsfw

@ -1 +1 @@
Subproject commit b83259592a1f0ae5af20b00d1aef813fa26cd350
Subproject commit 1f6a5e635fcd6bd812e262cc65a15a8a054f7ecf

View File

@ -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

42
scripts/q7s-cp.py Executable file
View File

@ -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 <eive-flatsat-ip>" -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()

11
scripts/q7s-port-tcp.sh Executable file
View File

@ -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'

11
scripts/q7s-port-udp.sh Executable file
View File

@ -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'

@ -1 +1 @@
Subproject commit f596c53315f1f81facb28faec3150612a5ad2ca0
Subproject commit c468400aaf8470a31e393f53c858d2bf2c361273