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