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