diff --git a/.gitmodules b/.gitmodules index 44a86d86..6bde354a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,7 +9,7 @@ url = https://egit.irs.uni-stuttgart.de/eive/fsfw.git [submodule "tmtc"] path = tmtc - url = https://egit.irs.uni-stuttgart.de/eive/eive_tmtc.git + url = https://egit.irs.uni-stuttgart.de/eive/eive-tmtc.git [submodule "thirdparty/lwgps"] path = thirdparty/lwgps url = https://github.com/rmspacefish/lwgps.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 33c6edfc..cbf38410 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,10 @@ cmake_minimum_required(VERSION 3.13) set(CMAKE_SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +if(TGT_BSP MATCHES "arm/q7s") + option(Q7S_SIMPLE_MODE OFF "Simple mode with a minimal main function") +endif() + option(ADD_ETL_LIB "Add ETL library" ON) if(NOT OS_FSFW) set(OS_FSFW host CACHE STRING "OS for the FSFW.") @@ -47,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) @@ -74,9 +79,11 @@ if(TGT_BSP) OR ${TGT_BSP} MATCHES "arm/beagleboneblack" ) set(FSFW_CONFIG_PATH "linux/fsfwconfig") - set(ADD_LINUX_FILES TRUE) - set(ADD_CSP_LIB TRUE) - set(FSFW_HAL_ADD_LINUX ON) + if(NOT Q7S_SIMPLE_MODE) + set(ADD_LINUX_FILES TRUE) + set(ADD_CSP_LIB TRUE) + set(FSFW_HAL_ADD_LINUX ON) + endif() endif() if(${TGT_BSP} MATCHES "arm/raspberrypi") @@ -133,27 +140,34 @@ if(ADD_LINUX_FILES) add_subdirectory(${LINUX_PATH}) endif() -add_subdirectory(${LWGPS_LIB_PATH}) add_subdirectory(${BSP_PATH}) -add_subdirectory(${FSFW_PATH}) -add_subdirectory(${MISSION_PATH}) -add_subdirectory(${TEST_PATH}) -add_subdirectory(${FSFW_HAL_LIB_PATH}) add_subdirectory(${COMMON_PATH}) +if(NOT Q7S_SIMPLE_MODE) + add_subdirectory(${LWGPS_LIB_PATH}) + add_subdirectory(${FSFW_PATH}) + add_subdirectory(${MISSION_PATH}) + add_subdirectory(${TEST_PATH}) + add_subdirectory(${FSFW_HAL_LIB_PATH}) +endif() + + ################################################################################ # Post-Sources preparation ################################################################################ set_property(CACHE OS_FSFW PROPERTY STRINGS host linux) -# Add libraries for all sources. -target_link_libraries(${TARGET_NAME} PRIVATE - ${LIB_FSFW_NAME} - ${LIB_OS_NAME} - ${LIB_LWGPS_NAME} - ${LIB_FSFW_HAL_NAME} -) +if(NOT Q7S_SIMPLE_MODE) + # Add libraries for all sources. + target_link_libraries(${TARGET_NAME} PRIVATE + ${LIB_FSFW_NAME} + ${LIB_OS_NAME} + ${LIB_LWGPS_NAME} + ${LIB_FSFW_HAL_NAME} + ${LIB_CXX_FS} + ) +endif() if(ADD_ETL_LIB) target_link_libraries(${TARGET_NAME} PRIVATE @@ -243,8 +257,3 @@ add_custom_command( include (${CMAKE_SCRIPT_PATH}/BuildType.cmake) set_build_type() - - - - - diff --git a/README.md b/README.md index ba18152d..356ccf75 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. @@ -79,7 +112,7 @@ wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/2Fp2ag6NGnbtAsK/downloa 3. Run the following commands in MinGW64 ```sh - pacman -Syuuu + pacman -Syu ``` It is recommended to install the full base development toolchain @@ -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,7 +652,84 @@ gpioget Example to get state: gpioget gpiochip7 14 -## Running the EIVE OBSW on a Raspberry Pi +Both the MIOs and EMIOs can be accessed via the zynq_gpio instance which +comprises 118 pins (54 MIOs and 64 EMIOs). + +## 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 +``` + +## Preparation of a fresh rootfs and SD card + +This section summarizes important changes between a fresh rootfs and the current +EIVE implementation + +### rootfs + +- 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 + +### SD Cards + +- Folder `bin` for binaries, for example the OBSW +- Folder `misc` for miscellaneous files +- Folder `tc` for telecommands +- 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 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. @@ -642,28 +745,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_linux_board/InitMission.cpp b/bsp_linux_board/InitMission.cpp index 16dab475..9e7abd94 100644 --- a/bsp_linux_board/InitMission.cpp +++ b/bsp_linux_board/InitMission.cpp @@ -135,9 +135,9 @@ void initmission::initTasks() { } #if OBSW_ADD_TEST_PST == 1 - FixedTimeslotTaskIF* pstTestTask = factory->createFixedTimeslotTask( - "ACS_PST", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 2.0, missedDeadlineFunc); - result = pst::pollingSequenceTest(pstTestTask); + FixedTimeslotTaskIF* pstTestTask = factory->createFixedTimeslotTask("ACS_PST", 50, + PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 2.0, missedDeadlineFunc); + result = pst::pstTest(pstTestTask); if(result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "initmission::initTasks: ACS PST initialization failed!" << std::endl; } diff --git a/bsp_linux_board/ObjectFactory.cpp b/bsp_linux_board/ObjectFactory.cpp index d6dfd623..c5e12868 100644 --- a/bsp_linux_board/ObjectFactory.cpp +++ b/bsp_linux_board/ObjectFactory.cpp @@ -1,3 +1,6 @@ +#include +#include +#include #include "ObjectFactory.h" #include "objects/systemObjectList.h" @@ -68,6 +71,8 @@ void ObjectFactory::produce(void* args){ #if RPI_ADD_UART_TEST == 1 new UartTestClass(objects::UART_TEST); +#else + new UartComIF(objects::UART_COM_IF); #endif #if RPI_LOOPBACK_TEST_GPIO == 1 @@ -146,4 +151,15 @@ void ObjectFactory::produce(void* args){ auto adisGyroHandler = new GyroADIS16507Handler(objects::GYRO_0_ADIS_HANDLER, objects::SPI_COM_IF, spiCookie); adisGyroHandler->setStartUpImmediately(); #endif /* RPI_TEST_ADIS16507 == 1 */ + +#if RPI_TEST_GPS_HANDLER == 1 + UartCookie* uartCookie = new UartCookie(objects::GPS0_HANDLER, "/dev/serial0", + UartModes::CANONICAL, 9600, 1024); + uartCookie->setToFlushInput(true); + uartCookie->setReadCycles(6); + GPSHyperionHandler* gpsHandler = new GPSHyperionHandler(objects::GPS0_HANDLER, + objects::UART_COM_IF, uartCookie); + gpsHandler->setStartUpImmediately(); +#endif + } diff --git a/bsp_linux_board/boardconfig/rpiConfig.h.in b/bsp_linux_board/boardconfig/rpiConfig.h.in index 0094903c..19629465 100644 --- a/bsp_linux_board/boardconfig/rpiConfig.h.in +++ b/bsp_linux_board/boardconfig/rpiConfig.h.in @@ -7,6 +7,7 @@ #define RPI_LOOPBACK_TEST_GPIO 0 #define RPI_TEST_ADIS16507 0 +#define RPI_TEST_GPS_HANDLER 0 // Only one of those 2 should be enabled! #define RPI_ADD_SPI_TEST 0 diff --git a/bsp_q7s/CMakeLists.txt b/bsp_q7s/CMakeLists.txt index ce790656..3bc9aa4e 100644 --- a/bsp_q7s/CMakeLists.txt +++ b/bsp_q7s/CMakeLists.txt @@ -1,11 +1,16 @@ target_sources(${TARGET_NAME} PUBLIC - InitMission.cpp main.cpp - ObjectFactory.cpp ) -add_subdirectory(boardconfig) -add_subdirectory(comIF) add_subdirectory(boardtest) -add_subdirectory(gpio) -add_subdirectory(core) + +if(Q7S_SIMPLE_MODE) + add_subdirectory(simple) +else() + add_subdirectory(boardconfig) + add_subdirectory(comIF) + 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 782ecf4f..11dec25c 100644 --- a/bsp_q7s/boardconfig/q7sConfig.h.in +++ b/bsp_q7s/boardconfig/q7sConfig.h.in @@ -1,13 +1,35 @@ #ifndef BSP_Q7S_BOARDCONFIG_Q7S_CONFIG_H_ #define BSP_Q7S_BOARDCONFIG_Q7S_CONFIG_H_ -#define Q7S_ADD_RTD_DEVICES 0 +#include + +#cmakedefine01 Q7S_SIMPLE_MODE + +#define Q7S_SD_NONE 0 +#define Q7S_SD_COLD_REDUNDANT 1 +#define Q7S_SD_HOT_REDUNDANT 2 +// The OBSW will perform different actions to set up the SD cards depending on the flag set here +// Set to Q7S_SD_NONE: Don't do anything +// Set to Q7S_COLD_REDUNDANT: On startup, get the prefered SD card, turn it on and mount it, and +// turn off the second SD card if it is on +// Set to Q7S_HOT_REDUNDANT: On startup, turn on both SD cards and mount them +#define Q7S_SD_CARD_CONFIG Q7S_SD_COLD_REDUNDANT + +#define Q7S_ADD_RTD_DEVICES 0 /* Only one of those 2 should be enabled! */ /* Add code for ACS board */ #define OBSW_ADD_ACS_BOARD 0 +#if OBSW_ADD_ACS_BOARD == 0 #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/bsp_q7s.mk b/bsp_q7s/bsp_q7s.mk deleted file mode 100644 index 93bfdc78..00000000 --- a/bsp_q7s/bsp_q7s.mk +++ /dev/null @@ -1,6 +0,0 @@ -CXXSRC += $(wildcard $(CURRENTPATH)/*.cpp) -CXXSRC += $(wildcard $(CURRENTPATH)/comIF/cookies/*.cpp) -CXXSRC += $(wildcard $(CURRENTPATH)/comIF/*.cpp) -CSRC += $(wildcard $(CURRENTPATH)/*.c) - -CSRC += $(wildcard $(CURRENTPATH)/boardconfig/*.c) \ No newline at end of file diff --git a/bsp_q7s/core/CMakeLists.txt b/bsp_q7s/core/CMakeLists.txt index 4b2364c1..fc397f2f 100644 --- a/bsp_q7s/core/CMakeLists.txt +++ b/bsp_q7s/core/CMakeLists.txt @@ -1,3 +1,6 @@ target_sources(${TARGET_NAME} PRIVATE CoreController.cpp + obsw.cpp + InitMission.cpp + ObjectFactory.cpp ) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 253efd91..c4863260 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -1,4 +1,7 @@ #include "CoreController.h" +#include "q7sConfig.h" + +#include "../memory/SdCardManager.h" CoreController::CoreController(object_id_t objectId): ExtendedControllerBase(objectId, objects::NO_OBJECT, 5) { @@ -20,7 +23,126 @@ LocalPoolDataSetBase* CoreController::getDataSetHandle(sid_t sid) { return nullptr; } +ReturnValue_t CoreController::initialize() { + return sdCardInit(); +} + ReturnValue_t CoreController::checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode) { return HasReturnvaluesIF::RETURN_OK; } + +ReturnValue_t CoreController::sdCardInit() { +#if Q7S_SD_CARD_CONFIG == Q7S_SD_NONE + sif::info << "No SD card initialization will be performed" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +#else + SdCardManager* sdcMan = SdCardManager::instance(); + + // Create update status file + ReturnValue_t result = sdcMan->updateSdCardStateFile(); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "CoreController::initialize: Updating SD card state file failed" + << std::endl; + } + + auto sdStatus = std::pair(sd::SdStatus::OFF, sd::SdStatus::OFF); + result = sdcMan->getSdCardActiveStatus(sdStatus); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "Getting SD card activity status failed" << std::endl; + } + + // Use a lambda to avoid duplicate code + auto setUpSdCard = [&](sd::SdCard sdCard, sd::SdStatus status, std::string sdString) { + std::string mountString; + if(sdCard == sd::SdCard::SLOT_0) { + mountString = SdCardManager::SD_0_MOUNT_POINT; + } + else { + mountString = SdCardManager::SD_1_MOUNT_POINT; + } + + if(status == sd::SdStatus::OFF) { + sif::info << "Switching on and mounting SD card " << sdString << " at " << + mountString << std::endl; + return sdcMan->switchOnSdCard(sdCard, true, &sdStatus); + } + else if(status == sd::SdStatus::ON) { + sif::info << "Mounting SD card " << sdString << " at " << mountString << std::endl; + return sdcMan->mountSdCard(sdCard); + } + else { + sif::info << "SD card " << sdString << " already on and mounted at " << + mountString << std::endl; + return SdCardManager::ALREADY_MOUNTED; + } + }; + +#if Q7S_SD_CARD_CONFIG == Q7S_SD_COLD_REDUNDANT + sd::SdCard preferredSdCard = sd::SdCard::SLOT_0; + result = sdcMan->getPreferredSdCard(preferredSdCard); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "Could not get preferred SD card information from the scratch buffer" + << std::endl; + } + std::string preferredString; + sd::SdStatus preferredStatus = sd::SdStatus::OFF; + + sd::SdStatus otherStatus = sd::SdStatus::OFF; + std::string otherString; + sd::SdCard otherSdc = sd::SdCard::SLOT_0; + + if(preferredSdCard == sd::SdCard::SLOT_0) { + preferredStatus = sdStatus.first; + preferredString = "0"; + otherSdc = sd::SdCard::SLOT_1; + otherStatus = sdStatus.second; + otherString = "1"; + } + else { + preferredString = "1"; + preferredStatus = sdStatus.second; + otherStatus = sdStatus.first; + otherSdc = sd::SdCard::SLOT_0; + otherString = "0"; + } + + sif::info << "Cold redundant SD card configuration, preferred SD card " << + preferredString << std::endl; + + result = setUpSdCard(preferredSdCard, preferredStatus, preferredString); + if(result != SdCardManager::ALREADY_MOUNTED and result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "Setting up preferred card " << otherString << + " in cold redundant mode failed" << std::endl; + // Try other SD card and mark set up operation as failed + setUpSdCard(otherSdc, otherStatus, otherString); + result = HasReturnvaluesIF::RETURN_FAILED; + } + + if(result != HasReturnvaluesIF::RETURN_FAILED and otherStatus != sd::SdStatus::OFF) { + sif::info << "Switching off secondary SD card " << otherString << std::endl; + // Switch off other SD card in cold redundant mode if setting up preferred one walked + // without issues + result = sdcMan->switchOffSdCard(otherSdc, otherStatus, &sdStatus); + if(result != HasReturnvaluesIF::RETURN_OK and result != SdCardManager::ALREADY_OFF) { + sif::warning << "Switching off secondary SD card " << otherString << + " in cold redundant mode failed" << std::endl; + } + } + + // Update status file + sdcMan->updateSdCardStateFile(); + return HasReturnvaluesIF::RETURN_OK; +#elif Q7S_SD_CARD_CONFIG == Q7S_SD_HOT_REDUNDANT + sif::info << "Hot redundant SD card configuration" << std::endl; + + setUpSdCard(sd::SdCard::SLOT_0, sdStatus.first, "0"); + setUpSdCard(sd::SdCard::SLOT_1, sdStatus.second, "1"); + // Update status file + sdcMan->updateSdCardStateFile(); + return HasReturnvaluesIF::RETURN_OK; +#endif + +#endif /* Q7S_SD_CARD_CONFIG != Q7S_SD_NONE */ + +} diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index bc8a1581..940a9097 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: @@ -15,6 +17,8 @@ private: LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode); + + ReturnValue_t sdCardInit(); }; diff --git a/bsp_q7s/InitMission.cpp b/bsp_q7s/core/InitMission.cpp similarity index 78% rename from bsp_q7s/InitMission.cpp rename to bsp_q7s/core/InitMission.cpp index 9a475a11..2bc334b9 100644 --- a/bsp_q7s/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); } @@ -85,14 +93,6 @@ void initmission::initTasks() { initmission::printAddObjectError("UDP_POLLING", objects::UDP_POLLING_TASK); } - /* UDP bridge */ - PeriodicTaskIF* errorReporterTestTask = factory->createPeriodicTask( - "ERROR_REPORTER", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); - result = udpBridgeTask->addComponent(objects::INTERNAL_ERROR_REPORTER); - if(result != HasReturnvaluesIF::RETURN_OK) { - initmission::printAddObjectError("ERROR_REPORTER", objects::INTERNAL_ERROR_REPORTER); - } - #if TEST_CCSDS_BRIDGE == 1 PeriodicTaskIF* ptmeTestTask = factory->createPeriodicTask( "PTME_TEST", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc); @@ -112,10 +112,14 @@ void initmission::initTasks() { PeriodicTaskIF* pusEvents = factory->createPeriodicTask( "PUS_EVENTS", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc); - result = pusVerification->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING); + result = pusEvents->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING); if(result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("PUS_EVENTS", objects::PUS_SERVICE_5_EVENT_REPORTING); } + result = pusEvents->addComponent(objects::EVENT_MANAGER); + if(result != HasReturnvaluesIF::RETURN_OK) { + initmission::printAddObjectError("PUS_MGMT", objects::EVENT_MANAGER); + } PeriodicTaskIF* pusHighPrio = factory->createPeriodicTask( "PUS_HIGH_PRIO", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc); @@ -153,30 +157,51 @@ void initmission::initTasks() { if(result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("PUS_17", objects::PUS_SERVICE_17_TEST); } + result = pusLowPrio->addComponent(objects::INTERNAL_ERROR_REPORTER); + if(result != HasReturnvaluesIF::RETURN_OK) { + initmission::printAddObjectError("ERROR_REPORTER", objects::INTERNAL_ERROR_REPORTER); + } #if TE0720 == 0 - //TODO: Add handling of missed deadlines /* Polling Sequence Table Default */ #if Q7S_ADD_SPI_TEST == 0 - FixedTimeslotTaskIF * pollingSequenceTableTaskDefault = factory->createFixedTimeslotTask( - "PST_TASK_DEFAULT", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, + FixedTimeslotTaskIF* spiPst = factory->createFixedTimeslotTask( + "PST_TASK_DEFAULT", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, missedDeadlineFunc); - result = pst::pollingSequenceInitDefault(pollingSequenceTableTaskDefault); + result = pst::pstSpi(spiPst); if (result != HasReturnvaluesIF::RETURN_OK) { sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; } #endif - FixedTimeslotTaskIF* gomSpacePstTask = factory-> - createFixedTimeslotTask("GS_PST_TASK", 50, - PeriodicTaskIF::MINIMUM_STACK_SIZE*8, 1.0, missedDeadlineFunc); - result = pst::gomspacePstInit(gomSpacePstTask); + FixedTimeslotTaskIF* uartPst = factory->createFixedTimeslotTask( + "UART_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, missedDeadlineFunc); + result = pst::pstUart(uartPst); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; + } + FixedTimeslotTaskIF* gpioPst = factory->createFixedTimeslotTask( + "GPIO_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, missedDeadlineFunc); + result = pst::pstGpio(gpioPst); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; + } + FixedTimeslotTaskIF* i2cPst = factory->createFixedTimeslotTask( + "I2C_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, missedDeadlineFunc); + result = pst::pstI2c(i2cPst); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; + } + + FixedTimeslotTaskIF* gomSpacePstTask = factory->createFixedTimeslotTask( + "GS_PST_TASK", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 1.0, missedDeadlineFunc); + result = pst::pstGompaceCan(gomSpacePstTask); if(result != HasReturnvaluesIF::RETURN_OK) { sif::error << "InitMission::initTasks: GomSpace PST initialization failed!" << std::endl; } -#else +#else /* TE7020 == 0 */ FixedTimeslotTaskIF * pollingSequenceTaskTE0720 = factory->createFixedTimeslotTask( "PST_TASK_TE0720", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE * 8, 3.0, missedDeadlineFunc); @@ -184,7 +209,7 @@ void initmission::initTasks() { if (result != HasReturnvaluesIF::RETURN_OK) { sif::error << "InitMission::initTasks: Creating TE0720 PST failed!" << std::endl; } -#endif +#endif /* TE7020 == 1 */ #if OBSW_ADD_TEST_CODE == 1 PeriodicTaskIF* testTask = factory->createPeriodicTask( @@ -212,10 +237,17 @@ void initmission::initTasks() { tmTcDistributor->startTask(); udpBridgeTask->startTask(); udpPollingTask->startTask(); + coreController->startTask(); -#if TE0720 == 0 && Q7S_ADD_SPI_TEST == 0 +#if TE0720 == 0 + uartPst->startTask(); + gpioPst->startTask(); + i2cPst->startTask(); +#if Q7S_ADD_SPI_TEST == 0 gomSpacePstTask->startTask(); - pollingSequenceTableTaskDefault->startTask(); + spiPst->startTask(); +#endif /* Q7S_ADD_SPI_TEST == 0 */ + #elif TE0720 == 1 && Q7S_ADD_SPI_TEST == 0 pollingSequenceTaskTE0720->startTask(); #endif @@ -226,8 +258,6 @@ void initmission::initTasks() { pusMedPrio->startTask(); pusLowPrio->startTask(); - errorReporterTestTask->startTask(); - #if OBSW_ADD_TEST_CODE == 1 testTask->startTask(); #endif diff --git a/bsp_q7s/InitMission.h b/bsp_q7s/core/InitMission.h similarity index 100% rename from bsp_q7s/InitMission.h rename to bsp_q7s/core/InitMission.h diff --git a/bsp_q7s/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp similarity index 89% rename from bsp_q7s/ObjectFactory.cpp rename to bsp_q7s/core/ObjectFactory.cpp index 99ec65c2..5f015ff1 100644 --- a/bsp_q7s/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -1,3 +1,4 @@ +#include #include "ObjectFactory.h" #include "OBSWConfig.h" #include "tmtc/apid.h" @@ -9,6 +10,7 @@ #include "bsp_q7s/gpio/gpioCallbacks.h" #include "bsp_q7s/core/CoreController.h" +#include "bsp_q7s/spiCallbacks/rwSpiCallback.h" #include #include @@ -31,11 +33,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -518,8 +522,6 @@ void ObjectFactory::produce(void* args){ Max31865PT1000Handler* rtdIc16 = new Max31865PT1000Handler(objects::RTD_IC16, objects::SPI_COM_IF, spiRtdIc16, 0); Max31865PT1000Handler* rtdIc17 = new Max31865PT1000Handler(objects::RTD_IC17, objects::SPI_COM_IF, spiRtdIc17, 0); Max31865PT1000Handler* rtdIc18 = new Max31865PT1000Handler(objects::RTD_IC18, objects::SPI_COM_IF, spiRtdIc18, 0); - rtdIc17->setStartUpImmediately(); -// rtdIc4->setStartUpImmediately(); (void) rtdIc3; (void) rtdIc4; @@ -535,7 +537,7 @@ void ObjectFactory::produce(void* args){ (void) rtdIc14; (void) rtdIc15; (void) rtdIc16; -// (void) rtdIc17; + (void) rtdIc17; (void) rtdIc18; #endif /* Q7S_ADD_RTD_DEVICES == 1 */ @@ -544,18 +546,87 @@ void ObjectFactory::produce(void* args){ std::string("/dev/i2c-0")); new IMTQHandler(objects::IMTQ_HANDLER, objects::I2C_COM_IF, imtqI2cCookie); - UartCookie* plocUartCookie = new UartCookie(objects::PLOC_HANDLER, std::string("/dev/ttyUL3"), + UartCookie* plocUartCookie = new UartCookie(objects::RW1, std::string("/dev/ttyUL3"), UartModes::NON_CANONICAL, 115200, PLOC::MAX_REPLY_SIZE); - PlocHandler* plocHandler = new PlocHandler(objects::PLOC_HANDLER, objects::UART_COM_IF, - plocUartCookie); -// plocHandler->setStartUpImmediately(); - (void) plocHandler; + new PlocHandler(objects::PLOC_HANDLER, objects::UART_COM_IF, plocUartCookie); + + GpioCookie* gpioCookieRw = new GpioCookie; + GpioCallback* csRw1 = new GpioCallback(std::string("Chip select reaction wheel 1"), gpio::OUT, + 1, &gpioCallbacks::spiCsDecoderCallback, gpioComIF); + gpioCookieRw->addGpio(gpioIds::CS_RW1, csRw1); + GpioCallback* csRw2 = new GpioCallback(std::string("Chip select reaction wheel 2"), gpio::OUT, + 1, &gpioCallbacks::spiCsDecoderCallback, gpioComIF); + gpioCookieRw->addGpio(gpioIds::CS_RW2, csRw2); + GpioCallback* csRw3 = new GpioCallback(std::string("Chip select reaction wheel 3"), gpio::OUT, + 1, &gpioCallbacks::spiCsDecoderCallback, gpioComIF); + gpioCookieRw->addGpio(gpioIds::CS_RW3, csRw3); + GpioCallback* csRw4 = new GpioCallback(std::string("Chip select reaction wheel 4"), gpio::OUT, + 1, &gpioCallbacks::spiCsDecoderCallback, gpioComIF); + gpioCookieRw->addGpio(gpioIds::CS_RW4, csRw4); + + GpiodRegular* enRw1 = new GpiodRegular(std::string("gpiochip5"), 7, + std::string("Enable reaction wheel 1"), gpio::OUT, 0); + gpioCookieRw->addGpio(gpioIds::EN_RW1, enRw1); + GpiodRegular* enRw2 = new GpiodRegular(std::string("gpiochip5"), 3, + std::string("Enable reaction wheel 2"), gpio::OUT, 0); + gpioCookieRw->addGpio(gpioIds::EN_RW2, enRw2); + GpiodRegular* enRw3 = new GpiodRegular(std::string("gpiochip5"), 11, + std::string("Enable reaction wheel 3"), gpio::OUT, 0); + gpioCookieRw->addGpio(gpioIds::EN_RW3, enRw3); + GpiodRegular* enRw4 = new GpiodRegular(std::string("gpiochip5"), 6, + std::string("Enable reaction wheel 4"), gpio::OUT, 0); + gpioCookieRw->addGpio(gpioIds::EN_RW4, enRw4); + + /** + * This GPIO is only internally connected to the SPI MUX module and responsible to disconnect + * the PS SPI peripheral from the SPI interface and route out the SPI lines of the AXI SPI core. + * Per default the PS SPI is selected (EMIO = 0). + */ + GpiodRegular* spiMux = new GpiodRegular(std::string("gpiochip11"), 54, + std::string("EMIO 0 SPI Mux"), gpio::OUT, 0); + gpioCookieRw->addGpio(gpioIds::SPI_MUX, spiMux); + + gpioComIF->addGpios(gpioCookieRw); + + auto rw1SpiCookie = new SpiCookie(addresses::RW1, gpioIds::CS_RW1, "/dev/spidev3.0", + RwDefinitions::MAX_REPLY_SIZE, spi::RW_MODE, spi::RW_SPEED, &rwSpiCallback::spiCallback, + nullptr); + auto rw2SpiCookie = new SpiCookie(addresses::RW2, gpioIds::CS_RW2, "/dev/spidev3.0", + RwDefinitions::MAX_REPLY_SIZE, spi::RW_MODE, spi::RW_SPEED, &rwSpiCallback::spiCallback, + nullptr); + auto rw3SpiCookie = new SpiCookie(addresses::RW3, gpioIds::CS_RW3, "/dev/spidev3.0", + RwDefinitions::MAX_REPLY_SIZE, spi::RW_MODE, spi::RW_SPEED, &rwSpiCallback::spiCallback, + nullptr); + auto rw4SpiCookie = new SpiCookie(addresses::RW4, gpioIds::CS_RW4, "/dev/spidev3.0", + RwDefinitions::MAX_REPLY_SIZE, spi::RW_MODE, spi::RW_SPEED, &rwSpiCallback::spiCallback, + nullptr); + + auto rwHandler1 = new RwHandler(objects::RW1, objects::SPI_COM_IF, rw1SpiCookie, gpioComIF, + gpioIds::EN_RW1); + rw1SpiCookie->setCallbackArgs(rwHandler1); + + auto rwHandler2 = new RwHandler(objects::RW2, objects::SPI_COM_IF, rw2SpiCookie, gpioComIF, + gpioIds::EN_RW2); + rw2SpiCookie->setCallbackArgs(rwHandler2); + + auto rwHandler3 = new RwHandler(objects::RW3, objects::SPI_COM_IF, rw3SpiCookie, gpioComIF, + gpioIds::EN_RW3); + rw3SpiCookie->setCallbackArgs(rwHandler3); + + auto rwHandler4 = new RwHandler(objects::RW4, objects::SPI_COM_IF, rw4SpiCookie, gpioComIF, + gpioIds::EN_RW4); + rw4SpiCookie->setCallbackArgs(rwHandler4); #endif /* TE0720 == 0 */ 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, @@ -630,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/ObjectFactory.h b/bsp_q7s/core/ObjectFactory.h similarity index 100% rename from bsp_q7s/ObjectFactory.h rename to bsp_q7s/core/ObjectFactory.h diff --git a/bsp_q7s/core/obsw.cpp b/bsp_q7s/core/obsw.cpp new file mode 100644 index 00000000..f813bcae --- /dev/null +++ b/bsp_q7s/core/obsw.cpp @@ -0,0 +1,25 @@ +#include "obsw.h" +#include "OBSWVersion.h" +#include "InitMission.h" +#include "fsfw/tasks/TaskFactory.h" +#include + +int obsw::obsw() { + std::cout << "-- EIVE OBSW --" << std::endl; +#if TE0720 == 0 + std::cout << "-- Compiled for Linux (Xiphos Q7S) --" << std::endl; +#else + std::cout << "-- Compiled for Linux (TE0720) --" << std::endl; +#endif + std::cout << "-- Software version " << SW_NAME << " v" << SW_VERSION << "." + << SW_SUBVERSION << "." << SW_SUBSUBVERSION << " -- " << std::endl; + std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl; + + initmission::initMission(); + + for(;;) { + /* Suspend main thread by sleeping it. */ + TaskFactory::delayTask(5000); + } + return 0; +} diff --git a/bsp_q7s/core/obsw.h b/bsp_q7s/core/obsw.h new file mode 100644 index 00000000..c2d974ae --- /dev/null +++ b/bsp_q7s/core/obsw.h @@ -0,0 +1,10 @@ +#ifndef BSP_Q7S_CORE_OBSW_H_ +#define BSP_Q7S_CORE_OBSW_H_ + +namespace obsw { + +int obsw(); + +}; + +#endif /* BSP_Q7S_CORE_OBSW_H_ */ diff --git a/bsp_q7s/gpio/gpioCallbacks.cpp b/bsp_q7s/gpio/gpioCallbacks.cpp index 2f59cb0e..5499517b 100644 --- a/bsp_q7s/gpio/gpioCallbacks.cpp +++ b/bsp_q7s/gpio/gpioCallbacks.cpp @@ -45,11 +45,13 @@ void initSpiCsDecoder(GpioIF* gpioComIF) { GpiodRegular* spiMuxBit6 = new GpiodRegular(std::string("gpiochip7"), 18, std::string("SPI Mux Bit 6"), gpio::OUT, 0); spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_6, spiMuxBit6); + GpiodRegular* enRwDecoder = new GpiodRegular(std::string("gpiochip5"), 17, + std::string("EN_RW_CS"), gpio::OUT, 1); + spiMuxGpios->addGpio(gpioIds::EN_RW_CS, enRwDecoder); result = gpioComInterface->addGpios(spiMuxGpios); if (result != HasReturnvaluesIF::RETURN_OK) { - sif::error << "initSpiCsDecoder: Failed to add mux bit gpios to gpioComIF" - << std::endl; + sif::error << "initSpiCsDecoder: Failed to add mux bit gpios to gpioComIF" << std::endl; return; } } @@ -218,6 +220,26 @@ void spiCsDecoderCallback(gpioId_t gpioId, gpio::GpioOperation gpioOp, int value selectY6(); break; } + case(gpioIds::CS_RW1): { + enableRwDecoder(); + selectY0(); + break; + } + case(gpioIds::CS_RW2): { + enableRwDecoder(); + selectY1(); + break; + } + case(gpioIds::CS_RW3): { + enableRwDecoder(); + selectY2(); + break; + } + case(gpioIds::CS_RW4): { + enableRwDecoder(); + selectY3(); + break; + } default: sif::debug << "spiCsDecoderCallback: Invalid gpio id " << gpioId << std::endl; } @@ -251,6 +273,13 @@ void enableDecoderInterfaceBoardIc2() { gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3); } +void enableRwDecoder() { + gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); + gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_2); + gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3); + gpioComInterface->pullHigh(gpioIds::EN_RW_CS); +} + void selectY0() { gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4); gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5); @@ -303,6 +332,7 @@ void disableAllDecoder() { gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_2); gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3); + gpioComInterface->pullLow(gpioIds::EN_RW_CS); } } diff --git a/bsp_q7s/gpio/gpioCallbacks.h b/bsp_q7s/gpio/gpioCallbacks.h index 4a0c73cb..eaf9a701 100644 --- a/bsp_q7s/gpio/gpioCallbacks.h +++ b/bsp_q7s/gpio/gpioCallbacks.h @@ -43,6 +43,11 @@ namespace gpioCallbacks { */ void enableDecoderInterfaceBoardIc2(); + /** + * @brief Enables the reaction wheel chip select decoder (IC3). + */ + void enableRwDecoder(); + /** * @brief This function disables all decoder. */ diff --git a/bsp_q7s/main.cpp b/bsp_q7s/main.cpp index 06f454c2..9ce0dca2 100644 --- a/bsp_q7s/main.cpp +++ b/bsp_q7s/main.cpp @@ -1,34 +1,23 @@ -#include "InitMission.h" -#include -#include -#include "OBSWConfig.h" +#include "q7sConfig.h" + +#if Q7S_SIMPLE_MODE == 0 +#include "core/obsw.h" +#else +#include "simple/simple.h" +#endif #include -#include - /** * @brief This is the main program for the target hardware. * @return */ int main(void) { - std::cout << "-- EIVE OBSW --" << std::endl; -#if TE0720 == 0 - std::cout << "-- Compiled for Linux (Xiphos Q7S) --" << std::endl; + using namespace std; +#if Q7S_SIMPLE_MODE == 0 + return obsw::obsw(); #else - std::cout << "-- Compiled for Linux (TE0720) --" << std::endl; + return simple::simple(); #endif - std::cout << "-- Software version " << SW_NAME << " v" << SW_VERSION << "." - << SW_SUBVERSION << "." << SW_SUBSUBVERSION << " -- " << std::endl; - std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl; - - initmission::initMission(); - - for(;;) { - /* Suspend main thread by sleeping it. */ - TaskFactory::delayTask(5000); - } } - - diff --git a/bsp_q7s/memory/CMakeLists.txt b/bsp_q7s/memory/CMakeLists.txt index 2ccdc7e2..6c7d0a94 100644 --- a/bsp_q7s/memory/CMakeLists.txt +++ b/bsp_q7s/memory/CMakeLists.txt @@ -1,4 +1,5 @@ target_sources(${TARGET_NAME} PRIVATE - FileSystemManager.cpp - SdCardAccess.cpp + FileSystemHandler.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..1519b92b --- /dev/null +++ b/bsp_q7s/memory/FileSystemHandler.cpp @@ -0,0 +1,184 @@ +#include "FileSystemHandler.h" + +#include "fsfw/tasks/TaskFactory.h" +#include "fsfw/memory/GenericFileSystemMessage.h" +#include "fsfw/ipc/QueueFactory.h" + +#include + +FileSystemHandler::FileSystemHandler(object_id_t fileSystemHandler): + SystemObject(fileSystemHandler) { + mq = QueueFactory::instance()->createMessageQueue(FS_MAX_QUEUE_SIZE); +} + +FileSystemHandler::~FileSystemHandler() { + QueueFactory::instance()->deleteMessageQueue(mq); +} + +ReturnValue_t FileSystemHandler::performOperation(uint8_t unsignedChar) { + while(true) { + try { + fileSystemHandlerLoop(); + } + catch(std::bad_alloc& e) { + // Restart OBSW, hints at a memory leak + sif::error << "Allocation error in FileSystemHandler::performOperation" + << e.what() << std::endl; + // TODO: If we trigger an event, it might not get sent because were restarting + // Set up an error file or a special flag in the scratch buffer. + // TODO: CoreController: Implement function to restart OBC + } + } +} + + +void FileSystemHandler::fileSystemHandlerLoop() { + CommandMessage filemsg; + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + while(true) { + if(opCounter % 5 == 0) { + fileSystemCheckup(); + } + 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; + } + } + opCounter++; + } + + // 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); +} + +void FileSystemHandler::fileSystemCheckup() { + SdCardManager::SdStatusPair statusPair; + sdcMan->getSdCardActiveStatus(statusPair); + sd::SdCard preferredSdCard; + sdcMan->getPreferredSdCard(preferredSdCard); + if((preferredSdCard == sd::SdCard::SLOT_0) and + (statusPair.first == sd::SdStatus::MOUNTED)) { + currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT; + } + if((preferredSdCard == sd::SdCard::SLOT_1) and + (statusPair.second == sd::SdStatus::MOUNTED)) { + currentMountPrefix = SdCardManager::SD_1_MOUNT_POINT; + } + else { + std::string sdString; + if(preferredSdCard == sd::SdCard::SLOT_0) { + sdString = "0"; + } + else { + sdString = "1"; + } + sif::warning << "FileSystemHandler::performOperation: Inconsistent" << + " state detected. Preferred SD card is " << sdString << + " but does not appear to be mounted. Attempting fix.." << std::endl; + // This function will appear to fix the inconsistent state + ReturnValue_t result = sdcMan->sanitizeState(&preferredSdCard, &statusPair); + if(result != HasReturnvaluesIF::RETURN_OK) { + // Oh no. + // TODO: Trigger medium severity event + sif::error << "Fix failed" << std::endl; + } + } +} + +MessageQueueId_t FileSystemHandler::getCommandQueue() const { + return mq->getId(); +} + +ReturnValue_t FileSystemHandler::initialize() { + sdcMan = SdCardManager::instance(); + sd::SdCard preferredSdCard; + ReturnValue_t result = sdcMan->getPreferredSdCard(preferredSdCard); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + if(preferredSdCard == sd::SdCard::SLOT_0) { + currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT; + } + else if(preferredSdCard == sd::SdCard::SLOT_1) { + currentMountPrefix = SdCardManager::SD_1_MOUNT_POINT; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t FileSystemHandler::appendToFile(const char *repositoryPath, const char *filename, + const uint8_t *data, size_t size, uint16_t packetNumber, void *args) { + // A double slash between repo and filename should not be an issue, so add it in any case + std::string fullPath = currentMountPrefix + std::string(repositoryPath) + "/" + + std::string(filename); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t FileSystemHandler::createFile(const char *repositoryPath, const char *filename, + const uint8_t *data, size_t size, void *args) { + // A double slash between repo and filename should not be an issue, so add it in any case + std::string fullPath = currentMountPrefix + std::string(repositoryPath) + "/" + + std::string(filename); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t FileSystemHandler::deleteFile(const char *repositoryPath, const char *filename, + void *args) { + // A double slash between repo and filename should not be an issue, so add it in any case + std::string fullPath = currentMountPrefix + std::string(repositoryPath) + "/" + + std::string(filename); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t FileSystemHandler::createDirectory(const char *repositoryPath, void *args) { + std::string fullPath = currentMountPrefix + std::string(repositoryPath); + if(std::filesystem::exists(fullPath)) { + return DIRECTORY_ALREADY_EXISTS; + } + if(std::filesystem::create_directory(fullPath)) { + return HasReturnvaluesIF::RETURN_OK; + } + sif::warning << "Creating directory " << fullPath << " failed" << std::endl; + return GENERIC_FILE_ERROR; +} + +ReturnValue_t FileSystemHandler::removeDirectory(const char *repositoryPath, + bool deleteRecurively, void *args) { + std::string fullPath = currentMountPrefix + std::string(repositoryPath); + if(not std::filesystem::exists(fullPath)) { + return DIRECTORY_DOES_NOT_EXIST; + } + std::error_code err; + if(not deleteRecurively) { + if(std::filesystem::remove(fullPath, err)) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + // Check error code. Most probably denied permissions because folder is not empty + } + } + else { + if(std::filesystem::remove_all(fullPath, err)) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + // Check error code + } + } + + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/bsp_q7s/memory/FileSystemHandler.h b/bsp_q7s/memory/FileSystemHandler.h new file mode 100644 index 00000000..886fa574 --- /dev/null +++ b/bsp_q7s/memory/FileSystemHandler.h @@ -0,0 +1,56 @@ +#ifndef BSP_Q7S_MEMORY_FILESYSTEMHANDLER_H_ +#define BSP_Q7S_MEMORY_FILESYSTEMHANDLER_H_ + +#include "SdCardManager.h" +#include "OBSWConfig.h" + +#include "fsfw/ipc/MessageQueueIF.h" +#include "fsfw/tasks/ExecutableObjectIF.h" +#include "fsfw/objectmanager/SystemObject.h" +#include "fsfw/memory/HasFileSystemIF.h" + +#include + +class FileSystemHandler: public SystemObject, + public ExecutableObjectIF, + public HasFileSystemIF { +public: + FileSystemHandler(object_id_t fileSystemHandler); + virtual~ FileSystemHandler(); + + ReturnValue_t performOperation(uint8_t) override; + + ReturnValue_t initialize() 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; + std::string currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT; + static constexpr uint32_t FS_MAX_QUEUE_SIZE = config::OBSW_FILESYSTEM_HANDLER_QUEUE_SIZE; + SdCardManager* sdcMan = nullptr; + uint8_t opCounter = 0; + + void fileSystemHandlerLoop(); + void fileSystemCheckup(); + + 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; + ReturnValue_t createDirectory(const char* repositoryPath, void* args = nullptr) override; + ReturnValue_t removeDirectory(const char* repositoryPath, bool deleteRecurively = false, + 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 deleted file mode 100644 index 3d5f12b9..00000000 --- a/bsp_q7s/memory/SdCardAccess.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include "SdCardAccess.h" - -SdCardAccess::SdCardAccess() { -} diff --git a/bsp_q7s/memory/SdCardAccess.h b/bsp_q7s/memory/SdCardAccess.h deleted file mode 100644 index ba273d09..00000000 --- a/bsp_q7s/memory/SdCardAccess.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef BSP_Q7S_MEMORY_SDCARDACCESS_H_ -#define BSP_Q7S_MEMORY_SDCARDACCESS_H_ - -class SdCardAccess { -public: - SdCardAccess(); -private: -}; - - -#endif /* BSP_Q7S_MEMORY_SDCARDACCESS_H_ */ diff --git a/bsp_q7s/memory/SdCardManager.cpp b/bsp_q7s/memory/SdCardManager.cpp new file mode 100644 index 00000000..5a50665b --- /dev/null +++ b/bsp_q7s/memory/SdCardManager.cpp @@ -0,0 +1,333 @@ +#include "SdCardManager.h" +#include "scratchApi.h" + +#include "linux/utility/utility.h" + +#include "fsfw/ipc/MutexFactory.h" +#include "fsfw/serviceinterface/ServiceInterface.h" + +#include +#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, bool doMountSdCard, + SdStatusPair* statusPair) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + if(statusPair == nullptr) { + statusPair = std::make_unique().get(); + result = getSdCardActiveStatus(*statusPair); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + + // Not allowed, this function turns on one SD card + if(sdCard == sd::SdCard::BOTH) { + sif::warning << "SdCardManager::switchOffSdCard: API does not allow sd::SdStatus::BOTH" + << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + sd::SdStatus targetStatus; + if(sdCard == sd::SdCard::SLOT_0) { + targetStatus = statusPair->first; + } + else if(sdCard == sd::SdCard::SLOT_1) { + targetStatus = statusPair->second; + } + + auto switchCall = [&]() { + if(targetStatus == sd::SdStatus::ON) { + if(not doMountSdCard) { + return ALREADY_ON; + } + else { + return mountSdCard(sdCard); + } + } + else if(targetStatus == sd::SdStatus::MOUNTED) { + return ALREADY_MOUNTED; + } + else if(targetStatus == sd::SdStatus::OFF) { + return setSdCardState(sdCard, true); + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } + }; + + result = switchCall(); + + if(result != HasReturnvaluesIF::RETURN_OK or not doMountSdCard) { + return result; + } + + return mountSdCard(sdCard); +} + +ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard, + SdStatusPair* statusPair) { + std::pair active; + ReturnValue_t result = getSdCardActiveStatus(active); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + // Not allowed, this function turns off one SD card + if(sdCard == sd::SdCard::BOTH) { + sif::warning << "SdCardManager::switchOffSdCard: API does not allow sd::SdStatus::BOTH" + << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(sdCard == sd::SdCard::SLOT_0) { + if(active.first == sd::SdStatus::OFF) { + return ALREADY_OFF; + } + } + else if(sdCard == sd::SdCard::SLOT_1) { + if(active.second == sd::SdStatus::OFF) { + return ALREADY_OFF; + } + } + + if(doUnmountSdCard) { + result = unmountSdCard(sdCard); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + + return setSdCardState(sdCard, false); +} + +ReturnValue_t SdCardManager::setSdCardState(sd::SdCard sdCard, bool on) { + using namespace std; + string sdstring = ""; + 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"; + } + ostringstream command; + command << "q7hw sd set " << sdstring << " " << statestring; + int result = 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::getSdCardActiveStatus(SdStatusPair& active) { + using namespace std; + if(not filesystem::exists(SD_STATE_FILE)) { + return STATUS_FILE_NEXISTS; + } + + // Now the file should exist in any case. Still check whether it exists. + fstream sdStatus(SD_STATE_FILE); + if (not sdStatus.good()) { + return STATUS_FILE_NEXISTS; + } + string line; + uint8_t idx = 0; + sd::SdCard currentSd = sd::SdCard::SLOT_0; + // Process status file line by line + while (std::getline(sdStatus, line)) { + processSdStatusLine(active, line, idx, currentSd); + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t SdCardManager::mountSdCard(sd::SdCard sdCard) { + using namespace std; + if(sdCard == sd::SdCard::BOTH) { + sif::warning << "SdCardManager::mountSdCard: API does not allow sd::SdStatus::BOTH" + << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + string mountDev; + string mountPoint; + if(sdCard == sd::SdCard::SLOT_0) { + mountDev = SD_0_DEV_NAME; + mountPoint = SD_0_MOUNT_POINT; + } + else if(sdCard == sd::SdCard::SLOT_1) { + mountDev = SD_1_DEV_NAME; + mountPoint = SD_1_MOUNT_POINT; + } + if(not filesystem::exists(mountDev)) { + sif::warning << "SdCardManager::mountSdCard: Device file does not exists. Make sure to" + " turn on the SD card" << std::endl; + return MOUNT_ERROR; + } + + string sdMountCommand = "mount " + mountDev + " " + mountPoint; + int result = system(sdMountCommand.c_str()); + if (result != 0) { + utility::handleSystemError(result, "SdCardManager::mountSdCard"); + return SYSTEM_CALL_ERROR; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t SdCardManager::unmountSdCard(sd::SdCard sdCard) { + using namespace std; + if(sdCard == sd::SdCard::BOTH) { + sif::warning << "SdCardManager::unmountSdCard: API does not allow sd::SdStatus::BOTH" + << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + string mountPoint; + if(sdCard == sd::SdCard::SLOT_0) { + mountPoint = SD_0_MOUNT_POINT; + } + else if(sdCard == sd::SdCard::SLOT_1) { + mountPoint = SD_1_MOUNT_POINT; + } + if(filesystem::is_empty(mountPoint)) { + // The mount point will always exist, but if it is empty, that is strong hint that + // the SD card was not mounted properly. Still proceed with operation. + sif::warning << "SdCardManager::unmountSdCard: Mount point is empty!" << std::endl; + } + string sdUnmountCommand = "umount " + mountPoint; + int result = system(sdUnmountCommand.c_str()); + if (result != 0) { + utility::handleSystemError(result, "SdCardManager::unmountSdCard"); + return SYSTEM_CALL_ERROR; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t SdCardManager::sanitizeState(sd::SdCard* prefSdCard, SdStatusPair* statusPair) { + if(prefSdCard == nullptr) { + prefSdCard = std::make_unique(sd::SdCard::SLOT_0).get(); + getPreferredSdCard(*prefSdCard); + } + if(statusPair == nullptr) { + statusPair = std::make_unique().get(); + getSdCardActiveStatus(*statusPair); + } + + auto sanitizerFunc = [&](sd::SdCard prefSdCard) { + if(statusPair->first == sd::SdStatus::ON) { + return mountSdCard(prefSdCard); + } + else { + return switchOnSdCard(prefSdCard, true, statusPair); + } + }; + + return sanitizerFunc(*prefSdCard); +} + +void SdCardManager::processSdStatusLine(std::pair &active, + std::string& line, uint8_t& idx, sd::SdCard& currentSd) { + using namespace std; + istringstream iss(line); + string word; + bool slotLine = false; + bool mountLine = false; + while(iss >> word) { + if (word == "Slot") { + slotLine = true; + } + if(word == "Mounted") { + mountLine = true; + } + + if(slotLine) { + if (word == "1:") { + currentSd = sd::SdCard::SLOT_1; + } + + if(word == "on") { + if(currentSd == sd::SdCard::SLOT_0) { + active.first = sd::SdStatus::ON; + } + else { + active.second = sd::SdStatus::ON; + } + } + else if (word == "off") { + if(currentSd == sd::SdCard::SLOT_0) { + active.first = sd::SdStatus::OFF; + } + else { + active.second = sd::SdStatus::OFF; + } + } + } + + if(mountLine) { + if(currentSd == sd::SdCard::SLOT_0) { + active.first = sd::SdStatus::MOUNTED; + } + else { + active.second = sd::SdStatus::MOUNTED; + } + } + + if(idx > 5) { + sif::warning << "SdCardManager::sdCardActive: /tmp/sd_status.txt has more than 6 " + "lines and might be invalid!" << std::endl; + } + } + idx++; +} + +ReturnValue_t SdCardManager::getPreferredSdCard(sd::SdCard& sdCard) const { + uint8_t prefSdCard = 0; + ReturnValue_t result = scratch::readNumber(scratch::PREFERED_SDC_KEY, prefSdCard); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + sdCard = static_cast(prefSdCard); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t SdCardManager::setPreferredSdCard(sd::SdCard sdCard) { + if(sdCard == sd::SdCard::BOTH) { + return HasReturnvaluesIF::RETURN_FAILED; + } + return scratch::writeNumber(scratch::PREFERED_SDC_KEY, static_cast(sdCard)); +} + +ReturnValue_t SdCardManager::updateSdCardStateFile() { + // Use q7hw utility and pipe the command output into the state file + std::string updateCmd = "q7hw sd info all > " + std::string(SD_STATE_FILE); + int result = std::system(updateCmd.c_str()); + 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..966e6e2a --- /dev/null +++ b/bsp_q7s/memory/SdCardManager.h @@ -0,0 +1,159 @@ +#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 +#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: + using SdStatusPair = std::pair; + + 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_MOUNTED = + HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 1); + static constexpr ReturnValue_t ALREADY_OFF = + HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 2); + static constexpr ReturnValue_t STATUS_FILE_NEXISTS = + HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 10); + static constexpr ReturnValue_t STATUS_FILE_FORMAT_INVALID = + HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 11); + static constexpr ReturnValue_t MOUNT_ERROR = + HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 12); + static constexpr ReturnValue_t UNMOUNT_ERROR = + HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 13); + static constexpr ReturnValue_t SYSTEM_CALL_ERROR = + HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 14); + + // C++17 does not support constexpr std::string yet + static constexpr char SD_0_DEV_NAME[] = "/dev/mmcblk0p1"; + static constexpr char SD_1_DEV_NAME[] = "/dev/mmcblk1p1"; + static constexpr char SD_0_MOUNT_POINT[] = "/mnt/sd0"; + static constexpr char SD_1_MOUNT_POINT[] = "/mnt/sd1"; + static constexpr char SD_STATE_FILE[] = "/tmp/sd_status.txt"; + + virtual ~SdCardManager(); + + static void create(); + + /** + * Returns the single instance of the SD card manager. + */ + static SdCardManager* instance(); + + /** + * Set the preferred SD card which will determine which SD card will be used as the primary + * SD card in hot redundant and cold redundant mode. This function will not switch the + * SD cards which are currently on and mounted, this needs to be implemented by + * an upper layer by using #switchOffSdCard , #switchOnSdCard and #updateSdCardStateFile + * @param sdCard + * @return + */ + ReturnValue_t setPreferredSdCard(sd::SdCard sdCard); + + /** + * Get the currently configured preferred SD card + * @param sdCard + * @return + */ + ReturnValue_t getPreferredSdCard(sd::SdCard& sdCard) const; + + /** + * Switch on the specified SD card. + * @param sdCard + * @param doMountSdCard Mount the SD card after switching it on, which is necessary + * to use it + * @param statusPair If the status pair is already available, it can be passed here + * @return - RETURN_OK on success, ALREADY_ON if it is already on, + * SYSTEM_CALL_ERROR on system error + */ + ReturnValue_t switchOnSdCard(sd::SdCard sdCard, bool doMountSdCard = true, + SdStatusPair* statusPair = nullptr); + + /** + * Switch off the specified SD card. + * @param sdCard + * @param doUnmountSdCard Unmount the SD card before switching the card off, which makes + * the operation safer + * @param statusPair If the status pair is already available, it can be passed here + * @return - RETURN_OK on success, ALREADY_ON if it is already on, + * SYSTEM_CALL_ERROR on system error + */ + ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true, + SdStatusPair* statusPair = nullptr); + + /** + * Update the state file or creates one if it does not exist. You need to call this + * function before calling #sdCardActive + * @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 getSdCardActiveStatus(SdStatusPair& active); + + /** + * Mount the specified SD card. This is necessary to use it. + * @param sdCard + * @return + */ + ReturnValue_t mountSdCard(sd::SdCard sdCard); + /** + * Unmount the specified SD card. This is recommended before switching it off. The SD card + * can't be used after it has been unmounted. + * @param sdCard + * @return + */ + ReturnValue_t unmountSdCard(sd::SdCard sdCard); + + /** + * In case that there is a discrepancy between the preferred SD card and the currently + * mounted one, this function will sanitize the state by attempting to mount the + * currently preferred SD card. If the caller already has state information, it can be + * passed into the function. + * @param prefSdCard Preferred SD card captured with #getPreferredSdCard + * @param statusPair Current SD card status capture with #getSdCardActiveStatus + * @throws std::bad_alloc if one of the two arguments was a nullptr and an allocation failed + * @return + */ + ReturnValue_t sanitizeState(sd::SdCard* prefSdCard = nullptr, + SdStatusPair* statusPair = nullptr); + +private: + SdCardManager(); + + ReturnValue_t setSdCardState(sd::SdCard sdCard, bool on); + + void processSdStatusLine(SdStatusPair& active, std::string& line, uint8_t& idx, + sd::SdCard& currentSd); + + 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..546a6585 --- /dev/null +++ b/bsp_q7s/memory/definitions.h @@ -0,0 +1,25 @@ +#ifndef BSP_Q7S_MEMORY_DEFINITIONS_H_ +#define BSP_Q7S_MEMORY_DEFINITIONS_H_ + +#include + +namespace sd { + +enum SdStatus: uint8_t { + OFF = 0, + ON = 1, + // A mounted SD card is on as well + MOUNTED = 2 +}; + +enum SdCard: uint8_t { + 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..eceda11a --- /dev/null +++ b/bsp_q7s/memory/scratchApi.h @@ -0,0 +1,72 @@ +#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 { + +static constexpr char PREFERED_SDC_KEY[] = "PREFSD"; + +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/CMakeLists.txt b/bsp_q7s/simple/CMakeLists.txt new file mode 100644 index 00000000..399a1dd3 --- /dev/null +++ b/bsp_q7s/simple/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(${TARGET_NAME} PRIVATE + simple.cpp +) diff --git a/bsp_q7s/simple/simple.cpp b/bsp_q7s/simple/simple.cpp new file mode 100644 index 00000000..a6bb9fdf --- /dev/null +++ b/bsp_q7s/simple/simple.cpp @@ -0,0 +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/bsp_q7s/simple/simple.h b/bsp_q7s/simple/simple.h new file mode 100644 index 00000000..096a7b7c --- /dev/null +++ b/bsp_q7s/simple/simple.h @@ -0,0 +1,10 @@ +#ifndef BSP_Q7S_SIMPLE_SIMPLE_H_ +#define BSP_Q7S_SIMPLE_SIMPLE_H_ + +namespace simple { + +int simple(); + +} + +#endif /* BSP_Q7S_SIMPLE_SIMPLE_H_ */ diff --git a/bsp_q7s/spi/Q7sSpiComIF.cpp b/bsp_q7s/spi/Q7sSpiComIF.cpp new file mode 100644 index 00000000..23dbe551 --- /dev/null +++ b/bsp_q7s/spi/Q7sSpiComIF.cpp @@ -0,0 +1,9 @@ +#include + +Q7sSpiComIF::Q7sSpiComIF(object_id_t objectId, GpioIF* gpioComIF) : + SpiComIF(objectId, gpioComIF) { +} + +Q7sSpiComIF::~Q7sSpiComIF() { +} + diff --git a/bsp_q7s/spi/Q7sSpiComIF.h b/bsp_q7s/spi/Q7sSpiComIF.h new file mode 100644 index 00000000..a10d63dd --- /dev/null +++ b/bsp_q7s/spi/Q7sSpiComIF.h @@ -0,0 +1,33 @@ +#ifndef BSP_Q7S_SPI_Q7SSPICOMIF_H_ +#define BSP_Q7S_SPI_Q7SSPICOMIF_H_ + +#include + + +/** + * @brief This additional communication interface is required because the SPI busses behind the + * devices "/dev/spi2.0" and "dev/spidev3.0" are multiplexed to one SPI interface. + * This was necessary because the processing system spi (/dev/spi2.0) does not support + * frequencies lower than 650 kHz. To reach lower frequencies also the CPU frequency must + * be reduced which leads to other effects compromising kernel drivers. + * The nano avionics reaction wheels require a spi frequency between 150 kHz and 300 kHz + * why an additional AXI SPI core has been implemented in the programmable logic. However, + * the spi frequency of the AXI SPI core is not configurable during runtime. Therefore, + * this communication interface multiplexes either the hard-wired SPI or the AXI SPI to + * the SPI interface. The multiplexing is performed via a GPIO connected to a VHDL + * module responsible for switching between the to SPI peripherals. + */ +class Q7sSpiComIF: public SpiComIF { +public: + /** + * @brief Constructor + * + * @param objectId + * @param gpioComIF + * @param gpioSwitchId The gpio ID of the GPIO connected to the SPI mux module in the PL. + */ + Q7sSpiComIF(object_id_t objectId, GpioIF* gpioComIF, gpioId_t gpioSwitchId); + virtual ~Q7sSpiComIF(); +}; + +#endif /* BSP_Q7S_SPI_Q7SSPICOMIF_H_ */ diff --git a/bsp_q7s/spiCallbacks/CMakeLists.txt b/bsp_q7s/spiCallbacks/CMakeLists.txt new file mode 100644 index 00000000..59d507e6 --- /dev/null +++ b/bsp_q7s/spiCallbacks/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(${TARGET_NAME} PRIVATE + rwSpiCallback.cpp +) diff --git a/bsp_q7s/spiCallbacks/rwSpiCallback.cpp b/bsp_q7s/spiCallbacks/rwSpiCallback.cpp new file mode 100644 index 00000000..f05fbbdf --- /dev/null +++ b/bsp_q7s/spiCallbacks/rwSpiCallback.cpp @@ -0,0 +1,236 @@ +#include +#include +#include +#include +#include +#include "devices/gpioIds.h" + +namespace rwSpiCallback { + +ReturnValue_t spiCallback(SpiComIF* comIf, SpiCookie *cookie, const uint8_t *sendData, + size_t sendLen, void* args) { + + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + + RwHandler* handler = reinterpret_cast(args); + if(handler == nullptr) { + sif::error << "rwSpiCallback::spiCallback: Pointer to handler is invalid" + << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + uint8_t writeBuffer[2]; + uint8_t writeSize = 0; + + int fileDescriptor = 0; + std::string device = cookie->getSpiDevice(); + UnixFileGuard fileHelper(device, &fileDescriptor, O_RDWR, "rwSpiCallback::spiCallback: "); + if(fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) { + sif::error << "rwSpiCallback::spiCallback: Failed to open device file" << std::endl; + return SpiComIF::OPENING_FILE_FAILED; + } + spi::SpiModes spiMode = spi::SpiModes::MODE_0; + uint32_t spiSpeed = 0; + cookie->getSpiParameters(spiMode, spiSpeed, nullptr); + comIf->setSpiSpeedAndMode(fileDescriptor, spiMode, spiSpeed); + + gpioId_t gpioId = cookie->getChipSelectPin(); + GpioIF* gpioIF = comIf->getGpioInterface(); + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; + uint32_t timeoutMs = 0; + MutexIF* mutex = comIf->getMutex(&timeoutType, &timeoutMs); + if(mutex == nullptr or gpioIF == nullptr) { + sif::debug << "rwSpiCallback::spiCallback: Mutex or GPIO interface invalid" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + result = mutex->lockMutex(timeoutType, timeoutMs); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::debug << "rwSpiCallback::spiCallback: Failed to lock mutex" << std::endl; + return result; + } + + /** Disconnect PS SPI peripheral and select AXI SPI core */ + if(gpioIF->pullHigh(gpioIds::SPI_MUX) != HasReturnvaluesIF::RETURN_OK) { + sif::error << "rwSpiCallback::spiCallback: Failed to pull spi mux gpio high" << std::endl; + } + + /** Sending frame start sign */ + writeBuffer[0] = 0x7E; + writeSize = 1; + + // Pull SPI CS low. For now, no support for active high given + if(gpioId != gpio::NO_GPIO) { + if(gpioIF->pullLow(gpioId) != HasReturnvaluesIF::RETURN_OK) { + sif::error << "rwSpiCallback::spiCallback: Failed to pull chip select low" << std::endl; + } + } + + if (write(fileDescriptor, writeBuffer, writeSize) != static_cast(writeSize)) { + sif::error << "rwSpiCallback::spiCallback: Write failed!" << std::endl; + closeSpi(gpioId, gpioIF, mutex); + return RwHandler::SPI_WRITE_FAILURE; + } + + /** Encoding and sending command */ + size_t idx = 0; + while(idx < sendLen) { + switch(*(sendData + idx)) { + case 0x7E: + writeBuffer[0] = 0x7D; + writeBuffer[1] = 0x5E; + writeSize = 2; + break; + case 0x7D: + writeBuffer[0] = 0x7D; + writeBuffer[1] = 0x5D; + writeSize = 2; + break; + default: + writeBuffer[0] = *(sendData + idx); + writeSize = 1; + break; + } + if (write(fileDescriptor, writeBuffer, writeSize) != static_cast(writeSize)) { + sif::error << "rwSpiCallback::spiCallback: Write failed!" << std::endl; + closeSpi(gpioId, gpioIF, mutex); + return RwHandler::SPI_WRITE_FAILURE; + } + idx++; + } + + /** Sending frame end sign */ + writeBuffer[0] = 0x7E; + writeSize = 1; + + if (write(fileDescriptor, writeBuffer, writeSize) != static_cast(writeSize)) { + sif::error << "rwSpiCallback::spiCallback: Write failed!" << std::endl; + closeSpi(gpioId, gpioIF, mutex); + return RwHandler::SPI_WRITE_FAILURE; + } + + uint8_t* rxBuf = nullptr; + result = comIf->getReadBuffer(cookie->getSpiAddress(), &rxBuf); + if(result != HasReturnvaluesIF::RETURN_OK) { + closeSpi(gpioId, gpioIF, mutex); + return result; + } + + size_t replyBufferSize = cookie->getMaxBufferSize(); + + /** There must be a delay of 20 ms after sending the command */ + usleep(RwDefinitions::SPI_REPLY_DELAY); + + /** + * The reaction wheel responds with empty frames while preparing the reply data. + * However, receiving more than 5 empty frames will be interpreted as an error. + */ + uint8_t byteRead = 0; + for (int idx = 0; idx < 10; idx++) { + if(read(fileDescriptor, &byteRead, 1) != 1) { + sif::error << "rwSpiCallback::spiCallback: Read failed" << std::endl; + closeSpi(gpioId, gpioIF, mutex); + return RwHandler::SPI_READ_FAILURE; + } + + if (byteRead != 0x7E) { + break; + } + + if (idx == 9) { + sif::error << "rwSpiCallback::spiCallback: Empty frame timeout" << std::endl; + closeSpi(gpioId, gpioIF, mutex); + return RwHandler::NO_REPLY; + } + } + + size_t decodedFrameLen = 0; + while(decodedFrameLen < replyBufferSize) { + + /** First byte already read in */ + if (decodedFrameLen != 0) { + byteRead = 0; + if(read(fileDescriptor, &byteRead, 1) != 1) { + sif::error << "rwSpiCallback::spiCallback: Read failed" << std::endl; + result = RwHandler::SPI_READ_FAILURE; + break; + } + } + + if (byteRead == 0x7E) { + /** Reached end of frame */ + break; + } + else if (byteRead == 0x7D) { + if(read(fileDescriptor, &byteRead, 1) != 1) { + sif::error << "rwSpiCallback::spiCallback: Read failed" << std::endl; + result = RwHandler::SPI_READ_FAILURE; + break; + } + if (byteRead == 0x5E) { + *(rxBuf + decodedFrameLen) = 0x7E; + decodedFrameLen++; + continue; + } + else if (byteRead == 0x5D) { + *(rxBuf + decodedFrameLen) = 0x7D; + decodedFrameLen++; + continue; + } + else { + sif::error << "rwSpiCallback::spiCallback: Invalid substitute" << std::endl; + closeSpi(gpioId, gpioIF, mutex); + result = RwHandler::INVALID_SUBSTITUTE; + break; + } + } + else { + *(rxBuf + decodedFrameLen) = byteRead; + decodedFrameLen++; + continue; + } + + /** + * There might be the unlikely case that each byte in a get-telemetry reply has been + * replaced by its substitute. Than the next byte must correspond to the end sign 0x7E. + * Otherwise there might be something wrong. + */ + if (decodedFrameLen == replyBufferSize) { + if(read(fileDescriptor, &byteRead, 1) != 1) { + sif::error << "rwSpiCallback::spiCallback: Failed to read last byte" << std::endl; + result = RwHandler::SPI_READ_FAILURE; + break; + } + if (byteRead != 0x7E) { + sif::error << "rwSpiCallback::spiCallback: Missing end sign 0x7E" << std::endl; + decodedFrameLen--; + result = RwHandler::MISSING_END_SIGN; + break; + } + } + result = HasReturnvaluesIF::RETURN_OK; + } + + cookie->assignTransferSize(decodedFrameLen); + + closeSpi(gpioId, gpioIF, mutex); + + return result; +} + +void closeSpi (gpioId_t gpioId, GpioIF* gpioIF, MutexIF* mutex) { + if(gpioId != gpio::NO_GPIO) { + if (gpioIF->pullHigh(gpioId) != HasReturnvaluesIF::RETURN_OK) { + sif::error << "closeSpi: Failed to pull chip select high" << std::endl; + } + } + if(mutex->unlockMutex() != HasReturnvaluesIF::RETURN_OK) { + sif::error << "rwSpiCallback::closeSpi: Failed to unlock mutex" << std::endl;; + } + + /** Route SPI interface again to PS SPI peripheral */ + if(gpioIF->pullLow(gpioIds::SPI_MUX) != HasReturnvaluesIF::RETURN_OK) { + sif::error << "rwSpiCallback::spiCallback: Failed to pull spi mux gpio low" << std::endl; + } +} +} diff --git a/bsp_q7s/spiCallbacks/rwSpiCallback.h b/bsp_q7s/spiCallbacks/rwSpiCallback.h new file mode 100644 index 00000000..e5a79e64 --- /dev/null +++ b/bsp_q7s/spiCallbacks/rwSpiCallback.h @@ -0,0 +1,44 @@ +#ifndef BSP_Q7S_RW_SPI_CALLBACK_H_ +#define BSP_Q7S_RW_SPI_CALLBACK_H_ + +#include +#include +#include + + +namespace rwSpiCallback { + +/** + * @brief This is the callback function to send commands to the nano avionics reaction wheels and + * receive the replies. + * + * @details The data to sent are additionally encoded according to the HDLC framing defined in the + * datasheet of the reaction wheels: + * https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/ + * Arbeitsdaten/08_Used%20Components/Nanoavionics_Reactionwheels&fileid=181622 + * Each command entails exactly one reply which will also be read in and decoded by this + * function. + * Because the reaction wheels require a spi clock frequency of maximum 300 kHZ and minimum + * 150 kHz which is not supported by the processing system SPI peripheral an AXI SPI core + * has been implemented in the programmable logic. This AXI SPI core works with a fixed + * frequency of 250 kHz. + * To allow the parallel usage of the same physical SPI bus, a VHDL module has been + * implemented which is able to disconnect the hard-wired SPI peripheral of the PS and + * route the AXI SPI to the SPI lines. + * To switch between the to SPI peripherals, an EMIO is used which will also be controlled + * by this function. + */ +ReturnValue_t spiCallback(SpiComIF* comIf, SpiCookie *cookie, const uint8_t *sendData, + size_t sendLen, void* args); + +/** + * @brief This function closes a spi session. Pulls the chip select to high an releases the + * mutex. + * @param gpioId Gpio ID of chip select + * @param gpioIF Pointer to gpio interface to drive the chip select + * @param mutex The spi mutex + */ +void closeSpi(gpioId_t gpioId, GpioIF* gpioIF, MutexIF* mutex); + +} +#endif /* BSP_Q7S_RW_SPI_CALLBACK_H_ */ diff --git a/cmake/scripts/Linux/create_cmake_debug_cfg.sh b/cmake/scripts/Linux/make_debug_cfg.sh similarity index 67% rename from cmake/scripts/Linux/create_cmake_debug_cfg.sh rename to cmake/scripts/Linux/make_debug_cfg.sh index 1207884e..dc21896d 100755 --- a/cmake/scripts/Linux/create_cmake_debug_cfg.sh +++ b/cmake/scripts/Linux/make_debug_cfg.sh @@ -17,9 +17,16 @@ fi build_generator="Unix Makefiles" 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 -python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug" -l "${builddir}" +${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 67% rename from cmake/scripts/Linux/create_cmake_release_cfg.sh rename to cmake/scripts/Linux/make_release_cfg.sh index 4412e671..95d87e70 100755 --- a/cmake/scripts/Linux/create_cmake_release_cfg.sh +++ b/cmake/scripts/Linux/make_release_cfg.sh @@ -17,9 +17,15 @@ fi build_generator="Unix Makefiles" os_fsfw="linux" builddir="build-Release-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 -python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug" -l "${builddir}" +${python} cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "release" -l "${builddir}" # Use this if commands are added which should not be printed # set +x 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/create_cmake_relwithdeb_cfg.sh b/cmake/scripts/Q7S/make_debug_cfg.sh similarity index 63% rename from cmake/scripts/Q7S/create_cmake_relwithdeb_cfg.sh rename to cmake/scripts/Q7S/make_debug_cfg.sh index 121f2d7e..4613d36a 100755 --- a/cmake/scripts/Q7S/create_cmake_relwithdeb_cfg.sh +++ b/cmake/scripts/Q7S/make_debug_cfg.sh @@ -16,14 +16,20 @@ fi os_fsfw="linux" tgt_bsp="arm/q7s" -build_dir="build-Release-Q7S" +build_dir="build-Debug-Q7S" build_generator="" if [ "${OS}" = "Windows_NT" ]; then build_generator="MinGW Makefiles" + python="py" # Could be other OS but this works for now. else build_generator="Unix Makefiles" + python="python3" fi -python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "reldeb" -t "${tgt_bsp}" \ - -l"${build_dir}" +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}" +# set +x + diff --git a/cmake/scripts/Q7S/create_cmake_debug_cfg.sh b/cmake/scripts/Q7S/make_release_cfg.sh similarity index 70% rename from cmake/scripts/Q7S/create_cmake_debug_cfg.sh rename to cmake/scripts/Q7S/make_release_cfg.sh index 4875c59a..9d7992f3 100755 --- a/cmake/scripts/Q7S/create_cmake_debug_cfg.sh +++ b/cmake/scripts/Q7S/make_release_cfg.sh @@ -20,10 +20,15 @@ build_dir="build-Debug-Q7S" build_generator="" if [ "${OS}" = "Windows_NT" ]; then build_generator="MinGW Makefiles" + python="py" # Could be other OS but this works for now. else build_generator="Unix Makefiles" + python="python3" fi -python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug" -t "${tgt_bsp}" \ +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}" +# set +x diff --git a/cmake/scripts/Q7S/ninja_debug_cfg.sh b/cmake/scripts/Q7S/ninja_debug_cfg.sh new file mode 100755 index 00000000..2d3b333f --- /dev/null +++ b/cmake/scripts/Q7S/ninja_debug_cfg.sh @@ -0,0 +1,33 @@ +#!/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 "cmake_build_config.py not found in upper directories!" + exit 1 +fi + +os_fsfw="linux" +tgt_bsp="arm/q7s" +build_dir="build-Debug-Q7S" +build_generator="Ninja" +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" -t "${tgt_bsp}" \ + -l"${build_dir}" +# set +x + diff --git a/cmake/scripts/Q7S/create_cmake_release_cfg.sh b/cmake/scripts/Q7S/simple/simple_make_debug_cfg.sh similarity index 59% rename from cmake/scripts/Q7S/create_cmake_release_cfg.sh rename to cmake/scripts/Q7S/simple/simple_make_debug_cfg.sh index 0e2c543c..8a6c7b3f 100755 --- a/cmake/scripts/Q7S/create_cmake_release_cfg.sh +++ b/cmake/scripts/Q7S/simple/simple_make_debug_cfg.sh @@ -16,14 +16,20 @@ fi os_fsfw="linux" tgt_bsp="arm/q7s" -build_dir="build-Release-Q7S" +build_dir="build-Simple-Q7S" build_generator="" +definitions="Q7S_SIMPLE_MODE=On" if [ "${OS}" = "Windows_NT" ]; then build_generator="MinGW Makefiles" + python="py" # Could be other OS but this works for now. else build_generator="Unix Makefiles" + python="python3" fi -python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "release" -t "${tgt_bsp}" \ - -l"${build_dir}" +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}" +# set +x diff --git a/cmake/scripts/Q7S/simple/simple_ninja_debug_cfg.sh b/cmake/scripts/Q7S/simple/simple_ninja_debug_cfg.sh new file mode 100755 index 00000000..965aae45 --- /dev/null +++ b/cmake/scripts/Q7S/simple/simple_ninja_debug_cfg.sh @@ -0,0 +1,34 @@ +#!/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 "cmake_build_config.py not found in upper directories!" + exit 1 +fi + +os_fsfw="linux" +tgt_bsp="arm/q7s" +build_dir="build-Simple-Q7S" +build_generator="Ninja" +definitions="Q7S_SIMPLE_MODE=On" +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" -t "${tgt_bsp}" \ + -l "${build_dir}" -d "${definitions}" +# set +x + diff --git a/cmake/scripts/RPi/create_cmake_size_cfg.sh b/cmake/scripts/RPi/create_cmake_size_cfg.sh deleted file mode 100755 index f7bad84e..00000000 --- a/cmake/scripts/RPi/create_cmake_size_cfg.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/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 "cmake_build_config.py not found in upper directories!" - exit 1 -fi - -os_fsfw="linux" -tgt_bsp="arm/raspberrypi" -build_generator="" -if [ "${OS}" = "Windows_NT" ]; then - build_generator="MinGW Makefiles" -# Could be other OS but this works for now. -else - build_generator="Unix Makefiles" -fi - -python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "size" -t "${tgt_bsp}" diff --git a/cmake/scripts/RPi/create_cmake_debug_cfg.sh b/cmake/scripts/RPi/make_debug_cfg.sh similarity index 67% rename from cmake/scripts/RPi/create_cmake_debug_cfg.sh rename to cmake/scripts/RPi/make_debug_cfg.sh index 57561846..dbb178de 100755 --- a/cmake/scripts/RPi/create_cmake_debug_cfg.sh +++ b/cmake/scripts/RPi/make_debug_cfg.sh @@ -20,10 +20,16 @@ build_generator="" build_dir="build-Debug-RPi" if [ "${OS}" = "Windows_NT" ]; then build_generator="MinGW Makefiles" + python="py" # Could be other OS but this works for now. else build_generator="Unix Makefiles" + python="python3" fi -python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug" -t "${tgt_bsp}" \ - -l"${build_dir}" +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}" +# set +x + diff --git a/cmake/scripts/RPi/create_cmake_release_cfg.sh b/cmake/scripts/RPi/make_release_cfg.sh similarity index 100% rename from cmake/scripts/RPi/create_cmake_release_cfg.sh rename to cmake/scripts/RPi/make_release_cfg.sh diff --git a/cmake/scripts/RPi/create_cmake_relwithdeb_cfg.sh b/cmake/scripts/RPi/ninja_debug_cfg.sh similarity index 57% rename from cmake/scripts/RPi/create_cmake_relwithdeb_cfg.sh rename to cmake/scripts/RPi/ninja_debug_cfg.sh index de7651a7..3fa0e5f4 100755 --- a/cmake/scripts/RPi/create_cmake_relwithdeb_cfg.sh +++ b/cmake/scripts/RPi/ninja_debug_cfg.sh @@ -16,14 +16,18 @@ fi os_fsfw="linux" tgt_bsp="arm/raspberrypi" -build_generator="" -build_dir="RelWithDeb-RPi" +build_generator="Ninja" +build_dir="build-Debug-RPi" if [ "${OS}" = "Windows_NT" ]; then - build_generator="MinGW Makefiles" + python="py" # Could be other OS but this works for now. else - build_generator="Unix Makefiles" + python="python3" fi -python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "reldeb" -t "${tgt_bsp}" \ - -l"${build_dir}" +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}" +# 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/common/config/commonClassIds.h b/common/config/commonClassIds.h index 7a53bdf0..8a4a8121 100644 --- a/common/config/commonClassIds.h +++ b/common/config/commonClassIds.h @@ -13,6 +13,7 @@ enum commonClassIds: uint8_t { HEATER_HANDLER, //HEATER SYRLINKS_HANDLER, //SYRLINKS IMTQ_HANDLER, //IMTQ + RW_HANDLER, //Reaction Wheels PLOC_HANDLER, //PLOC SUS_HANDLER, //SUSS CCSDS_IP_CORE_BRIDGE, // IP Core interface diff --git a/common/config/commonObjects.h b/common/config/commonObjects.h index 3baf58b0..1fb755e3 100644 --- a/common/config/commonObjects.h +++ b/common/config/commonObjects.h @@ -6,48 +6,77 @@ namespace objects { 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, + CCSDS_PACKET_DISTRIBUTOR = 0x50000100, + PUS_PACKET_DISTRIBUTOR = 0x50000200, + UDP_BRIDGE = 0x50000300, + UDP_POLLING_TASK = 0x50000400, /* 0x43 ('C') for Controllers */ - THERMAL_CONTROLLER = 0x43001000, - ATTITUDE_CONTROLLER = 0x43002000, - ACS_CONTROLLER = 0x43003000, - CORE_CONTROLLER = 0x43004000, + THERMAL_CONTROLLER = 0x43400001, + ACS_CONTROLLER = 0x43100002, + CORE_CONTROLLER = 0x43000003, - /* 0x44 ('D') for device handlers */ - P60DOCK_HANDLER = 0x44000001, - PDU1_HANDLER = 0x44000002, - PDU2_HANDLER = 0x44000003, - ACU_HANDLER = 0x44000004, - TMP1075_HANDLER_1 = 0x44000005, - TMP1075_HANDLER_2 = 0x44000006, - MGM_0_LIS3_HANDLER = 0x44000007, - MGM_1_RM3100_HANDLER = 0x44000008, - MGM_2_LIS3_HANDLER = 0x44000009, - MGM_3_RM3100_HANDLER = 0x44000010, - GYRO_0_ADIS_HANDLER = 0x44000011, - GYRO_1_L3G_HANDLER = 0x44000012, - GYRO_2_L3G_HANDLER = 0x44000013, + /* 0x44 ('D') for device handlers */ + P60DOCK_HANDLER = 0x44250000, + PDU1_HANDLER = 0x44250001, + PDU2_HANDLER = 0x44250002, + ACU_HANDLER = 0x44250003, + TMP1075_HANDLER_1 = 0x44420004, + TMP1075_HANDLER_2 = 0x44420005, + MGM_0_LIS3_HANDLER = 0x44120006, + MGM_1_RM3100_HANDLER = 0x44120107, + MGM_2_LIS3_HANDLER = 0x44120208, + MGM_3_RM3100_HANDLER = 0x44120309, + GYRO_0_ADIS_HANDLER = 0x44120010, + GYRO_1_L3G_HANDLER = 0x44120111, + GYRO_2_ADIS_HANDLER = 0x44120212, + GYRO_3_L3G_HANDLER = 0x44120313, - IMTQ_HANDLER = 0x44000014, - PLOC_HANDLER = 0x44000015, + IMTQ_HANDLER = 0x44140014, + PLOC_HANDLER = 0x44330015, - SUS_1 = 0x44000016, - SUS_2 = 0x44000017, - SUS_3 = 0x44000018, - SUS_4 = 0x44000019, - SUS_5 = 0x4400001A, - SUS_6 = 0x4400001B, - SUS_7 = 0x4400001C, - SUS_8 = 0x4400001D, - SUS_9 = 0x4400001E, - SUS_10 = 0x4400001F, - SUS_11 = 0x44000021, - SUS_12 = 0x44000022, - SUS_13 = 0x44000023, + /** + * Not yet specified which pt1000 will measure which device/location in the satellite. + * Therefore object ids are named according to the IC naming of the RTDs in the schematic. + */ + RTD_IC3 = 0x44420016, + RTD_IC4 = 0x44420017, + RTD_IC5 = 0x44420018, + RTD_IC6 = 0x44420019, + RTD_IC7 = 0x44420020, + RTD_IC8 = 0x44420021, + RTD_IC9 = 0x44420022, + RTD_IC10 = 0x44420023, + RTD_IC11 = 0x44420024, + RTD_IC12 = 0x44420025, + RTD_IC13 = 0x44420026, + RTD_IC14 = 0x44420027, + RTD_IC15 = 0x44420028, + RTD_IC16 = 0x44420029, + RTD_IC17 = 0x44420030, + RTD_IC18 = 0x44420031, + + SUS_1 = 0x44120032, + SUS_2 = 0x44120033, + SUS_3 = 0x44120034, + SUS_4 = 0x44120035, + SUS_5 = 0x44120036, + SUS_6 = 0x44120037, + SUS_7 = 0x44120038, + SUS_8 = 0x44120039, + SUS_9 = 0x44120040, + SUS_10 = 0x44120041, + SUS_11 = 0x44120042, + SUS_12 = 0x44120043, + SUS_13 = 0x44120044, + + GPS0_HANDLER = 0x44130045, + GPS1_HANDLER = 0x44130146, + + RW1 = 0x44210001, + RW2 = 0x44210002, + RW3 = 0x44210003, + RW4 = 0x44210004 }; } diff --git a/common/config/commonSubsystemIds.h b/common/config/commonSubsystemIds.h index 0bc3e1dd..bc2fe400 100644 --- a/common/config/commonSubsystemIds.h +++ b/common/config/commonSubsystemIds.h @@ -13,6 +13,7 @@ enum: uint8_t { SA_DEPL_HANDLER = 110, PLOC_HANDLER = 111, IMTQ_HANDLER = 112, + RW_HANDLER = 113, COMMON_SUBSYSTEM_ID_END }; } diff --git a/common/config/spiConf.h b/common/config/spiConf.h index 2632924d..47600eb3 100644 --- a/common/config/spiConf.h +++ b/common/config/spiConf.h @@ -26,6 +26,9 @@ static constexpr spi::SpiModes DEFAULT_MAX_1227_MODE = spi::SpiModes::MODE_3; static constexpr uint32_t DEFAULT_ADIS16507_SPEED = 976'000; static constexpr spi::SpiModes DEFAULT_ADIS16507_MODE = spi::SpiModes::MODE_3; +static constexpr uint32_t RW_SPEED = 300000; +static constexpr spi::SpiModes RW_MODE = spi::SpiModes::MODE_0; + } #endif /* COMMON_CONFIG_SPICONF_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 cae69d54..da8a4470 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit cae69d540097acba46bffa47fd7afc6a8a19bd15 +Subproject commit da8a4470734808bed4d872e47c192af694382c41 diff --git a/fsfw_hal b/fsfw_hal index fce40ebf..8ff09c95 160000 --- a/fsfw_hal +++ b/fsfw_hal @@ -1 +1 @@ -Subproject commit fce40ebf9a4a45bafedaee2fc87e5aa10e49fdcc +Subproject commit 8ff09c95a69f1f43fec6104d6cce1e788b2b870d diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv index 81459869..c895aebb 100644 --- a/generators/bsp_q7s_events.csv +++ b/generators/bsp_q7s_events.csv @@ -81,3 +81,12 @@ 11102;ACK_FAILURE;LOW; ;../../mission/devices/PlocHandler.h 11103;EXE_FAILURE;LOW; ;../../mission/devices/PlocHandler.h 11104;CRC_FAILURE_EVENT;LOW; ;../../mission/devices/PlocHandler.h +11201;SELF_TEST_I2C_FAILURE;LOW; ;../../mission/devices/IMTQHandler.h +11202;SELF_TEST_SPI_FAILURE;LOW; ;../../mission/devices/IMTQHandler.h +11203;SELF_TEST_ADC_FAILURE;LOW; ;../../mission/devices/IMTQHandler.h +11204;SELF_TEST_PWM_FAILURE;LOW; ;../../mission/devices/IMTQHandler.h +11205;SELF_TEST_TC_FAILURE;LOW; ;../../mission/devices/IMTQHandler.h +11206;SELF_TEST_MTM_RANGE_FAILURE;LOW; ;../../mission/devices/IMTQHandler.h +11207;SELF_TEST_COIL_CURRENT_FAILURE;LOW; ;../../mission/devices/IMTQHandler.h +11208;INVALID_ERROR_BYTE;LOW; ;../../mission/devices/IMTQHandler.h +11301;ERROR_STATE;HIGH; ;../../mission/devices/RwHandler.h diff --git a/generators/bsp_q7s_objects.csv b/generators/bsp_q7s_objects.csv index 8df83d6a..e0180089 100644 --- a/generators/bsp_q7s_objects.csv +++ b/generators/bsp_q7s_objects.csv @@ -1,52 +1,74 @@ 0x00005060;P60DOCK_TEST_TASK -0x44000001;P60DOCK_HANDLER -0x44000002;PDU1_HANDLER -0x44000003;PDU2_HANDLER -0x44000004;ACU_HANDLER -0x44000005;TMP1075_HANDLER_1 -0x44000006;TMP1075_HANDLER_2 -0x44000007;MGM_0_LIS3_HANDLER -0x44000008;MGM_1_RM3100_HANDLER -0x44000009;MGM_2_LIS3_HANDLER -0x44000010;MGM_3_RM3100_HANDLER -0x44000011;GYRO_0_ADIS_HANDLER -0x44000012;GYRO_1_L3G_HANDLER -0x44000013;GYRO_2_L3G_HANDLER -0x44000014;IMTQ_HANDLER -0x44000015;PLOC_HANDLER -0x44000016;SUS_1 -0x44000017;SUS_2 -0x44000018;SUS_3 -0x44000019;SUS_4 -0x4400001A;SUS_5 -0x4400001B;SUS_6 -0x4400001C;SUS_7 -0x4400001D;SUS_8 -0x4400001E;SUS_9 -0x4400001F;SUS_10 -0x44000021;SUS_11 -0x44000022;SUS_12 -0x44000023;SUS_13 -0x44001000;PCDU_HANDLER -0x44001001;SOLAR_ARRAY_DEPL_HANDLER -0x44001002;SYRLINKS_HK_HANDLER -0x47000001;GPIO_IF -0x49000001;ARDUINO_COM_IF -0x49000002;CSP_COM_IF -0x49000003;I2C_COM_IF -0x49000004;UART_COM_IF -0x49000005;SPI_COM_IF +0x43000003;CORE_CONTROLLER +0x43100002;ACS_CONTROLLER +0x43400001;THERMAL_CONTROLLER +0x44120006;MGM_0_LIS3_HANDLER +0x44120010;GYRO_0_ADIS_HANDLER +0x44120032;SUS_1 +0x44120033;SUS_2 +0x44120034;SUS_3 +0x44120035;SUS_4 +0x44120036;SUS_5 +0x44120037;SUS_6 +0x44120038;SUS_7 +0x44120039;SUS_8 +0x44120040;SUS_9 +0x44120041;SUS_10 +0x44120042;SUS_11 +0x44120043;SUS_12 +0x44120044;SUS_13 +0x44120107;MGM_1_RM3100_HANDLER +0x44120111;GYRO_1_L3G_HANDLER +0x44120208;MGM_2_LIS3_HANDLER +0x44120212;GYRO_2_ADIS_HANDLER +0x44120309;MGM_3_RM3100_HANDLER +0x44120313;GYRO_3_L3G_HANDLER +0x44130045;GPS0_HANDLER +0x44130146;GPS1_HANDLER +0x44140014;IMTQ_HANDLER +0x442000A1;PCDU_HANDLER +0x44210001;RW1 +0x44210002;RW2 +0x44210003;RW3 +0x44210004;RW4 +0x44250000;P60DOCK_HANDLER +0x44250001;PDU1_HANDLER +0x44250002;PDU2_HANDLER +0x44250003;ACU_HANDLER +0x443200A5;RAD_SENSOR +0x44330015;PLOC_HANDLER +0x444100A2;SOLAR_ARRAY_DEPL_HANDLER +0x444100A4;HEATER_HANDLER +0x44420004;TMP1075_HANDLER_1 +0x44420005;TMP1075_HANDLER_2 +0x44420016;RTD_IC3 +0x44420017;RTD_IC4 +0x44420018;RTD_IC5 +0x44420019;RTD_IC6 +0x44420020;RTD_IC7 +0x44420021;RTD_IC8 +0x44420022;RTD_IC9 +0x44420023;RTD_IC10 +0x44420024;RTD_IC11 +0x44420025;RTD_IC12 +0x44420026;RTD_IC13 +0x44420027;RTD_IC14 +0x44420028;RTD_IC15 +0x44420029;RTD_IC16 +0x44420030;RTD_IC17 +0x44420031;RTD_IC18 +0x445300A3;SYRLINKS_HK_HANDLER +0x49000000;ARDUINO_COM_IF +0x49010005;GPIO_IF +0x49020004;SPI_COM_IF +0x49030003;UART_COM_IF +0x49040002;I2C_COM_IF +0x49050001;CSP_COM_IF 0x50000100;CCSDS_PACKET_DISTRIBUTOR 0x50000200;PUS_PACKET_DISTRIBUTOR 0x50000300;UDP_BRIDGE 0x50000400;UDP_POLLING_TASK -0x51000300;PUS_SERVICE_3 -0x51000400;PUS_SERVICE_5 0x51000500;PUS_SERVICE_6 -0x51000800;PUS_SERVICE_8 -0x51002300;PUS_SERVICE_23 -0x51020100;PUS_SERVICE_201 -0x52000002;TM_FUNNEL 0x53000000;FSFW_OBJECTS_START 0x53000001;PUS_SERVICE_1_VERIFICATION 0x53000002;PUS_SERVICE_2_DEVICE_ACCESS @@ -67,27 +89,12 @@ 0x534f0300;IPC_STORE 0x53500010;TIME_STAMPER 0x53ffffff;FSFW_OBJECTS_END -0x54000003;HEATER_HANDLER -0x54000004;RTD_IC3 -0x54000005;RTD_IC4 -0x54000006;RTD_IC5 -0x54000007;RTD_IC6 -0x54000008;RTD_IC7 -0x54000009;RTD_IC8 -0x5400000A;RTD_IC9 -0x5400000B;RTD_IC10 -0x5400000C;RTD_IC11 -0x5400000D;RTD_IC12 -0x5400000E;RTD_IC13 -0x5400000F;RTD_IC14 0x54000010;SPI_TEST -0x5400001F;RTD_IC15 -0x5400002F;RTD_IC16 -0x5400003F;RTD_IC17 -0x5400004F;RTD_IC18 -0x54000050;RAD_SENSOR +0x54000020;UART_TEST 0x5400AFFE;DUMMY_HANDLER 0x5400CAFE;DUMMY_INTERFACE 0x54123456;LIBGPIOD_TEST 0x54694269;TEST_TASK +0x73000100;TM_FUNNEL +0x73500000;CCSDS_IP_CORE_BRIDGE 0xFFFFFFFF;NO_OBJECT diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index c3af08e1..9ae81646 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 83 translations. + * @brief Auto-generated event translation file. Contains 92 translations. * @details - * Generated on: 2021-06-08 17:09:32 + * Generated on: 2021-06-29 16:20:09 */ #include "translateEvents.h" @@ -88,6 +88,15 @@ const char *MEMORY_READ_RPT_CRC_FAILURE_STRING = "MEMORY_READ_RPT_CRC_FAILURE"; const char *ACK_FAILURE_STRING = "ACK_FAILURE"; const char *EXE_FAILURE_STRING = "EXE_FAILURE"; const char *CRC_FAILURE_EVENT_STRING = "CRC_FAILURE_EVENT"; +const char *SELF_TEST_I2C_FAILURE_STRING = "SELF_TEST_I2C_FAILURE"; +const char *SELF_TEST_SPI_FAILURE_STRING = "SELF_TEST_SPI_FAILURE"; +const char *SELF_TEST_ADC_FAILURE_STRING = "SELF_TEST_ADC_FAILURE"; +const char *SELF_TEST_PWM_FAILURE_STRING = "SELF_TEST_PWM_FAILURE"; +const char *SELF_TEST_TC_FAILURE_STRING = "SELF_TEST_TC_FAILURE"; +const char *SELF_TEST_MTM_RANGE_FAILURE_STRING = "SELF_TEST_MTM_RANGE_FAILURE"; +const char *SELF_TEST_COIL_CURRENT_FAILURE_STRING = "SELF_TEST_COIL_CURRENT_FAILURE"; +const char *INVALID_ERROR_BYTE_STRING = "INVALID_ERROR_BYTE"; +const char *ERROR_STATE_STRING = "ERROR_STATE"; const char * translateEvents(Event event) { switch( (event & 0xffff) ) { @@ -257,6 +266,24 @@ const char * translateEvents(Event event) { return EXE_FAILURE_STRING; case(11104): return CRC_FAILURE_EVENT_STRING; + case(11201): + return SELF_TEST_I2C_FAILURE_STRING; + case(11202): + return SELF_TEST_SPI_FAILURE_STRING; + case(11203): + return SELF_TEST_ADC_FAILURE_STRING; + case(11204): + return SELF_TEST_PWM_FAILURE_STRING; + case(11205): + return SELF_TEST_TC_FAILURE_STRING; + case(11206): + return SELF_TEST_MTM_RANGE_FAILURE_STRING; + case(11207): + return SELF_TEST_COIL_CURRENT_FAILURE_STRING; + case(11208): + return INVALID_ERROR_BYTE_STRING; + case(11301): + return ERROR_STATE_STRING; default: return "UNKNOWN_EVENT"; } diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index 47b55435..2068158b 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -1,27 +1,17 @@ -/** +/** * @brief Auto-generated object translation file. * @details - * Contains 93 translations. - * Generated on: 2021-05-18 16:48:46 + * Contains 100 translations. + * Generated on: 2021-06-29 16:19:57 */ #include "translateObjects.h" const char *P60DOCK_TEST_TASK_STRING = "P60DOCK_TEST_TASK"; -const char *P60DOCK_HANDLER_STRING = "P60DOCK_HANDLER"; -const char *PDU1_HANDLER_STRING = "PDU1_HANDLER"; -const char *PDU2_HANDLER_STRING = "PDU2_HANDLER"; -const char *ACU_HANDLER_STRING = "ACU_HANDLER"; -const char *TMP1075_HANDLER_1_STRING = "TMP1075_HANDLER_1"; -const char *TMP1075_HANDLER_2_STRING = "TMP1075_HANDLER_2"; +const char *CORE_CONTROLLER_STRING = "CORE_CONTROLLER"; +const char *ACS_CONTROLLER_STRING = "ACS_CONTROLLER"; +const char *THERMAL_CONTROLLER_STRING = "THERMAL_CONTROLLER"; const char *MGM_0_LIS3_HANDLER_STRING = "MGM_0_LIS3_HANDLER"; -const char *MGM_1_RM3100_HANDLER_STRING = "MGM_1_RM3100_HANDLER"; -const char *MGM_2_LIS3_HANDLER_STRING = "MGM_2_LIS3_HANDLER"; -const char *MGM_3_RM3100_HANDLER_STRING = "MGM_3_RM3100_HANDLER"; const char *GYRO_0_ADIS_HANDLER_STRING = "GYRO_0_ADIS_HANDLER"; -const char *GYRO_1_L3G_HANDLER_STRING = "GYRO_1_L3G_HANDLER"; -const char *GYRO_2_L3G_HANDLER_STRING = "GYRO_2_L3G_HANDLER"; -const char *IMTQ_HANDLER_STRING = "IMTQ_HANDLER"; -const char *PLOC_HANDLER_STRING = "PLOC_HANDLER"; const char *SUS_1_STRING = "SUS_1"; const char *SUS_2_STRING = "SUS_2"; const char *SUS_3_STRING = "SUS_3"; @@ -35,26 +25,58 @@ const char *SUS_10_STRING = "SUS_10"; const char *SUS_11_STRING = "SUS_11"; const char *SUS_12_STRING = "SUS_12"; const char *SUS_13_STRING = "SUS_13"; +const char *MGM_1_RM3100_HANDLER_STRING = "MGM_1_RM3100_HANDLER"; +const char *GYRO_1_L3G_HANDLER_STRING = "GYRO_1_L3G_HANDLER"; +const char *MGM_2_LIS3_HANDLER_STRING = "MGM_2_LIS3_HANDLER"; +const char *GYRO_2_ADIS_HANDLER_STRING = "GYRO_2_ADIS_HANDLER"; +const char *MGM_3_RM3100_HANDLER_STRING = "MGM_3_RM3100_HANDLER"; +const char *GYRO_3_L3G_HANDLER_STRING = "GYRO_3_L3G_HANDLER"; +const char *GPS0_HANDLER_STRING = "GPS0_HANDLER"; +const char *GPS1_HANDLER_STRING = "GPS1_HANDLER"; +const char *IMTQ_HANDLER_STRING = "IMTQ_HANDLER"; const char *PCDU_HANDLER_STRING = "PCDU_HANDLER"; +const char *RW1_STRING = "RW1"; +const char *RW2_STRING = "RW2"; +const char *RW3_STRING = "RW3"; +const char *RW4_STRING = "RW4"; +const char *P60DOCK_HANDLER_STRING = "P60DOCK_HANDLER"; +const char *PDU1_HANDLER_STRING = "PDU1_HANDLER"; +const char *PDU2_HANDLER_STRING = "PDU2_HANDLER"; +const char *ACU_HANDLER_STRING = "ACU_HANDLER"; +const char *RAD_SENSOR_STRING = "RAD_SENSOR"; +const char *PLOC_HANDLER_STRING = "PLOC_HANDLER"; const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER"; +const char *HEATER_HANDLER_STRING = "HEATER_HANDLER"; +const char *TMP1075_HANDLER_1_STRING = "TMP1075_HANDLER_1"; +const char *TMP1075_HANDLER_2_STRING = "TMP1075_HANDLER_2"; +const char *RTD_IC3_STRING = "RTD_IC3"; +const char *RTD_IC4_STRING = "RTD_IC4"; +const char *RTD_IC5_STRING = "RTD_IC5"; +const char *RTD_IC6_STRING = "RTD_IC6"; +const char *RTD_IC7_STRING = "RTD_IC7"; +const char *RTD_IC8_STRING = "RTD_IC8"; +const char *RTD_IC9_STRING = "RTD_IC9"; +const char *RTD_IC10_STRING = "RTD_IC10"; +const char *RTD_IC11_STRING = "RTD_IC11"; +const char *RTD_IC12_STRING = "RTD_IC12"; +const char *RTD_IC13_STRING = "RTD_IC13"; +const char *RTD_IC14_STRING = "RTD_IC14"; +const char *RTD_IC15_STRING = "RTD_IC15"; +const char *RTD_IC16_STRING = "RTD_IC16"; +const char *RTD_IC17_STRING = "RTD_IC17"; +const char *RTD_IC18_STRING = "RTD_IC18"; const char *SYRLINKS_HK_HANDLER_STRING = "SYRLINKS_HK_HANDLER"; -const char *GPIO_IF_STRING = "GPIO_IF"; const char *ARDUINO_COM_IF_STRING = "ARDUINO_COM_IF"; -const char *CSP_COM_IF_STRING = "CSP_COM_IF"; -const char *I2C_COM_IF_STRING = "I2C_COM_IF"; -const char *UART_COM_IF_STRING = "UART_COM_IF"; +const char *GPIO_IF_STRING = "GPIO_IF"; const char *SPI_COM_IF_STRING = "SPI_COM_IF"; +const char *UART_COM_IF_STRING = "UART_COM_IF"; +const char *I2C_COM_IF_STRING = "I2C_COM_IF"; +const char *CSP_COM_IF_STRING = "CSP_COM_IF"; const char *CCSDS_PACKET_DISTRIBUTOR_STRING = "CCSDS_PACKET_DISTRIBUTOR"; const char *PUS_PACKET_DISTRIBUTOR_STRING = "PUS_PACKET_DISTRIBUTOR"; const char *UDP_BRIDGE_STRING = "UDP_BRIDGE"; const char *UDP_POLLING_TASK_STRING = "UDP_POLLING_TASK"; -const char *PUS_SERVICE_3_STRING = "PUS_SERVICE_3"; -const char *PUS_SERVICE_5_STRING = "PUS_SERVICE_5"; const char *PUS_SERVICE_6_STRING = "PUS_SERVICE_6"; -const char *PUS_SERVICE_8_STRING = "PUS_SERVICE_8"; -const char *PUS_SERVICE_23_STRING = "PUS_SERVICE_23"; -const char *PUS_SERVICE_201_STRING = "PUS_SERVICE_201"; -const char *TM_FUNNEL_STRING = "TM_FUNNEL"; const char *FSFW_OBJECTS_START_STRING = "FSFW_OBJECTS_START"; const char *PUS_SERVICE_1_VERIFICATION_STRING = "PUS_SERVICE_1_VERIFICATION"; const char *PUS_SERVICE_2_DEVICE_ACCESS_STRING = "PUS_SERVICE_2_DEVICE_ACCESS"; @@ -75,109 +97,150 @@ const char *TM_STORE_STRING = "TM_STORE"; const char *IPC_STORE_STRING = "IPC_STORE"; const char *TIME_STAMPER_STRING = "TIME_STAMPER"; const char *FSFW_OBJECTS_END_STRING = "FSFW_OBJECTS_END"; -const char *HEATER_HANDLER_STRING = "HEATER_HANDLER"; -const char *RTD_IC3_STRING = "RTD_IC3"; -const char *RTD_IC4_STRING = "RTD_IC4"; -const char *RTD_IC5_STRING = "RTD_IC5"; -const char *RTD_IC6_STRING = "RTD_IC6"; -const char *RTD_IC7_STRING = "RTD_IC7"; -const char *RTD_IC8_STRING = "RTD_IC8"; -const char *RTD_IC9_STRING = "RTD_IC9"; -const char *RTD_IC10_STRING = "RTD_IC10"; -const char *RTD_IC11_STRING = "RTD_IC11"; -const char *RTD_IC12_STRING = "RTD_IC12"; -const char *RTD_IC13_STRING = "RTD_IC13"; -const char *RTD_IC14_STRING = "RTD_IC14"; const char *SPI_TEST_STRING = "SPI_TEST"; -const char *RTD_IC15_STRING = "RTD_IC15"; -const char *RTD_IC16_STRING = "RTD_IC16"; -const char *RTD_IC17_STRING = "RTD_IC17"; -const char *RTD_IC18_STRING = "RTD_IC18"; -const char *RAD_SENSOR_STRING = "RAD_SENSOR"; +const char *UART_TEST_STRING = "UART_TEST"; const char *DUMMY_HANDLER_STRING = "DUMMY_HANDLER"; const char *DUMMY_INTERFACE_STRING = "DUMMY_INTERFACE"; const char *LIBGPIOD_TEST_STRING = "LIBGPIOD_TEST"; const char *TEST_TASK_STRING = "TEST_TASK"; +const char *TM_FUNNEL_STRING = "TM_FUNNEL"; +const char *CCSDS_IP_CORE_BRIDGE_STRING = "CCSDS_IP_CORE_BRIDGE"; const char *NO_OBJECT_STRING = "NO_OBJECT"; const char* translateObject(object_id_t object) { switch( (object & 0xFFFFFFFF) ) { case 0x00005060: return P60DOCK_TEST_TASK_STRING; - case 0x44000001: - return P60DOCK_HANDLER_STRING; - case 0x44000002: - return PDU1_HANDLER_STRING; - case 0x44000003: - return PDU2_HANDLER_STRING; - case 0x44000004: - return ACU_HANDLER_STRING; - case 0x44000005: - return TMP1075_HANDLER_1_STRING; - case 0x44000006: - return TMP1075_HANDLER_2_STRING; - case 0x44000007: + case 0x43000003: + return CORE_CONTROLLER_STRING; + case 0x43100002: + return ACS_CONTROLLER_STRING; + case 0x43400001: + return THERMAL_CONTROLLER_STRING; + case 0x44120006: return MGM_0_LIS3_HANDLER_STRING; - case 0x44000008: - return MGM_1_RM3100_HANDLER_STRING; - case 0x44000009: - return MGM_2_LIS3_HANDLER_STRING; - case 0x44000010: - return MGM_3_RM3100_HANDLER_STRING; - case 0x44000011: + case 0x44120010: return GYRO_0_ADIS_HANDLER_STRING; - case 0x44000012: - return GYRO_1_L3G_HANDLER_STRING; - case 0x44000013: - return GYRO_2_L3G_HANDLER_STRING; - case 0x44000014: - return IMTQ_HANDLER_STRING; - case 0x44000015: - return PLOC_HANDLER_STRING; - case 0x44000016: + case 0x44120032: return SUS_1_STRING; - case 0x44000017: + case 0x44120033: return SUS_2_STRING; - case 0x44000018: + case 0x44120034: return SUS_3_STRING; - case 0x44000019: + case 0x44120035: return SUS_4_STRING; - case 0x4400001A: + case 0x44120036: return SUS_5_STRING; - case 0x4400001B: + case 0x44120037: return SUS_6_STRING; - case 0x4400001C: + case 0x44120038: return SUS_7_STRING; - case 0x4400001D: + case 0x44120039: return SUS_8_STRING; - case 0x4400001E: + case 0x44120040: return SUS_9_STRING; - case 0x4400001F: + case 0x44120041: return SUS_10_STRING; - case 0x44000021: + case 0x44120042: return SUS_11_STRING; - case 0x44000022: + case 0x44120043: return SUS_12_STRING; - case 0x44000023: + case 0x44120044: return SUS_13_STRING; - case 0x44001000: + case 0x44120107: + return MGM_1_RM3100_HANDLER_STRING; + case 0x44120111: + return GYRO_1_L3G_HANDLER_STRING; + case 0x44120208: + return MGM_2_LIS3_HANDLER_STRING; + case 0x44120212: + return GYRO_2_ADIS_HANDLER_STRING; + case 0x44120309: + return MGM_3_RM3100_HANDLER_STRING; + case 0x44120313: + return GYRO_3_L3G_HANDLER_STRING; + case 0x44130045: + return GPS0_HANDLER_STRING; + case 0x44130146: + return GPS1_HANDLER_STRING; + case 0x44140014: + return IMTQ_HANDLER_STRING; + case 0x442000A1: return PCDU_HANDLER_STRING; - case 0x44001001: + case 0x44210001: + return RW1_STRING; + case 0x44210002: + return RW2_STRING; + case 0x44210003: + return RW3_STRING; + case 0x44210004: + return RW4_STRING; + case 0x44250000: + return P60DOCK_HANDLER_STRING; + case 0x44250001: + return PDU1_HANDLER_STRING; + case 0x44250002: + return PDU2_HANDLER_STRING; + case 0x44250003: + return ACU_HANDLER_STRING; + case 0x443200A5: + return RAD_SENSOR_STRING; + case 0x44330015: + return PLOC_HANDLER_STRING; + case 0x444100A2: return SOLAR_ARRAY_DEPL_HANDLER_STRING; - case 0x44001002: + case 0x444100A4: + return HEATER_HANDLER_STRING; + case 0x44420004: + return TMP1075_HANDLER_1_STRING; + case 0x44420005: + return TMP1075_HANDLER_2_STRING; + case 0x44420016: + return RTD_IC3_STRING; + case 0x44420017: + return RTD_IC4_STRING; + case 0x44420018: + return RTD_IC5_STRING; + case 0x44420019: + return RTD_IC6_STRING; + case 0x44420020: + return RTD_IC7_STRING; + case 0x44420021: + return RTD_IC8_STRING; + case 0x44420022: + return RTD_IC9_STRING; + case 0x44420023: + return RTD_IC10_STRING; + case 0x44420024: + return RTD_IC11_STRING; + case 0x44420025: + return RTD_IC12_STRING; + case 0x44420026: + return RTD_IC13_STRING; + case 0x44420027: + return RTD_IC14_STRING; + case 0x44420028: + return RTD_IC15_STRING; + case 0x44420029: + return RTD_IC16_STRING; + case 0x44420030: + return RTD_IC17_STRING; + case 0x44420031: + return RTD_IC18_STRING; + case 0x445300A3: return SYRLINKS_HK_HANDLER_STRING; - case 0x47000001: - return GPIO_IF_STRING; - case 0x49000001: + case 0x49000000: return ARDUINO_COM_IF_STRING; - case 0x49000002: - return CSP_COM_IF_STRING; - case 0x49000003: - return I2C_COM_IF_STRING; - case 0x49000004: - return UART_COM_IF_STRING; - case 0x49000005: + case 0x49010005: + return GPIO_IF_STRING; + case 0x49020004: return SPI_COM_IF_STRING; + case 0x49030003: + return UART_COM_IF_STRING; + case 0x49040002: + return I2C_COM_IF_STRING; + case 0x49050001: + return CSP_COM_IF_STRING; case 0x50000100: return CCSDS_PACKET_DISTRIBUTOR_STRING; case 0x50000200: @@ -186,20 +249,8 @@ const char* translateObject(object_id_t object) { return UDP_BRIDGE_STRING; case 0x50000400: return UDP_POLLING_TASK_STRING; - case 0x51000300: - return PUS_SERVICE_3_STRING; - case 0x51000400: - return PUS_SERVICE_5_STRING; case 0x51000500: return PUS_SERVICE_6_STRING; - case 0x51000800: - return PUS_SERVICE_8_STRING; - case 0x51002300: - return PUS_SERVICE_23_STRING; - case 0x51020100: - return PUS_SERVICE_201_STRING; - case 0x52000002: - return TM_FUNNEL_STRING; case 0x53000000: return FSFW_OBJECTS_START_STRING; case 0x53000001: @@ -240,44 +291,10 @@ const char* translateObject(object_id_t object) { return TIME_STAMPER_STRING; case 0x53ffffff: return FSFW_OBJECTS_END_STRING; - case 0x54000003: - return HEATER_HANDLER_STRING; - case 0x54000004: - return RTD_IC3_STRING; - case 0x54000005: - return RTD_IC4_STRING; - case 0x54000006: - return RTD_IC5_STRING; - case 0x54000007: - return RTD_IC6_STRING; - case 0x54000008: - return RTD_IC7_STRING; - case 0x54000009: - return RTD_IC8_STRING; - case 0x5400000A: - return RTD_IC9_STRING; - case 0x5400000B: - return RTD_IC10_STRING; - case 0x5400000C: - return RTD_IC11_STRING; - case 0x5400000D: - return RTD_IC12_STRING; - case 0x5400000E: - return RTD_IC13_STRING; - case 0x5400000F: - return RTD_IC14_STRING; case 0x54000010: return SPI_TEST_STRING; - case 0x5400001F: - return RTD_IC15_STRING; - case 0x5400002F: - return RTD_IC16_STRING; - case 0x5400003F: - return RTD_IC17_STRING; - case 0x5400004F: - return RTD_IC18_STRING; - case 0x54000050: - return RAD_SENSOR_STRING; + case 0x54000020: + return UART_TEST_STRING; case 0x5400AFFE: return DUMMY_HANDLER_STRING; case 0x5400CAFE: @@ -286,6 +303,10 @@ const char* translateObject(object_id_t object) { return LIBGPIOD_TEST_STRING; case 0x54694269: return TEST_TASK_STRING; + case 0x73000100: + return TM_FUNNEL_STRING; + case 0x73500000: + return CCSDS_IP_CORE_BRIDGE_STRING; case 0xFFFFFFFF: return NO_OBJECT_STRING; default: 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/devices/SusHandler.h b/linux/devices/SusHandler.h index 2312d383..ca9a5c45 100644 --- a/linux/devices/SusHandler.h +++ b/linux/devices/SusHandler.h @@ -4,7 +4,6 @@ #include "devicedefinitions/SusDefinitions.h" #include #include -#include /** * @brief This is the device handler class for the SUS sensor. The sensor is diff --git a/linux/fsfwconfig/OBSWConfig.h.in b/linux/fsfwconfig/OBSWConfig.h.in index b3002cf4..30b01491 100644 --- a/linux/fsfwconfig/OBSWConfig.h.in +++ b/linux/fsfwconfig/OBSWConfig.h.in @@ -20,6 +20,7 @@ debugging. */ #define OBSW_PRINT_MISSED_DEADLINES 1 #define OBSW_ADD_TEST_CODE 1 #define OBSW_ADD_TEST_PST 1 +#define OBSW_ADD_GPS 0 #define TEST_LIBGPIOD 0 #define TEST_RADIATION_SENSOR_HANDLER 0 @@ -43,6 +44,7 @@ debugging. */ #define DEBUG_SUS 1 #define DEBUG_RTD 1 #define IMTQ_DEBUG 1 +#define RW_DEBUG 1 // Leave at one as the BSP is linux. Used by the ADIS16507 device handler #define OBSW_ADIS16507_LINUX_COM_IF 1 @@ -50,7 +52,7 @@ debugging. */ #include "OBSWVersion.h" /* Can be used to switch device to NORMAL mode immediately */ -#define OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP 1 +#define OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP 0 #ifdef __cplusplus @@ -62,6 +64,7 @@ namespace config { #endif /* Add mission configuration flags here */ +static constexpr uint32_t OBSW_FILESYSTEM_HANDLER_QUEUE_SIZE = 50; #ifdef __cplusplus } diff --git a/linux/fsfwconfig/devices/addresses.h b/linux/fsfwconfig/devices/addresses.h index 0deb8490..9d620475 100644 --- a/linux/fsfwconfig/devices/addresses.h +++ b/linux/fsfwconfig/devices/addresses.h @@ -17,7 +17,8 @@ namespace addresses { GYRO_0_ADIS = objects::GYRO_0_ADIS_HANDLER, GYRO_1_L3G = objects::GYRO_1_L3G_HANDLER, - GYRO_2_L3G = objects::GYRO_2_L3G_HANDLER, + GYRO_2_ADIS = objects::GYRO_2_ADIS_HANDLER, + GYRO_3_L3G = objects::GYRO_3_L3G_HANDLER, RAD_SENSOR = objects::RAD_SENSOR, @@ -63,7 +64,11 @@ namespace addresses { RTD_IC15, RTD_IC16, RTD_IC17, - RTD_IC18 + RTD_IC18, + RW1, + RW2, + RW3, + RW4 }; /* Addresses of devices supporting the CSP protocol */ diff --git a/linux/fsfwconfig/devices/gpioIds.h b/linux/fsfwconfig/devices/gpioIds.h index 102b04b9..aad06629 100644 --- a/linux/fsfwconfig/devices/gpioIds.h +++ b/linux/fsfwconfig/devices/gpioIds.h @@ -68,7 +68,21 @@ namespace gpioIds { CS_RAD_SENSOR, PAPB_BUSY_N, - PAPB_EMPTY + PAPB_EMPTY, + + EN_RW1, + EN_RW2, + EN_RW3, + EN_RW4, + + CS_RW1, + CS_RW2, + CS_RW3, + CS_RW4, + + EN_RW_CS, + + SPI_MUX }; } diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index c3af08e1..9ae81646 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 83 translations. + * @brief Auto-generated event translation file. Contains 92 translations. * @details - * Generated on: 2021-06-08 17:09:32 + * Generated on: 2021-06-29 16:20:09 */ #include "translateEvents.h" @@ -88,6 +88,15 @@ const char *MEMORY_READ_RPT_CRC_FAILURE_STRING = "MEMORY_READ_RPT_CRC_FAILURE"; const char *ACK_FAILURE_STRING = "ACK_FAILURE"; const char *EXE_FAILURE_STRING = "EXE_FAILURE"; const char *CRC_FAILURE_EVENT_STRING = "CRC_FAILURE_EVENT"; +const char *SELF_TEST_I2C_FAILURE_STRING = "SELF_TEST_I2C_FAILURE"; +const char *SELF_TEST_SPI_FAILURE_STRING = "SELF_TEST_SPI_FAILURE"; +const char *SELF_TEST_ADC_FAILURE_STRING = "SELF_TEST_ADC_FAILURE"; +const char *SELF_TEST_PWM_FAILURE_STRING = "SELF_TEST_PWM_FAILURE"; +const char *SELF_TEST_TC_FAILURE_STRING = "SELF_TEST_TC_FAILURE"; +const char *SELF_TEST_MTM_RANGE_FAILURE_STRING = "SELF_TEST_MTM_RANGE_FAILURE"; +const char *SELF_TEST_COIL_CURRENT_FAILURE_STRING = "SELF_TEST_COIL_CURRENT_FAILURE"; +const char *INVALID_ERROR_BYTE_STRING = "INVALID_ERROR_BYTE"; +const char *ERROR_STATE_STRING = "ERROR_STATE"; const char * translateEvents(Event event) { switch( (event & 0xffff) ) { @@ -257,6 +266,24 @@ const char * translateEvents(Event event) { return EXE_FAILURE_STRING; case(11104): return CRC_FAILURE_EVENT_STRING; + case(11201): + return SELF_TEST_I2C_FAILURE_STRING; + case(11202): + return SELF_TEST_SPI_FAILURE_STRING; + case(11203): + return SELF_TEST_ADC_FAILURE_STRING; + case(11204): + return SELF_TEST_PWM_FAILURE_STRING; + case(11205): + return SELF_TEST_TC_FAILURE_STRING; + case(11206): + return SELF_TEST_MTM_RANGE_FAILURE_STRING; + case(11207): + return SELF_TEST_COIL_CURRENT_FAILURE_STRING; + case(11208): + return INVALID_ERROR_BYTE_STRING; + case(11301): + return ERROR_STATE_STRING; default: return "UNKNOWN_EVENT"; } diff --git a/linux/fsfwconfig/objects/systemObjectList.h b/linux/fsfwconfig/objects/systemObjectList.h index 5d5cdee1..eb5333c2 100644 --- a/linux/fsfwconfig/objects/systemObjectList.h +++ b/linux/fsfwconfig/objects/systemObjectList.h @@ -6,67 +6,64 @@ #include // The objects will be instantiated in the ID order +// For naming scheme see flight manual +/* +https://egit.irs.uni-stuttgart.de/redmine/projects/eive-flight-manual/wiki/EIVE_Project_IDs + +Second byte first four bits is the subsystem: +OBDH 0x0 +ACS 0x1 +EPS 0x2 +PL 0x3 +TCS 0x4 +COM 0x5 + +Second byte last four bits is the bus: +None 0x0 +GPIO 0x1 +SPI 0x2 +UART 0x3 +I2C 0x4 +CAN 0x5 + +Third byte is an assembly counter if there are multiple redundant devices. +Fourth byte is a unique counter. + + */ namespace objects { - enum sourceObjects: uint32_t { - /* 0x53 reserved for FSFW */ - FW_ADDRESS_START = PUS_SERVICE_1_VERIFICATION, - FW_ADDRESS_END = TIME_STAMPER, +enum sourceObjects: uint32_t { + /* 0x53 reserved for FSFW */ + FW_ADDRESS_START = PUS_SERVICE_1_VERIFICATION, + FW_ADDRESS_END = TIME_STAMPER, + PUS_SERVICE_6 = 0x51000500, - CCSDS_IP_CORE_BRIDGE = 0x50000500, + CCSDS_IP_CORE_BRIDGE = 0x73500000, + TM_FUNNEL = 0x73000100, - PUS_SERVICE_6 = 0x51000500, + /* 0x49 ('I') for Communication Interfaces **/ + ARDUINO_COM_IF = 0x49000000, + CSP_COM_IF = 0x49050001, + I2C_COM_IF = 0x49040002, + UART_COM_IF = 0x49030003, + SPI_COM_IF = 0x49020004, + GPIO_IF = 0x49010005, - TM_FUNNEL = 0x52000002, + /* Custom device handler */ + PCDU_HANDLER = 0x442000A1, + SOLAR_ARRAY_DEPL_HANDLER = 0x444100A2, + SYRLINKS_HK_HANDLER = 0x445300A3, + HEATER_HANDLER = 0x444100A4, + RAD_SENSOR = 0x443200A5, - /* 0x49 ('I') for Communication Interfaces **/ - ARDUINO_COM_IF = 0x49000001, - CSP_COM_IF = 0x49000002, - I2C_COM_IF = 0x49000003, - UART_COM_IF = 0x49000004, - SPI_COM_IF = 0x49000005, - - /* 0x47 ('G') for Gpio Interfaces */ - GPIO_IF = 0x47000001, - - /* Custom device handler */ - PCDU_HANDLER = 0x44001000, - SOLAR_ARRAY_DEPL_HANDLER = 0x44001001, - SYRLINKS_HK_HANDLER = 0x44001002, - - /* 0x54 ('T') for thermal objects */ - HEATER_HANDLER = 0x54000003, - /** - * Not yet specified which pt1000 will measure which device/location in the satellite. - * Therefore object ids are named according to the IC naming of the RTDs in the schematic. - */ - RTD_IC3 = 0x54000004, - RTD_IC4 = 0x54000005, - RTD_IC5 = 0x54000006, - RTD_IC6 = 0x54000007, - RTD_IC7 = 0x54000008, - RTD_IC8 = 0x54000009, - RTD_IC9 = 0x5400000A, - RTD_IC10 = 0x5400000B, - RTD_IC11 = 0x5400000C, - RTD_IC12 = 0x5400000D, - RTD_IC13 = 0x5400000E, - RTD_IC14 = 0x5400000F, - RTD_IC15 = 0x5400001F, - RTD_IC16 = 0x5400002F, - RTD_IC17 = 0x5400003F, - RTD_IC18 = 0x5400004F, - - RAD_SENSOR = 0x54000050, - - /* 0x54 ('T') for test handlers */ - TEST_TASK = 0x54694269, - LIBGPIOD_TEST = 0x54123456, - SPI_TEST = 0x54000010, - UART_TEST = 0x54000020, - DUMMY_INTERFACE = 0x5400CAFE, - DUMMY_HANDLER = 0x5400AFFE, - P60DOCK_TEST_TASK = 0x00005060 - }; + /* 0x54 ('T') for test handlers */ + TEST_TASK = 0x54694269, + LIBGPIOD_TEST = 0x54123456, + SPI_TEST = 0x54000010, + UART_TEST = 0x54000020, + DUMMY_INTERFACE = 0x5400CAFE, + DUMMY_HANDLER = 0x5400AFFE, + P60DOCK_TEST_TASK = 0x00005060 +}; } #endif /* BSP_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ */ diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index 47b55435..2068158b 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -1,27 +1,17 @@ -/** +/** * @brief Auto-generated object translation file. * @details - * Contains 93 translations. - * Generated on: 2021-05-18 16:48:46 + * Contains 100 translations. + * Generated on: 2021-06-29 16:19:57 */ #include "translateObjects.h" const char *P60DOCK_TEST_TASK_STRING = "P60DOCK_TEST_TASK"; -const char *P60DOCK_HANDLER_STRING = "P60DOCK_HANDLER"; -const char *PDU1_HANDLER_STRING = "PDU1_HANDLER"; -const char *PDU2_HANDLER_STRING = "PDU2_HANDLER"; -const char *ACU_HANDLER_STRING = "ACU_HANDLER"; -const char *TMP1075_HANDLER_1_STRING = "TMP1075_HANDLER_1"; -const char *TMP1075_HANDLER_2_STRING = "TMP1075_HANDLER_2"; +const char *CORE_CONTROLLER_STRING = "CORE_CONTROLLER"; +const char *ACS_CONTROLLER_STRING = "ACS_CONTROLLER"; +const char *THERMAL_CONTROLLER_STRING = "THERMAL_CONTROLLER"; const char *MGM_0_LIS3_HANDLER_STRING = "MGM_0_LIS3_HANDLER"; -const char *MGM_1_RM3100_HANDLER_STRING = "MGM_1_RM3100_HANDLER"; -const char *MGM_2_LIS3_HANDLER_STRING = "MGM_2_LIS3_HANDLER"; -const char *MGM_3_RM3100_HANDLER_STRING = "MGM_3_RM3100_HANDLER"; const char *GYRO_0_ADIS_HANDLER_STRING = "GYRO_0_ADIS_HANDLER"; -const char *GYRO_1_L3G_HANDLER_STRING = "GYRO_1_L3G_HANDLER"; -const char *GYRO_2_L3G_HANDLER_STRING = "GYRO_2_L3G_HANDLER"; -const char *IMTQ_HANDLER_STRING = "IMTQ_HANDLER"; -const char *PLOC_HANDLER_STRING = "PLOC_HANDLER"; const char *SUS_1_STRING = "SUS_1"; const char *SUS_2_STRING = "SUS_2"; const char *SUS_3_STRING = "SUS_3"; @@ -35,26 +25,58 @@ const char *SUS_10_STRING = "SUS_10"; const char *SUS_11_STRING = "SUS_11"; const char *SUS_12_STRING = "SUS_12"; const char *SUS_13_STRING = "SUS_13"; +const char *MGM_1_RM3100_HANDLER_STRING = "MGM_1_RM3100_HANDLER"; +const char *GYRO_1_L3G_HANDLER_STRING = "GYRO_1_L3G_HANDLER"; +const char *MGM_2_LIS3_HANDLER_STRING = "MGM_2_LIS3_HANDLER"; +const char *GYRO_2_ADIS_HANDLER_STRING = "GYRO_2_ADIS_HANDLER"; +const char *MGM_3_RM3100_HANDLER_STRING = "MGM_3_RM3100_HANDLER"; +const char *GYRO_3_L3G_HANDLER_STRING = "GYRO_3_L3G_HANDLER"; +const char *GPS0_HANDLER_STRING = "GPS0_HANDLER"; +const char *GPS1_HANDLER_STRING = "GPS1_HANDLER"; +const char *IMTQ_HANDLER_STRING = "IMTQ_HANDLER"; const char *PCDU_HANDLER_STRING = "PCDU_HANDLER"; +const char *RW1_STRING = "RW1"; +const char *RW2_STRING = "RW2"; +const char *RW3_STRING = "RW3"; +const char *RW4_STRING = "RW4"; +const char *P60DOCK_HANDLER_STRING = "P60DOCK_HANDLER"; +const char *PDU1_HANDLER_STRING = "PDU1_HANDLER"; +const char *PDU2_HANDLER_STRING = "PDU2_HANDLER"; +const char *ACU_HANDLER_STRING = "ACU_HANDLER"; +const char *RAD_SENSOR_STRING = "RAD_SENSOR"; +const char *PLOC_HANDLER_STRING = "PLOC_HANDLER"; const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER"; +const char *HEATER_HANDLER_STRING = "HEATER_HANDLER"; +const char *TMP1075_HANDLER_1_STRING = "TMP1075_HANDLER_1"; +const char *TMP1075_HANDLER_2_STRING = "TMP1075_HANDLER_2"; +const char *RTD_IC3_STRING = "RTD_IC3"; +const char *RTD_IC4_STRING = "RTD_IC4"; +const char *RTD_IC5_STRING = "RTD_IC5"; +const char *RTD_IC6_STRING = "RTD_IC6"; +const char *RTD_IC7_STRING = "RTD_IC7"; +const char *RTD_IC8_STRING = "RTD_IC8"; +const char *RTD_IC9_STRING = "RTD_IC9"; +const char *RTD_IC10_STRING = "RTD_IC10"; +const char *RTD_IC11_STRING = "RTD_IC11"; +const char *RTD_IC12_STRING = "RTD_IC12"; +const char *RTD_IC13_STRING = "RTD_IC13"; +const char *RTD_IC14_STRING = "RTD_IC14"; +const char *RTD_IC15_STRING = "RTD_IC15"; +const char *RTD_IC16_STRING = "RTD_IC16"; +const char *RTD_IC17_STRING = "RTD_IC17"; +const char *RTD_IC18_STRING = "RTD_IC18"; const char *SYRLINKS_HK_HANDLER_STRING = "SYRLINKS_HK_HANDLER"; -const char *GPIO_IF_STRING = "GPIO_IF"; const char *ARDUINO_COM_IF_STRING = "ARDUINO_COM_IF"; -const char *CSP_COM_IF_STRING = "CSP_COM_IF"; -const char *I2C_COM_IF_STRING = "I2C_COM_IF"; -const char *UART_COM_IF_STRING = "UART_COM_IF"; +const char *GPIO_IF_STRING = "GPIO_IF"; const char *SPI_COM_IF_STRING = "SPI_COM_IF"; +const char *UART_COM_IF_STRING = "UART_COM_IF"; +const char *I2C_COM_IF_STRING = "I2C_COM_IF"; +const char *CSP_COM_IF_STRING = "CSP_COM_IF"; const char *CCSDS_PACKET_DISTRIBUTOR_STRING = "CCSDS_PACKET_DISTRIBUTOR"; const char *PUS_PACKET_DISTRIBUTOR_STRING = "PUS_PACKET_DISTRIBUTOR"; const char *UDP_BRIDGE_STRING = "UDP_BRIDGE"; const char *UDP_POLLING_TASK_STRING = "UDP_POLLING_TASK"; -const char *PUS_SERVICE_3_STRING = "PUS_SERVICE_3"; -const char *PUS_SERVICE_5_STRING = "PUS_SERVICE_5"; const char *PUS_SERVICE_6_STRING = "PUS_SERVICE_6"; -const char *PUS_SERVICE_8_STRING = "PUS_SERVICE_8"; -const char *PUS_SERVICE_23_STRING = "PUS_SERVICE_23"; -const char *PUS_SERVICE_201_STRING = "PUS_SERVICE_201"; -const char *TM_FUNNEL_STRING = "TM_FUNNEL"; const char *FSFW_OBJECTS_START_STRING = "FSFW_OBJECTS_START"; const char *PUS_SERVICE_1_VERIFICATION_STRING = "PUS_SERVICE_1_VERIFICATION"; const char *PUS_SERVICE_2_DEVICE_ACCESS_STRING = "PUS_SERVICE_2_DEVICE_ACCESS"; @@ -75,109 +97,150 @@ const char *TM_STORE_STRING = "TM_STORE"; const char *IPC_STORE_STRING = "IPC_STORE"; const char *TIME_STAMPER_STRING = "TIME_STAMPER"; const char *FSFW_OBJECTS_END_STRING = "FSFW_OBJECTS_END"; -const char *HEATER_HANDLER_STRING = "HEATER_HANDLER"; -const char *RTD_IC3_STRING = "RTD_IC3"; -const char *RTD_IC4_STRING = "RTD_IC4"; -const char *RTD_IC5_STRING = "RTD_IC5"; -const char *RTD_IC6_STRING = "RTD_IC6"; -const char *RTD_IC7_STRING = "RTD_IC7"; -const char *RTD_IC8_STRING = "RTD_IC8"; -const char *RTD_IC9_STRING = "RTD_IC9"; -const char *RTD_IC10_STRING = "RTD_IC10"; -const char *RTD_IC11_STRING = "RTD_IC11"; -const char *RTD_IC12_STRING = "RTD_IC12"; -const char *RTD_IC13_STRING = "RTD_IC13"; -const char *RTD_IC14_STRING = "RTD_IC14"; const char *SPI_TEST_STRING = "SPI_TEST"; -const char *RTD_IC15_STRING = "RTD_IC15"; -const char *RTD_IC16_STRING = "RTD_IC16"; -const char *RTD_IC17_STRING = "RTD_IC17"; -const char *RTD_IC18_STRING = "RTD_IC18"; -const char *RAD_SENSOR_STRING = "RAD_SENSOR"; +const char *UART_TEST_STRING = "UART_TEST"; const char *DUMMY_HANDLER_STRING = "DUMMY_HANDLER"; const char *DUMMY_INTERFACE_STRING = "DUMMY_INTERFACE"; const char *LIBGPIOD_TEST_STRING = "LIBGPIOD_TEST"; const char *TEST_TASK_STRING = "TEST_TASK"; +const char *TM_FUNNEL_STRING = "TM_FUNNEL"; +const char *CCSDS_IP_CORE_BRIDGE_STRING = "CCSDS_IP_CORE_BRIDGE"; const char *NO_OBJECT_STRING = "NO_OBJECT"; const char* translateObject(object_id_t object) { switch( (object & 0xFFFFFFFF) ) { case 0x00005060: return P60DOCK_TEST_TASK_STRING; - case 0x44000001: - return P60DOCK_HANDLER_STRING; - case 0x44000002: - return PDU1_HANDLER_STRING; - case 0x44000003: - return PDU2_HANDLER_STRING; - case 0x44000004: - return ACU_HANDLER_STRING; - case 0x44000005: - return TMP1075_HANDLER_1_STRING; - case 0x44000006: - return TMP1075_HANDLER_2_STRING; - case 0x44000007: + case 0x43000003: + return CORE_CONTROLLER_STRING; + case 0x43100002: + return ACS_CONTROLLER_STRING; + case 0x43400001: + return THERMAL_CONTROLLER_STRING; + case 0x44120006: return MGM_0_LIS3_HANDLER_STRING; - case 0x44000008: - return MGM_1_RM3100_HANDLER_STRING; - case 0x44000009: - return MGM_2_LIS3_HANDLER_STRING; - case 0x44000010: - return MGM_3_RM3100_HANDLER_STRING; - case 0x44000011: + case 0x44120010: return GYRO_0_ADIS_HANDLER_STRING; - case 0x44000012: - return GYRO_1_L3G_HANDLER_STRING; - case 0x44000013: - return GYRO_2_L3G_HANDLER_STRING; - case 0x44000014: - return IMTQ_HANDLER_STRING; - case 0x44000015: - return PLOC_HANDLER_STRING; - case 0x44000016: + case 0x44120032: return SUS_1_STRING; - case 0x44000017: + case 0x44120033: return SUS_2_STRING; - case 0x44000018: + case 0x44120034: return SUS_3_STRING; - case 0x44000019: + case 0x44120035: return SUS_4_STRING; - case 0x4400001A: + case 0x44120036: return SUS_5_STRING; - case 0x4400001B: + case 0x44120037: return SUS_6_STRING; - case 0x4400001C: + case 0x44120038: return SUS_7_STRING; - case 0x4400001D: + case 0x44120039: return SUS_8_STRING; - case 0x4400001E: + case 0x44120040: return SUS_9_STRING; - case 0x4400001F: + case 0x44120041: return SUS_10_STRING; - case 0x44000021: + case 0x44120042: return SUS_11_STRING; - case 0x44000022: + case 0x44120043: return SUS_12_STRING; - case 0x44000023: + case 0x44120044: return SUS_13_STRING; - case 0x44001000: + case 0x44120107: + return MGM_1_RM3100_HANDLER_STRING; + case 0x44120111: + return GYRO_1_L3G_HANDLER_STRING; + case 0x44120208: + return MGM_2_LIS3_HANDLER_STRING; + case 0x44120212: + return GYRO_2_ADIS_HANDLER_STRING; + case 0x44120309: + return MGM_3_RM3100_HANDLER_STRING; + case 0x44120313: + return GYRO_3_L3G_HANDLER_STRING; + case 0x44130045: + return GPS0_HANDLER_STRING; + case 0x44130146: + return GPS1_HANDLER_STRING; + case 0x44140014: + return IMTQ_HANDLER_STRING; + case 0x442000A1: return PCDU_HANDLER_STRING; - case 0x44001001: + case 0x44210001: + return RW1_STRING; + case 0x44210002: + return RW2_STRING; + case 0x44210003: + return RW3_STRING; + case 0x44210004: + return RW4_STRING; + case 0x44250000: + return P60DOCK_HANDLER_STRING; + case 0x44250001: + return PDU1_HANDLER_STRING; + case 0x44250002: + return PDU2_HANDLER_STRING; + case 0x44250003: + return ACU_HANDLER_STRING; + case 0x443200A5: + return RAD_SENSOR_STRING; + case 0x44330015: + return PLOC_HANDLER_STRING; + case 0x444100A2: return SOLAR_ARRAY_DEPL_HANDLER_STRING; - case 0x44001002: + case 0x444100A4: + return HEATER_HANDLER_STRING; + case 0x44420004: + return TMP1075_HANDLER_1_STRING; + case 0x44420005: + return TMP1075_HANDLER_2_STRING; + case 0x44420016: + return RTD_IC3_STRING; + case 0x44420017: + return RTD_IC4_STRING; + case 0x44420018: + return RTD_IC5_STRING; + case 0x44420019: + return RTD_IC6_STRING; + case 0x44420020: + return RTD_IC7_STRING; + case 0x44420021: + return RTD_IC8_STRING; + case 0x44420022: + return RTD_IC9_STRING; + case 0x44420023: + return RTD_IC10_STRING; + case 0x44420024: + return RTD_IC11_STRING; + case 0x44420025: + return RTD_IC12_STRING; + case 0x44420026: + return RTD_IC13_STRING; + case 0x44420027: + return RTD_IC14_STRING; + case 0x44420028: + return RTD_IC15_STRING; + case 0x44420029: + return RTD_IC16_STRING; + case 0x44420030: + return RTD_IC17_STRING; + case 0x44420031: + return RTD_IC18_STRING; + case 0x445300A3: return SYRLINKS_HK_HANDLER_STRING; - case 0x47000001: - return GPIO_IF_STRING; - case 0x49000001: + case 0x49000000: return ARDUINO_COM_IF_STRING; - case 0x49000002: - return CSP_COM_IF_STRING; - case 0x49000003: - return I2C_COM_IF_STRING; - case 0x49000004: - return UART_COM_IF_STRING; - case 0x49000005: + case 0x49010005: + return GPIO_IF_STRING; + case 0x49020004: return SPI_COM_IF_STRING; + case 0x49030003: + return UART_COM_IF_STRING; + case 0x49040002: + return I2C_COM_IF_STRING; + case 0x49050001: + return CSP_COM_IF_STRING; case 0x50000100: return CCSDS_PACKET_DISTRIBUTOR_STRING; case 0x50000200: @@ -186,20 +249,8 @@ const char* translateObject(object_id_t object) { return UDP_BRIDGE_STRING; case 0x50000400: return UDP_POLLING_TASK_STRING; - case 0x51000300: - return PUS_SERVICE_3_STRING; - case 0x51000400: - return PUS_SERVICE_5_STRING; case 0x51000500: return PUS_SERVICE_6_STRING; - case 0x51000800: - return PUS_SERVICE_8_STRING; - case 0x51002300: - return PUS_SERVICE_23_STRING; - case 0x51020100: - return PUS_SERVICE_201_STRING; - case 0x52000002: - return TM_FUNNEL_STRING; case 0x53000000: return FSFW_OBJECTS_START_STRING; case 0x53000001: @@ -240,44 +291,10 @@ const char* translateObject(object_id_t object) { return TIME_STAMPER_STRING; case 0x53ffffff: return FSFW_OBJECTS_END_STRING; - case 0x54000003: - return HEATER_HANDLER_STRING; - case 0x54000004: - return RTD_IC3_STRING; - case 0x54000005: - return RTD_IC4_STRING; - case 0x54000006: - return RTD_IC5_STRING; - case 0x54000007: - return RTD_IC6_STRING; - case 0x54000008: - return RTD_IC7_STRING; - case 0x54000009: - return RTD_IC8_STRING; - case 0x5400000A: - return RTD_IC9_STRING; - case 0x5400000B: - return RTD_IC10_STRING; - case 0x5400000C: - return RTD_IC11_STRING; - case 0x5400000D: - return RTD_IC12_STRING; - case 0x5400000E: - return RTD_IC13_STRING; - case 0x5400000F: - return RTD_IC14_STRING; case 0x54000010: return SPI_TEST_STRING; - case 0x5400001F: - return RTD_IC15_STRING; - case 0x5400002F: - return RTD_IC16_STRING; - case 0x5400003F: - return RTD_IC17_STRING; - case 0x5400004F: - return RTD_IC18_STRING; - case 0x54000050: - return RAD_SENSOR_STRING; + case 0x54000020: + return UART_TEST_STRING; case 0x5400AFFE: return DUMMY_HANDLER_STRING; case 0x5400CAFE: @@ -286,6 +303,10 @@ const char* translateObject(object_id_t object) { return LIBGPIOD_TEST_STRING; case 0x54694269: return TEST_TASK_STRING; + case 0x73000100: + return TM_FUNNEL_STRING; + case 0x73500000: + return CCSDS_IP_CORE_BRIDGE_STRING; case 0xFFFFFFFF: return NO_OBJECT_STRING; default: diff --git a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp index 60059d3c..a213ca06 100644 --- a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp +++ b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp @@ -9,18 +9,30 @@ #include "objects/systemObjectList.h" -ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) +ReturnValue_t pst::pstGpio(FixedTimeslotTaskIF *thisSequence) { - /* Length of a communication cycle */ + // Length of a communication cycle uint32_t length = thisSequence->getPeriodMs(); - thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0, - DeviceHandlerIF::PERFORM_OPERATION); - thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0, - DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::HEATER_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::SOLAR_ARRAY_DEPL_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { + return HasReturnvaluesIF::RETURN_OK; + } + + sif::error << "PollingSequence::initialize has errors!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +} + +ReturnValue_t pst::pstSpi(FixedTimeslotTaskIF *thisSequence) { + uint32_t length = thisSequence->getPeriodMs(); + + thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0, + DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0, + DeviceHandlerIF::PERFORM_OPERATION); #if Q7S_ADD_RTD_DEVICES == 1 thisSequence->addSlot(objects::RTD_IC3, length * 0, DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::RTD_IC4, length * 0, DeviceHandlerIF::PERFORM_OPERATION); @@ -40,12 +52,8 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) thisSequence->addSlot(objects::RTD_IC18, length * 0, DeviceHandlerIF::PERFORM_OPERATION); #endif /* Q7S_ADD_RTD_DEVICES */ - thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); - thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.2, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.2, DeviceHandlerIF::SEND_WRITE); - #if Q7S_ADD_RTD_DEVICES == 1 thisSequence->addSlot(objects::RTD_IC3, length * 0.2, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::RTD_IC4, length * 0.2, DeviceHandlerIF::SEND_WRITE); @@ -65,12 +73,8 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) thisSequence->addSlot(objects::RTD_IC18, length * 0.2, DeviceHandlerIF::SEND_WRITE); #endif /* Q7S_ADD_RTD_DEVICES */ - thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE); - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE); - thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.4, DeviceHandlerIF::GET_WRITE); - #if Q7S_ADD_RTD_DEVICES == 1 thisSequence->addSlot(objects::RTD_IC3, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::RTD_IC4, length * 0.4, DeviceHandlerIF::GET_WRITE); @@ -90,12 +94,8 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) thisSequence->addSlot(objects::RTD_IC18, length * 0.4, DeviceHandlerIF::GET_WRITE); #endif /* Q7S_ADD_RTD_DEVICES */ - thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE); - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE); - thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.6, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.6, DeviceHandlerIF::SEND_READ); - #if Q7S_ADD_RTD_DEVICES == 1 thisSequence->addSlot(objects::RTD_IC3, length * 0.6, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::RTD_IC4, length * 0.6, DeviceHandlerIF::SEND_READ); @@ -115,12 +115,8 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) thisSequence->addSlot(objects::RTD_IC18, length * 0.6, DeviceHandlerIF::SEND_READ); #endif /* Q7S_ADD_RTD_DEVICES */ - thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.8, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.8, DeviceHandlerIF::GET_READ); - #if Q7S_ADD_RTD_DEVICES == 1 thisSequence->addSlot(objects::RTD_IC3, length * 0.8, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::RTD_IC4, length * 0.8, DeviceHandlerIF::GET_READ); @@ -140,21 +136,12 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) thisSequence->addSlot(objects::RTD_IC18, length * 0.8, DeviceHandlerIF::GET_READ); #endif /* Q7S_ADD_RTD_DEVICES */ - thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); - - /* Radiation sensor */ -// thisSequence->addSlot(objects::RAD_SENSOR, length * 0, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::RAD_SENSOR, length * 0.2, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::RAD_SENSOR, length * 0.4, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::RAD_SENSOR, length * 0.6, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::RAD_SENSOR, length * 0.8, DeviceHandlerIF::GET_READ); - - if (length != 3000) { - sif::warning << "pollingSequenceInitDefault: Frequency changed. Make sure timing critical " - << "SUS sensors still produce correct values" << std::endl; - } + thisSequence->addSlot(objects::RAD_SENSOR, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::RAD_SENSOR, length * 0.2, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::RAD_SENSOR, length * 0.4, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::RAD_SENSOR, length * 0.6, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::RAD_SENSOR, length * 0.8, DeviceHandlerIF::GET_READ); /** * The sun sensor will be shutdown as soon as the chip select is pulled high. Thus all @@ -166,263 +153,368 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) */ /* Write setup */ -// thisSequence->addSlot(objects::SUS_1, length * 0.9, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_1, length * 0.9, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_1, length * 0.9, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_1, length * 0.9, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_1, length * 0.9, DeviceHandlerIF::GET_READ); -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_1, length * 0.901, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_1, length * 0.901, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_1, length * 0.901, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_1, length * 0.901, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_1, length * 0.901, DeviceHandlerIF::GET_READ); -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_1, length * 0.902, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_1, length * 0.902, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_1, length * 0.902, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_1, length * 0.902, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_1, length * 0.902, DeviceHandlerIF::GET_READ); + // thisSequence->addSlot(objects::SUS_1, length * 0.9, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_1, length * 0.9, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_1, length * 0.9, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_1, length * 0.9, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_1, length * 0.9, DeviceHandlerIF::GET_READ); + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_1, length * 0.901, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_1, length * 0.901, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_1, length * 0.901, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_1, length * 0.901, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_1, length * 0.901, DeviceHandlerIF::GET_READ); + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_1, length * 0.902, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_1, length * 0.902, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_1, length * 0.902, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_1, length * 0.902, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_1, length * 0.902, DeviceHandlerIF::GET_READ); /* Write setup */ -// thisSequence->addSlot(objects::SUS_2, length * 0.903, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_2, length * 0.903, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_2, length * 0.903, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_2, length * 0.903, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_2, length * 0.903, DeviceHandlerIF::GET_READ); -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_2, length * 0.904, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_2, length * 0.904, SusHandler::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_2, length * 0.904, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_2, length * 0.904, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_2, length * 0.904, DeviceHandlerIF::GET_READ); -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_2, length * 0.905, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_2, length * 0.905, SusHandler::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_2, length * 0.905, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_2, length * 0.905, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_2, length * 0.905, DeviceHandlerIF::GET_READ); + // thisSequence->addSlot(objects::SUS_2, length * 0.903, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_2, length * 0.903, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_2, length * 0.903, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_2, length * 0.903, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_2, length * 0.903, DeviceHandlerIF::GET_READ); + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_2, length * 0.904, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_2, length * 0.904, SusHandler::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_2, length * 0.904, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_2, length * 0.904, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_2, length * 0.904, DeviceHandlerIF::GET_READ); + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_2, length * 0.905, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_2, length * 0.905, SusHandler::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_2, length * 0.905, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_2, length * 0.905, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_2, length * 0.905, DeviceHandlerIF::GET_READ); /* Write setup */ -// thisSequence->addSlot(objects::SUS_3, length * 0.8, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_3, length * 0.8, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_3, length * 0.8, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_3, length * 0.8, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_3, length * 0.8, DeviceHandlerIF::GET_READ); -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_3, length * 0.91, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_3, length * 0.91, SusHandler::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_3, length * 0.91, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_3, length * 0.91, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_3, length * 0.91, DeviceHandlerIF::GET_READ); -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_3, length * 0.93, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_3, length * 0.93, SusHandler::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_3, length * 0.93, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_3, length * 0.93, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_3, length * 0.93, DeviceHandlerIF::GET_READ); -// -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_4, length * 0.909, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_4, length * 0.909, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_4, length * 0.909, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_4, length * 0.909, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_4, length * 0.909, DeviceHandlerIF::GET_READ); -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_4, length * 0.91, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_4, length * 0.91, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_4, length * 0.91, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_4, length * 0.91, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_4, length * 0.91, DeviceHandlerIF::GET_READ); -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_4, length * 0.911, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_4, length * 0.911, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_4, length * 0.911, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_4, length * 0.911, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_4, length * 0.911, DeviceHandlerIF::GET_READ); -// -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_5, length * 0.912, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_5, length * 0.912, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_5, length * 0.912, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_5, length * 0.912, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_5, length * 0.912, DeviceHandlerIF::GET_READ); -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_5, length * 0.913, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_5, length * 0.913, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_5, length * 0.913, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_5, length * 0.913, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_5, length * 0.913, DeviceHandlerIF::GET_READ); -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_5, length * 0.914, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_5, length * 0.914, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_5, length * 0.914, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_5, length * 0.914, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_5, length * 0.914, DeviceHandlerIF::GET_READ); -// -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_6, length * 0.915, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_6, length * 0.915, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_6, length * 0.915, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_6, length * 0.915, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_6, length * 0.915, DeviceHandlerIF::GET_READ); -// /* Start ADC conversions */ -// thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::GET_READ); -// /* Read ADC conversions from inernal FIFO */ -// thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::GET_READ); -// -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_7, length * 0.918, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_7, length * 0.918, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_7, length * 0.918, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_7, length * 0.918, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_7, length * 0.918, DeviceHandlerIF::GET_READ); -// /* Start ADC conversions */ -// thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::GET_READ); -// /* Read ADC conversions from inernal FIFO */ -// thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::GET_READ); -// -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_8, length * 0.921, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_8, length * 0.921, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_8, length * 0.921, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_8, length * 0.921, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_8, length * 0.921, DeviceHandlerIF::GET_READ); -// /* Start ADC conversions */ -// thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::GET_READ); -// /* Read ADC conversions from inernal FIFO */ -// thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::GET_READ); -// -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_9, length * 0.924, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_9, length * 0.924, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_9, length * 0.924, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_9, length * 0.924, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_9, length * 0.924, DeviceHandlerIF::GET_READ); -// /* Start ADC conversions */ -// thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::GET_READ); -// /* Read ADC conversions */ -// thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::GET_READ); -// -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_10, length * 0.927, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_10, length * 0.927, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_10, length * 0.927, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_10, length * 0.927, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_10, length * 0.927, DeviceHandlerIF::GET_READ); -// /* Start ADC conversions */ -// thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::GET_READ); -// /* Read ADC conversions */ -// thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::GET_READ); -// -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_11, length * 0.93, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_11, length * 0.93, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_11, length * 0.93, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_11, length * 0.93, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_11, length * 0.93, DeviceHandlerIF::GET_READ); -// /* Start ADC conversions */ -// thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::GET_READ); -// /* Read ADC conversions */ -// thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::GET_READ); -// -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_12, length * 0.933, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_12, length * 0.933, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_12, length * 0.933, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_12, length * 0.933, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_12, length * 0.933, DeviceHandlerIF::GET_READ); -// /* Start ADC conversions */ -// thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::GET_READ); -// /* Read ADC conversions */ -// thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::GET_READ); -// -// /* Write setup */ -// thisSequence->addSlot(objects::SUS_13, length * 0.936, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_13, length * 0.936, SusHandler::FIRST_WRITE); -// thisSequence->addSlot(objects::SUS_13, length * 0.936, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_13, length * 0.936, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_13, length * 0.936, DeviceHandlerIF::GET_READ); -// /* Start ADC conversions */ -// thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::GET_READ); -// /* Read ADC conversions */ -// thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::PERFORM_OPERATION); -// thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::SEND_WRITE); -// thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::GET_WRITE); -// thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::SEND_READ); -// thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::GET_READ); + // thisSequence->addSlot(objects::SUS_3, length * 0.8, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_3, length * 0.8, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_3, length * 0.8, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_3, length * 0.8, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_3, length * 0.8, DeviceHandlerIF::GET_READ); + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_3, length * 0.91, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_3, length * 0.91, SusHandler::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_3, length * 0.91, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_3, length * 0.91, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_3, length * 0.91, DeviceHandlerIF::GET_READ); + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_3, length * 0.93, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_3, length * 0.93, SusHandler::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_3, length * 0.93, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_3, length * 0.93, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_3, length * 0.93, DeviceHandlerIF::GET_READ); + // + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_4, length * 0.909, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_4, length * 0.909, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_4, length * 0.909, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_4, length * 0.909, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_4, length * 0.909, DeviceHandlerIF::GET_READ); + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_4, length * 0.91, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_4, length * 0.91, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_4, length * 0.91, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_4, length * 0.91, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_4, length * 0.91, DeviceHandlerIF::GET_READ); + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_4, length * 0.911, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_4, length * 0.911, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_4, length * 0.911, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_4, length * 0.911, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_4, length * 0.911, DeviceHandlerIF::GET_READ); + // + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_5, length * 0.912, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_5, length * 0.912, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_5, length * 0.912, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_5, length * 0.912, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_5, length * 0.912, DeviceHandlerIF::GET_READ); + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_5, length * 0.913, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_5, length * 0.913, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_5, length * 0.913, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_5, length * 0.913, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_5, length * 0.913, DeviceHandlerIF::GET_READ); + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_5, length * 0.914, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_5, length * 0.914, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_5, length * 0.914, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_5, length * 0.914, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_5, length * 0.914, DeviceHandlerIF::GET_READ); + // + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_6, length * 0.915, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_6, length * 0.915, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_6, length * 0.915, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_6, length * 0.915, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_6, length * 0.915, DeviceHandlerIF::GET_READ); + // /* Start ADC conversions */ + // thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::GET_READ); + // /* Read ADC conversions from inernal FIFO */ + // thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::GET_READ); + // + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_7, length * 0.918, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_7, length * 0.918, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_7, length * 0.918, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_7, length * 0.918, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_7, length * 0.918, DeviceHandlerIF::GET_READ); + // /* Start ADC conversions */ + // thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::GET_READ); + // /* Read ADC conversions from inernal FIFO */ + // thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::GET_READ); + // + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_8, length * 0.921, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_8, length * 0.921, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_8, length * 0.921, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_8, length * 0.921, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_8, length * 0.921, DeviceHandlerIF::GET_READ); + // /* Start ADC conversions */ + // thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::GET_READ); + // /* Read ADC conversions from inernal FIFO */ + // thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::GET_READ); + // + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_9, length * 0.924, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_9, length * 0.924, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_9, length * 0.924, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_9, length * 0.924, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_9, length * 0.924, DeviceHandlerIF::GET_READ); + // /* Start ADC conversions */ + // thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::GET_READ); + // /* Read ADC conversions */ + // thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::GET_READ); + // + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_10, length * 0.927, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_10, length * 0.927, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_10, length * 0.927, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_10, length * 0.927, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_10, length * 0.927, DeviceHandlerIF::GET_READ); + // /* Start ADC conversions */ + // thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::GET_READ); + // /* Read ADC conversions */ + // thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::GET_READ); + // + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_11, length * 0.93, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_11, length * 0.93, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_11, length * 0.93, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_11, length * 0.93, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_11, length * 0.93, DeviceHandlerIF::GET_READ); + // /* Start ADC conversions */ + // thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::GET_READ); + // /* Read ADC conversions */ + // thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::GET_READ); + // + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_12, length * 0.933, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_12, length * 0.933, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_12, length * 0.933, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_12, length * 0.933, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_12, length * 0.933, DeviceHandlerIF::GET_READ); + // /* Start ADC conversions */ + // thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::GET_READ); + // /* Read ADC conversions */ + // thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::GET_READ); + // + // /* Write setup */ + // thisSequence->addSlot(objects::SUS_13, length * 0.936, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_13, length * 0.936, SusHandler::FIRST_WRITE); + // thisSequence->addSlot(objects::SUS_13, length * 0.936, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_13, length * 0.936, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_13, length * 0.936, DeviceHandlerIF::GET_READ); + // /* Start ADC conversions */ + // thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::GET_READ); + // /* Read ADC conversions */ + // thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::PERFORM_OPERATION); + // thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::SEND_WRITE); + // thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::GET_WRITE); + // thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::SEND_READ); + // thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::GET_READ); - if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { - return HasReturnvaluesIF::RETURN_OK; + thisSequence->addSlot(objects::RW1, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::RW1, length * 0.2, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::RW1, length * 0.4, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::RW1, length * 0.6, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::RW1, length * 0.8, DeviceHandlerIF::GET_READ); + + thisSequence->addSlot(objects::RW2, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::RW2, length * 0.2, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::RW2, length * 0.4, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::RW2, length * 0.6, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::RW2, length * 0.8, DeviceHandlerIF::GET_READ); + + thisSequence->addSlot(objects::RW3, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::RW3, length * 0.2, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::RW3, length * 0.4, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::RW3, length * 0.6, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::RW3, length * 0.8, DeviceHandlerIF::GET_READ); + + thisSequence->addSlot(objects::RW4, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::RW4, length * 0.2, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::RW4, length * 0.4, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::RW4, length * 0.6, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::RW4, length * 0.8, DeviceHandlerIF::GET_READ); + + if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) { + sif::error << "SPI PST initialization failed" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; } - - sif::error << "PollingSequence::initialize has errors!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; + return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t pst::gomspacePstInit(FixedTimeslotTaskIF *thisSequence){ +ReturnValue_t pst::pstI2c(FixedTimeslotTaskIF *thisSequence) { + // Length of a communication cycle + uint32_t length = thisSequence->getPeriodMs(); + thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); + if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) { + sif::error << "I2C PST initialization failed" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { + // Length of a communication cycle uint32_t length = thisSequence->getPeriodMs(); + thisSequence->addSlot(objects::PLOC_HANDLER, length * 0, + DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0, + DeviceHandlerIF::PERFORM_OPERATION); +#if OBSW_ADD_ACS_BOARD == 1 + thisSequence->addSlot(objects::GPS0_HANDLER, length * 0, + DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::GPS1_HANDLER, length * 0, + DeviceHandlerIF::PERFORM_OPERATION); +#endif + + thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.2, + DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.2, + DeviceHandlerIF::SEND_WRITE); +#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, + DeviceHandlerIF::SEND_WRITE); +#endif + + thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.4, + DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.4, + DeviceHandlerIF::GET_WRITE); +#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, + DeviceHandlerIF::GET_WRITE); +#endif + + thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.6, + DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.6, + DeviceHandlerIF::SEND_READ); +#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, + DeviceHandlerIF::SEND_READ); +#endif + + thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.8, + DeviceHandlerIF::GET_READ); + thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.8, + DeviceHandlerIF::GET_READ); +#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, + DeviceHandlerIF::GET_READ); +#endif + + if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) { + sif::error << "UART PST initialization failed" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t pst::pstGompaceCan(FixedTimeslotTaskIF *thisSequence){ + uint32_t length = thisSequence->getPeriodMs(); + + // PCDU handlers receives two messages and both must be handled thisSequence->addSlot(objects::PCDU_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::PCDU_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); @@ -472,18 +564,18 @@ ReturnValue_t pst::gomspacePstInit(FixedTimeslotTaskIF *thisSequence){ length * 0.8, DeviceHandlerIF::GET_READ); if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) { - sif::error << "Initialization of GomSpace PST failed" << std::endl; + sif::error << "GomSpace PST initialization failed" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t pst::pollingSequenceTest(FixedTimeslotTaskIF* thisSequence) { +ReturnValue_t pst::pstTest(FixedTimeslotTaskIF* thisSequence) { /* Length of a communication cycle */ uint32_t length = thisSequence->getPeriodMs(); #if OBSW_ADD_ACS_BOARD == 1 thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0, - DeviceHandlerIF::PERFORM_OPERATION); + DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.4, @@ -504,28 +596,28 @@ ReturnValue_t pst::pollingSequenceTest(FixedTimeslotTaskIF* thisSequence) { thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); - thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0, - DeviceHandlerIF::PERFORM_OPERATION); - thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0.2, - DeviceHandlerIF::SEND_WRITE); - thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0.4, - DeviceHandlerIF::GET_WRITE); - thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0.6, - DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0.8, - DeviceHandlerIF::GET_READ); + thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0, + DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0.2, + DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0.4, + DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0.6, + DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0.8, + DeviceHandlerIF::GET_READ); - thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0, - DeviceHandlerIF::PERFORM_OPERATION); - thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.2, - DeviceHandlerIF::SEND_WRITE); - thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.4, - DeviceHandlerIF::GET_WRITE); - thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.6, - DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.8, - DeviceHandlerIF::GET_READ); + thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0, + DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.2, + DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.4, + DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.6, + DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.8, + DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::GYRO_2_L3G_HANDLER, length * 0, @@ -560,15 +652,25 @@ ReturnValue_t pst::pollingSequenceTest(FixedTimeslotTaskIF* thisSequence) { thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); #endif - static_cast(length); - if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { - return HasReturnvaluesIF::RETURN_OK; - } - sif::error << "PollingSequence::initialize has errors!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; +#if RPI_TEST_GPS_HANDLER == 1 + thisSequence->addSlot(objects::GPS0_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + + thisSequence->addSlot(objects::GPS0_HANDLER, length * 0, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::GPS0_HANDLER, length * 0, DeviceHandlerIF::GET_READ); + + thisSequence->addSlot(objects::GPS0_HANDLER, length * 0.5, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::GPS0_HANDLER, length * 0.5, DeviceHandlerIF::GET_READ); +#endif + static_cast(length); + if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) { + sif::error << "Test PST initialization failed" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; } +#if TE7020 == 1 ReturnValue_t pst::pollingSequenceTE0720(FixedTimeslotTaskIF *thisSequence) { uint32_t length = thisSequence->getPeriodMs(); @@ -617,4 +719,4 @@ ReturnValue_t pst::pollingSequenceTE0720(FixedTimeslotTaskIF *thisSequence) { } return HasReturnvaluesIF::RETURN_OK; } - +#endif /* TE7020 == 1 */ diff --git a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.h b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.h index e05f96aa..a2b5edfb 100644 --- a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.h +++ b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.h @@ -1,7 +1,14 @@ #ifndef POLLINGSEQUENCEFACTORY_H_ #define POLLINGSEQUENCEFACTORY_H_ -#include +#include "OBSWConfig.h" +#if defined(RASPBERRY_PI) +#include "rpiConfig.h" +#elif defined(XIPHOS_Q7S) +#include "q7sConfig.h" +#endif + +#include "fsfw/returnvalues/HasReturnvaluesIF.h" class FixedTimeslotTaskIF; @@ -25,21 +32,36 @@ class FixedTimeslotTaskIF; namespace pst { /* 0.4 second period init*/ -ReturnValue_t pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence); +ReturnValue_t pstGpio(FixedTimeslotTaskIF *thisSequence); /** - * @brief This function creates the PST for all gomspace devices. They are - * scheduled in a separate PST because the gomspace library uses - * blocking calls when requesting data from devices. + * @brief This function creates the PST for all gomspace devices. + * @details + * Scheduled in a separate PST because the gomspace library uses blocking calls when requesting + * data from devices. */ -ReturnValue_t gomspacePstInit(FixedTimeslotTaskIF *thisSequence); +ReturnValue_t pstGompaceCan(FixedTimeslotTaskIF *thisSequence); -ReturnValue_t pollingSequenceTest(FixedTimeslotTaskIF* thisSequence); +ReturnValue_t pstUart(FixedTimeslotTaskIF* thisSequence); +ReturnValue_t pstSpi(FixedTimeslotTaskIF* thisSequence); + +ReturnValue_t pstI2c(FixedTimeslotTaskIF* thisSequence); + +/** + * Generic test PST + * @param thisSequence + * @return + */ +ReturnValue_t pstTest(FixedTimeslotTaskIF* thisSequence); + +#if TE7020 == 1 /** * @brief This polling sequence will be created when the software is compiled for the TE0720. */ ReturnValue_t pollingSequenceTE0720(FixedTimeslotTaskIF* thisSequence); +#endif + } 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 22a4a09c..16bd992b 100644 --- a/misc/eclipse/.cproject +++ b/misc/eclipse/.cproject @@ -19,25 +19,25 @@ - + - @@ -77,19 +77,23 @@ - @@ -127,7 +131,7 @@ - +