Compare commits

..

1 Commits

Author SHA1 Message Date
0a11ca6051 Merge pull request 'Update to v1.8.0' (#100) from develop into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #100
2021-09-24 10:17:43 +02:00
397 changed files with 25297 additions and 39952 deletions

View File

@ -1,8 +0,0 @@
---
BasedOnStyle: Google
IndentWidth: 2
---
Language: Cpp
ColumnLimit: 100
ReflowComments: true
---

3
.gitignore vendored
View File

@ -8,9 +8,6 @@
!misc/eclipse/**/.cproject
!misc/eclipse/**/.project
#vscode
/.vscode
# Python
__pycache__
.idea

View File

@ -13,32 +13,34 @@ cmake_minimum_required(VERSION 3.13)
set(CMAKE_SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
option(EIVE_ADD_ETL_LIB "Add ETL library" ON)
option(EIVE_ADD_JSON_LIB "Add JSON library" ON)
option(EIVE_SYSROOT_MAGIC "Perform sysroot magic which might not be necessary" OFF)
option(EIVE_CREATE_UNIQUE_OBSW_BIN "Append username to generated binary name" ON)
if(NOT FSFW_OSAL)
set(FSFW_OSAL linux CACHE STRING "OS for the FSFW.")
if(TGT_BSP MATCHES "arm/q7s")
option(EIVE_BUILD_WATCHDOG "Compile the OBSW watchdog insted" OFF)
option(BUILD_Q7S_SIMPLE_MODE OFF "Simple mode with a minimal main function")
endif()
if(TGT_BSP)
if(TGT_BSP MATCHES "arm/raspberrypi" OR TGT_BSP MATCHES "arm/beagleboneblack")
option(LINUX_CROSS_COMPILE ON)
option(EIVE_BUILD_GPSD_GPS_HANDLER "Build GPSD dependent GPS Handler" OFF)
elseif(TGT_BSP MATCHES "arm/q7s")
option(EIVE_BUILD_GPSD_GPS_HANDLER "Build GPSD dependent GPS Handler" ON)
endif()
option(ADD_ETL_LIB "Add ETL library" ON)
option(ADD_JSON_LIB "Add JSON library" ON)
option(EIVE_SYSROOT_MAGIC "Perform sysroot magic which might not be necessary" OFF)
if(NOT FSFW_OSAL)
set(FSFW_OSAL host CACHE STRING "OS for the FSFW.")
endif()
if(TGT_BSP MATCHES "arm/raspberrypi" OR TGT_BSP MATCHES "arm/beagleboneblack")
option(LINUX_CROSS_COMPILE ON)
endif()
# Perform steps like loading toolchain files where applicable.
include(${CMAKE_SCRIPT_PATH}/PreProjectConfig.cmake)
pre_project_config()
set(PROJECT_NAME_TO_SET eive-obsw-$ENV{USERNAME})
if(EIVE_BUILD_WATCHDOG)
set(PROJECT_NAME_TO_SET eive-watchdog)
endif()
# Project Name
project(eive-obsw ASM C CXX)
project(${PROJECT_NAME_TO_SET} ASM C CXX)
################################################################################
# Pre-Sources preparation
@ -49,42 +51,34 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# Set names and variables
set(OBSW_NAME ${CMAKE_PROJECT_NAME})
set(WATCHDOG_NAME eive-watchdog)
set(SIMPLE_OBSW_NAME eive-simple)
set(UNITTEST_NAME eive-unittest)
set(TARGET_NAME ${CMAKE_PROJECT_NAME})
set(LIB_FSFW_NAME fsfw)
set(LIB_EIVE_MISSION eive-mission)
set(LIB_ETL_NAME etl)
set(LIB_CSP_NAME libcsp)
set(LIB_LWGPS_NAME lwgps)
set(LIB_ARCSEC wire)
set(THIRD_PARTY_FOLDER thirdparty)
set(LIB_CXX_FS -lstdc++fs)
set(LIB_CATCH2 Catch2)
set(LIB_GPS gps)
set(LIB_JSON_NAME nlohmann_json::nlohmann_json)
# Set path names
set(FSFW_PATH fsfw)
set(MISSION_PATH mission)
set(TEST_PATH test/testtasks)
set(UNITTEST_PATH unittest)
set(LINUX_PATH linux)
set(COMMON_PATH common)
set(WATCHDOG_PATH watchdog)
set(COMMON_CONFIG_PATH ${COMMON_PATH}/config)
set(UNITTEST_CFG_PATH ${UNITTEST_PATH}/testcfg)
set(LIB_EIVE_MISSION_PATH mission)
set(LIB_CSP_PATH ${THIRD_PARTY_FOLDER}/libcsp)
set(LIB_ETL_PATH ${THIRD_PARTY_FOLDER}/etl)
set(LIB_CATCH2_PATH ${THIRD_PARTY_FOLDER}/Catch2)
set(LIB_LWGPS_PATH ${THIRD_PARTY_FOLDER}/lwgps)
set(LIB_ARCSEC_PATH ${THIRD_PARTY_FOLDER}/arcsec_star_tracker)
set(FSFW_HAL_LIB_PATH fsfw_hal)
set(CSP_LIB_PATH ${THIRD_PARTY_FOLDER}/libcsp)
set(ETL_LIB_PATH ${THIRD_PARTY_FOLDER}/etl)
set(LWGPS_LIB_PATH ${THIRD_PARTY_FOLDER}/lwgps)
set(ARCSEC_LIB_PATH ${THIRD_PARTY_FOLDER}/arcsec_star_tracker)
set(LIB_JSON_PATH ${THIRD_PARTY_FOLDER}/json)
set(FSFW_WARNING_SHADOW_LOCAL_GCC OFF)
set(EIVE_ADD_LINUX_FILES False)
set(ADD_LINUX_FILES False)
# Analyse different OS and architecture/target options, determine BSP_PATH,
# display information about compiler etc.
@ -93,27 +87,21 @@ pre_source_hw_os_config()
if(TGT_BSP)
if(TGT_BSP MATCHES "arm/q7s" OR TGT_BSP MATCHES "arm/raspberrypi"
OR TGT_BSP MATCHES "arm/beagleboneblack" OR TGT_BSP MATCHES "arm/egse"
OR TGT_BSP MATCHES "arm/beagleboneblack"
)
set(FSFW_CONFIG_PATH "linux/fsfwconfig")
if(NOT BUILD_Q7S_SIMPLE_MODE)
set(EIVE_ADD_LINUX_FILES TRUE)
set(ADD_LINUX_FILES TRUE)
set(ADD_CSP_LIB TRUE)
set(FSFW_HAL_ADD_LINUX ON)
endif()
endif()
if(TGT_BSP MATCHES "arm/raspberrypi" )
if(TGT_BSP MATCHES "arm/raspberrypi")
# Used by configure file
set(RASPBERRY_PI ON)
set(FSFW_HAL_ADD_RASPBERRY_PI ON)
endif()
if(TGT_BSP MATCHES "arm/egse")
# Used by configure file
set(EGSE ON)
set(FSFW_HAL_LINUX_ADD_LIBGPIOD OFF)
endif()
if(TGT_BSP MATCHES "arm/beagleboneblack")
# Used by configure file
@ -129,19 +117,17 @@ else()
set(FSFW_CONFIG_PATH "${BSP_PATH}/fsfwconfig")
endif()
# Configuration files
configure_file(${COMMON_CONFIG_PATH}/commonConfig.h.in commonConfig.h)
configure_file(${FSFW_CONFIG_PATH}/FSFWConfig.h.in FSFWConfig.h)
configure_file(${FSFW_CONFIG_PATH}/OBSWConfig.h.in OBSWConfig.h)
if(TGT_BSP MATCHES "arm/q7s")
configure_file(${BSP_PATH}/boardconfig/q7sConfig.h.in q7sConfig.h)
elseif(TGT_BSP MATCHES "arm/raspberrypi" OR TGT_BSP MATCHES "arm/egse")
configure_file(${BSP_PATH}/boardconfig/rpiConfig.h.in rpiConfig.h)
if(NOT EIVE_BUILD_WATCHDOG)
configure_file(${COMMON_CONFIG_PATH}/commonConfig.h.in commonConfig.h)
configure_file(${FSFW_CONFIG_PATH}/FSFWConfig.h.in FSFWConfig.h)
configure_file(${FSFW_CONFIG_PATH}/OBSWConfig.h.in OBSWConfig.h)
if(TGT_BSP MATCHES "arm/q7s")
configure_file(${BSP_PATH}/boardconfig/q7sConfig.h.in q7sConfig.h)
elseif(TGT_BSP MATCHES "arm/raspberrypi")
configure_file(${BSP_PATH}/boardconfig/rpiConfig.h.in rpiConfig.h)
endif()
endif()
configure_file(${WATCHDOG_PATH}/watchdogConf.h.in watchdogConf.h)
# Set common config path for FSFW
@ -150,30 +136,120 @@ set(FSFW_ADDITIONAL_INC_PATHS
${CMAKE_CURRENT_BINARY_DIR}
)
# Check whether the user has already installed Catch2 first
find_package(Catch2 3)
################################################################################
# Executable and Sources
################################################################################
#global compiler options need to be set before adding executables
# Add executable
add_executable(${TARGET_NAME})
if(ADD_ETL_LIB)
add_subdirectory(${ETL_LIB_PATH})
endif()
if(ADD_JSON_LIB)
add_subdirectory(${LIB_JSON_PATH})
endif()
if(NOT EIVE_BUILD_WATCHDOG)
if(ADD_LINUX_FILES)
add_subdirectory(${LINUX_PATH})
endif()
add_subdirectory(${BSP_PATH})
add_subdirectory(${COMMON_PATH})
if(ADD_CSP_LIB)
add_subdirectory(${CSP_LIB_PATH})
endif()
endif()
if((NOT BUILD_Q7S_SIMPLE_MODE) AND (NOT EIVE_BUILD_WATCHDOG))
add_subdirectory(${LWGPS_LIB_PATH})
add_subdirectory(${FSFW_PATH})
add_subdirectory(${MISSION_PATH})
add_subdirectory(${TEST_PATH})
add_subdirectory(${ARCSEC_LIB_PATH})
endif()
if(EIVE_BUILD_WATCHDOG)
add_subdirectory(${WATCHDOG_PATH})
endif()
################################################################################
# Post-Sources preparation
################################################################################
set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux)
if((NOT BUILD_Q7S_SIMPLE_MODE) AND (NOT EIVE_BUILD_WATCHDOG))
# Add libraries for all sources.
target_link_libraries(${TARGET_NAME} PRIVATE
${LIB_FSFW_NAME}
${LIB_OS_NAME}
${LIB_LWGPS_NAME}
)
if(TGT_BSP MATCHES "arm/q7s")
target_link_libraries(${TARGET_NAME} PRIVATE
${LIB_ARCSEC}
)
endif()
endif()
if(NOT EIVE_BUILD_WATCHDOG)
if(ADD_CSP_LIB)
target_link_libraries(${TARGET_NAME} PRIVATE
${LIB_CSP_NAME}
)
endif()
endif()
if(ADD_ETL_LIB)
target_link_libraries(${TARGET_NAME} PRIVATE
${LIB_ETL_NAME}
)
endif()
if(ADD_JSON_LIB)
target_link_libraries(${TARGET_NAME} PRIVATE
${LIB_JSON_NAME}
)
endif()
target_link_libraries(${TARGET_NAME} PRIVATE
${LIB_CXX_FS}
)
# Add include paths for all sources.
target_include_directories(${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${FSFW_CONFIG_PATH}
${CMAKE_CURRENT_BINARY_DIR}
${ARCSEC_LIB_PATH}
)
if(TGT_BSP MATCHES "arm/q7s")
target_include_directories(${TARGET_NAME} PRIVATE
${ARCSEC_LIB_PATH}
)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_compile_options(
"-Wall"
"-Wextra"
"-Wimplicit-fallthrough=1"
"-Wno-unused-parameter"
"-Wno-psabi"
set(WARNING_FLAGS
-Wall
-Wextra
-Wimplicit-fallthrough=1
-Wno-unused-parameter
-Wno-psabi
)
# Remove unused sections.
add_compile_options(
target_compile_options(${TARGET_NAME} PRIVATE
"-ffunction-sections"
"-fdata-sections"
)
# Removed unused sections.
add_link_options(
target_link_options(${TARGET_NAME} PRIVATE
"-Wl,--gc-sections"
)
@ -181,162 +257,15 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(COMPILER_FLAGS "/permissive-")
endif()
# Not installed, so use FetchContent to download and provide Catch2
if(NOT Catch2_FOUND)
include(FetchContent)
FetchContent_Declare(
Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v3.0.0-preview4
)
FetchContent_MakeAvailable(Catch2)
#fixes regression -preview4, to be confirmed in later releases
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
set_target_properties(Catch2 PROPERTIES EXCLUDE_FROM_ALL "true")
set_target_properties(Catch2WithMain PROPERTIES EXCLUDE_FROM_ALL "true")
endif()
add_library(${LIB_EIVE_MISSION})
# Add main executable
add_executable(${OBSW_NAME})
if(EIVE_CREATE_UNIQUE_OBSW_BIN)
set(OBSW_BIN_NAME ${CMAKE_PROJECT_NAME}-$ENV{USERNAME})
else()
set(OBSW_BIN_NAME ${CMAKE_PROJECT_NAME})
endif()
set_target_properties(${OBSW_NAME} PROPERTIES OUTPUT_NAME ${OBSW_BIN_NAME})
#watchdog
add_executable(${WATCHDOG_NAME} EXCLUDE_FROM_ALL)
add_subdirectory(${WATCHDOG_PATH})
target_link_libraries(${WATCHDOG_NAME} PUBLIC
${LIB_CXX_FS}
)
target_include_directories(${WATCHDOG_NAME} PUBLIC
${CMAKE_BINARY_DIR}
)
#unittests
add_executable(${UNITTEST_NAME} EXCLUDE_FROM_ALL)
if(EIVE_ADD_ETL_LIB)
add_subdirectory(${LIB_ETL_PATH})
endif()
if(EIVE_ADD_JSON_LIB)
add_subdirectory(${LIB_JSON_PATH})
endif()
if(EIVE_ADD_LINUX_FILES)
add_subdirectory(${LIB_ARCSEC_PATH})
add_subdirectory(${LINUX_PATH})
endif()
add_subdirectory(${BSP_PATH})
if(ADD_CSP_LIB)
add_subdirectory(${LIB_CSP_PATH})
endif()
add_subdirectory(${COMMON_PATH})
add_subdirectory(${LIB_LWGPS_PATH})
add_subdirectory(${FSFW_PATH})
add_subdirectory(${LIB_EIVE_MISSION_PATH})
add_subdirectory(${TEST_PATH})
add_subdirectory(${UNITTEST_PATH})
################################################################################
# Post-Sources preparation
################################################################################
# Add libraries
target_link_libraries(${LIB_EIVE_MISSION} PUBLIC
${LIB_FSFW_NAME}
${LIB_LWGPS_NAME}
${LIB_OS_NAME}
)
target_link_libraries(${OBSW_NAME} PRIVATE
${LIB_EIVE_MISSION}
)
if(TGT_BSP MATCHES "arm/q7s")
target_link_libraries(${LIB_EIVE_MISSION} PUBLIC
${LIB_ARCSEC}
${LIB_GPS}
)
endif()
target_link_libraries(${UNITTEST_NAME} PRIVATE
Catch2
${LIB_EIVE_MISSION}
)
if(TGT_BSP MATCHES "arm/egse")
target_link_libraries(${OBSW_NAME} PRIVATE
${LIB_ARCSEC}
)
endif()
if(ADD_CSP_LIB)
target_link_libraries(${OBSW_NAME} PRIVATE
${LIB_CSP_NAME}
)
endif()
if(EIVE_ADD_ETL_LIB)
target_link_libraries(${LIB_EIVE_MISSION} PUBLIC
${LIB_ETL_NAME}
)
endif()
if(EIVE_ADD_JSON_LIB)
target_link_libraries(${LIB_EIVE_MISSION} PUBLIC
${LIB_JSON_NAME}
)
endif()
target_link_libraries(${LIB_EIVE_MISSION} PUBLIC
${LIB_CXX_FS}
)
# Add include paths for all sources.
target_include_directories(${LIB_EIVE_MISSION} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${FSFW_CONFIG_PATH}
${CMAKE_CURRENT_BINARY_DIR}
${LIB_ARCSEC_PATH}
)
if(TGT_BSP MATCHES "arm/q7s" OR TGT_BSP MATCHES "arm/egse")
target_include_directories(${LIB_EIVE_MISSION} PUBLIC
${ARCSEC_LIB_PATH}
)
endif()
if(CMAKE_VERBOSE)
message(STATUS "Warning flags: ${WARNING_FLAGS}")
endif()
# Compile options for all sources.
target_compile_options(${TARGET_NAME} PRIVATE
${WARNING_FLAGS}
)
if(${CMAKE_CROSSCOMPILING})
include (${CMAKE_SCRIPT_PATH}/HardwareOsPostConfig.cmake)
@ -368,12 +297,11 @@ string(CONCAT POST_BUILD_COMMENT
)
add_custom_command(
TARGET ${OBSW_NAME}
TARGET ${TARGET_NAME}
POST_BUILD
COMMAND ${CMAKE_SIZE} ${OBSW_BIN_NAME}${FILE_SUFFIX}
COMMAND ${CMAKE_SIZE} ${TARGET_NAME}${FILE_SUFFIX}
COMMENT ${POST_BUILD_COMMENT}
)
include (${CMAKE_SCRIPT_PATH}/BuildType.cmake)
set_build_type()

View File

@ -1,12 +0,0 @@
python_script := './cmake/scripts/cmake-build-cfg.py'
default: q7s-debug-make
q7s-debug-make:
{{python_script}} -o linux -g make -b debug -t "arm/q7s" -l build-Debug-Q7S
q7s-release-make:
{{python_script}} -o linux -g make -b release -t "arm/q7s" -l build-Release-Q7S
q7s-debug-ninja:
{{python_script}} -o linux -g ninja -b debug -t "arm/q7s" -l build-Debug-Q7S

203
README.md
View File

@ -11,18 +11,13 @@
4. [Useful and Common Host Commands](#host-commands)
5. [Setting up Prerequisites](#set-up-prereq)
6. [Remote Debugging](#remote-debugging)
6. [Remote Reset](#remote-reset)
8. [TMTC testing](#tmtc-testing)
9. [Direct Debugging](#direct-debugging)
10. [Transfering Files to the Q7S](#file-transfer)
11. [Q7S OBC](#q7s)
12. [Static Code Analysis](#static-code-analysis)
13. [Eclipse](#eclipse)
14. [Running the OBSW on a Raspberry Pi](#rpi)
15. [Running OBSW on EGSE](#egse)
16. [Manually preparing sysroots to compile gpsd](#gpsd)
17. [FSFW](#fsfw)
18. [Coding Style](#coding-style)
7. [Direct Debugging](#direct-debugging)
8. [Transfering Files to the Q7S](#file-transfer)
9. [Q7S OBC](#q7s)
10. [Static Code Analysis](#static-code-analysis)
11. [Eclipse](#eclipse)
12. [Running the OBSW on a Raspberry Pi](#rpi)
13. [FSFW](#fsfw)
# <a id="general"></a> General information
@ -40,7 +35,7 @@ Target systems:
relevant pages. The most recent datasheet can be found
[here](https://trac2.xiphos.ca/manual/wiki/Q7RevB/UserManual).
* Linux OS built with Yocto 2.5
* [Linux Kernel](https://github.com/XiphosSystemsCorp/linux-xlnx.git) . EIVE version can be found
* 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)
@ -107,7 +102,7 @@ When using Windows, run theses steps in MSYS2.
```sh
mkdir build-Debug-Q7S && cd build-Debug-Q7S
cmake -DTGT_BSP="arm/q7s" -DCMAKE_BUILD_TYPE=Debug ..
cmake -DTGT_BSP="arm/q7s" -DCMAKE_BUILD_TYPE=Debug -DOS_FSFW=linux ..
cmake --build . -j
```
@ -122,7 +117,8 @@ When using Windows, run theses steps in MSYS2.
This will invoke a Python script which in turn invokes CMake with the correct
arguments to configure CMake for Q7S cross-compilation.
There are also different values for `-DTGT_BSP` to build for the Raspberry Pi
You can build the hosted variant of the OBSW by replacing `-DOS_FSFW=linux` with
`-DOS_FSFW=host`. There are also different values for `-DTGT_BSP` to build for the Raspberry Pi
or the Beagle Bone Black: `arm/raspberrypi` and `arm/beagleboneblack`.
5. Build the software with
@ -161,47 +157,20 @@ automatically.
### Q7S OBSW
The EIVE OBSW is the default target if no target is specified.
```sh
mkdir build-Debug-Q7S && cd build-Debug-Q7S
cmake -DTGT_BSP=arm/q7s -DCMAKE_BUILD_TYPE=Debug ..
cmake -DTGT_BSP=arm/q7s -DFSFW_OSAL=linux -DCMAKE_BUILD_TYPE=Debug ..
cmake --build . -j
```
### Q7S Watchdog
To build the EIVE watchdog, the corresponding target must be specified in the build command.
The configure steps do not need to be repeated if the folder has already been configured.
```sh
mkdir build-Debug-Watchdog && cd build-Debug-Watchdog
cmake -DTGT_BSP=arm/q7s -DCMAKE_BUILD_TYPE=Debug ..
cmake --build . --target eive-watchdog -j
```
### Hosted
You can also use the FSFW OSAL `host` to build on Windows or for generic OSes.
Note: Currently this is not supported.
```sh
mkdir build-Debug-Host && cd build-Debug-Host
cmake -DFSFW_OSAL=host -DCMAKE_BUILD_TYPE=Debug ..
mkdir build-Debug-Q7S && cd build-Debug-Q7S
cmake -DTGT_BSP=arm/q7s -DFSFW_OSAL=linux -DEIVE_BUILD_WATCHDOG=ON -DCMAKE_BUILD_TYPE=Debug ..
cmake --build . -j
```
### Unittests
To build the unittests, the corresponding target must be specified in the build command.
The configure steps do not need to be repeated if the folder has already been configured.
```sh
mkdir build-Debug-Unittest && cd build-Debug-Unittest
cmake ..
cmake --build . --target eive-unittests -j
```
## Connect to EIVE flatsat
### DNS
@ -442,24 +411,12 @@ Beagle Bone Black for download here
Download it and unzip it somewhere in the Xilinx installation folder.
You can use the following command if `wget` can be used or for CI/CD:
```sh
wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/SyXpdBBQX32xPgE/download/cortexa9hf-neon-xiphos-linux-gnueabi.tar.gz
```
wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/agnJGYeRf6fw2ci/download/cortexa9hf-neon-xiphos-linux-gnueabi.tar.gz
```
Then, create a new environmental variables `Q7S_SYSROOT` and set it to the local system root path.
### Updating system root for CI
If the system root is updated, it needs to be manually updated on the buggy file server.
If access on `buggy.irs.uni-stuttgart.de` is possible with `ssh` and the rootfs in the cloud
[was updated](https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Software/rootfs&fileid=831849)
as well, you can update the rootfs like this:
```sh
cd /var/www/eive/tools
wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/SyXpdBBQX32xPgE/download/cortexa9hf-neon-xiphos-linux-gnueabi.tar.gz
```
## Setting up UNIX environment for real-time functionalities
Please note that on most UNIX environments (e.g. Ubuntu), the real time functionalities
@ -557,10 +514,10 @@ ssh root@192.168.133.10
```
If this has not been done yet, you can access the serial
console of the Q7S like this
console of the Q7S like this to set it
```sh
picocom -b 115200 /dev/q7sSerial
picocom -b 115200 /dev/ttyUSB0
```
The flatsat has the aliases and shell scripts `q7s_ssh` and `q7s_serial` for this task as well.
@ -597,63 +554,6 @@ alias or shell script to do this quickly.
Note: When now setting up a debug session in the Xilinx SDK or Eclipse, the host must be set
to localhost instead of the IP address of the Q7S.
# <a id="remote-reset"></a> Remote Reset
1. Launch xilinx hardware server on flatsat with alias
````
launch-hwserver-xilinx
````
2. On host PC start xsc
3. In xsct console type the follwing command to connect to the hardware server (replace </flatsat-pc-ip-address/> with the IP address of the flatsat PC. Can be found out with ifconfig)
````
connect -url tcp:</flatsat-pc-ip-address/>:3121
````
4. The following command will list all available devices
````
targets
````
5. Connect to the APU of the Q7S
````
target </APU-number/>
````
6. Perform reset
````
rst
````
# <a id="tmtc-testing"></a> TMTC testing
The OBSW supports sending PUS TM packets via TCP or the PDEC IP Core which transmits the data as
CADU frames. To make the CADU frames receivabel by the
[TMTC porgram](https://egit.irs.uni-stuttgart.de/eive/eive-tmtc), a python script is running as
`systemd` service named `tmtc_bridge` on the flatsat PC which forwards TCP commands to the TCP
server of the OBC and reads CADU frames from a serial interface.
You can check whether the service is running the following command on the flatsat PC
```sh
systemctl status tmtc_bridge
```
The PUS packets transported with the CADU frames are extracted
and forwared to the TMTC program's TCP client. The code of the TMTC bridge can be found
[here](https://egit.irs.uni-stuttgart.de/eive/tmtc-bridge). To connect the TMTC program to the
TMTC-bridge a port forwarding from a host must be set up with the following command:
```sh
ssh -L 1537:127.0.0.1:7100 eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 -t bash
```
You can print the output of the `systemd` service with
```sh
journalctl -u tmtc_bridge
```
This can be helpful to determine whether any TCs arrive or TMs are coming back.
Note: The encoding of the TM packets and conversion of CADU frames takes some time.
Thus the replies are received with a larger delay compared to a direct TCP connection.
# <a id="direct-debugging"></a> Direct Debugging
1. Assign static IP address to Q7S
@ -1066,7 +966,26 @@ cat file.bin | hexdump -v -n X
## Preparation of a fresh rootfs and SD card
See [q7s-package repository README](https://egit.irs.uni-stuttgart.de/eive/q7s-package)
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 a few shell helper scripts
- Folder `profile.d` in `/etc` folder which contains the `path-set.sh` script
which is sourced at software startup
- Library `libwire.so` in `/usr/lib` folder
### SD Cards
- Folder `bin` for binaries, for example the OBSW
- Folder `misc` for miscellaneous files. Contains `ls` for directory listings
- Folder `tc` for telecommands
- Folder `tm` for telemetry
- Folder `xdi` for XDI components (e.g. for firmware or device tree updates)
# <a id="static-code-analysis"></a> Running cppcheck on the Software
@ -1114,7 +1033,7 @@ The [TCF agent](https://wiki.eclipse.org/TCF) can be used to perform remote debu
1. Install the TCF agent plugin in Eclipse from
the [releases](https://www.eclipse.org/tcf/downloads.php). Go to
Help &rarr; Install New Software and use the download page, for
example https://download.eclipse.org/tools/tcf/releases/1.7/1.7.0/ to search for the plugin and install it. You can find the newest version [here](https://www.eclipse.org/tcf/downloads.php)
example https://download.eclipse.org/tools/tcf/releases/1.6/1.6.2/ to search for the plugin and install it.
2. Go to Window &rarr; Perspective &rarr; Open Perspective and open the **Target Explorer Perspective**.
Here, the Q7S should show up if the local port forwarding was set up as explained previously.
@ -1153,38 +1072,6 @@ sudo apt-get install gpiod libgpiod-dev
to install the required GPIO libraries before cloning the system root folder.
# <a id="egse"></a> Running OBSW on EGSE
The EGSE is a test system from arcsec build arround a raspberry pi 4 to test the star tracker. The IP address of the EGSE (raspberry pi) is 192.168.18.31. An ssh session can be opened with
````
ssh pi@192.168.18.31
````
Password: raspberry
To run the obsw perform the following steps:
1. Build the cmake EGSE Configuration
* the sysroots for the EGSE can be found [here](https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Software/egse&fileid=1190471)
* toolchain for linux host can be downloaded from [here](https://github.com/Pro/raspi-toolchain)
* toolchain for windows host from [here](https://gnutoolchains.com/raspberry/) (the raspios-buster-armhf toolchain is the right one for the EGSE)
2. Disable the ser2net systemd service on the EGSE
````sh
$ sudo systemctl stop ser2net.service
````
3. Power on the star tracker by running
````sh
$ ~/powerctrl/enable0.sh`
````
4. Run portforwarding script for tmtc tcp connection and tcf agent on host PC
````sh
$ ./scripts/egse-port.sh
````
5. The star tracker can be powered off by running
````sh
$ ~/powerctrl/disable0.sh
````
# <a id="gpsd"></a> Manually preparing sysroots to compile gpsd
Copy all header files from [here](https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Software/gpsd&fileid=1189985) to the /usr/include directory and all static libraries to /usr/lib.
# <a id="fsfw"></a> Flight Software Framework (FSFW)
An EIVE fork of the FSFW is submodules into this repository.
@ -1204,15 +1091,3 @@ git merge upstream/master
Alternatively, changes from other upstreams (forks) and branches can be merged like that
in the same way.
# <a id="coding-style"></a> Coding Style
* the formatting is based on the clang-format tools
## Setting up eclipse auto-fromatter with clang-format
1. Help &rarr; Install New Software &rarr; Add
2. In location insert the link http://www.cppstyle.com/luna
3. The software package CppStyle should now be available for installation
4. On windows download the clang-formatting tools from https://llvm.org/builds/. On linux clang-format can be installed with the package manager.
5. Navigate to Preferences &rarr; C/C++ &rarr; CppStyle
6. Insert the path to the clang-format executable
7. Under C/C++ &rarr; Code Style &rarr; Formatter, change the formatter to CppStyle (clang-format)
8. Code can now be formatted with the clang tool by using the key combination Ctrl + Shift + f

View File

@ -2,9 +2,7 @@ FROM ubuntu:focal
RUN apt-get update
RUN apt-get --yes upgrade
#tzdata is a dependency, won't install otherwise
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get --yes install cmake libgpiod-dev xz-utils nano curl git gcc g++ lcov valgrind libgps-dev
RUN apt-get --yes install cmake libgpiod-dev xz-utils nano curl
# Q7S root filesystem, required for cross-compilation.
RUN mkdir -p /usr/rootfs; \
@ -16,5 +14,6 @@ RUN mkdir -p /usr/tools; \
curl https://buggy.irs.uni-stuttgart.de/eive/tools/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf.tar.gz \
| tar -xz -C /usr/tools
ENV Q7S_SYSROOT="/usr/rootfs/cortexa9hf-neon-xiphos-linux-gnueabi"
ENV PATH=$PATH:"/usr/tools/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin"
ENV PATH=$PATH:"/usr/tools/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin"

View File

@ -1,36 +1,48 @@
pipeline {
environment {
BUILDDIR_Q7 = 'build_q7'
BUILDDIR_LINUX = 'build_linux'
}
agent {
docker {
image 'eive-obsw-ci:d2'
args '--sysctl fs.mqueue.msg_max=100'
}
}
agent any
stages {
stage('Clean') {
stage('Build Container') {
when {
changeset "automation/Dockerfile-q7s"
branch 'develop'
}
steps {
sh 'rm -rf $BUILDDIR_Q7'
sh 'rm -rf $BUILDDIR_LINUX'
sh 'docker build -t eive-fsw-build-q7s:gcc8 - < automation/Dockerfile-q7s'
}
}
stage('Clean') {
when {
anyOf {
changelog 'cleanCI'
changeset '*.cmake'
changeset 'CMakeLists.txt'
}
}
steps {
sh 'rm -rf build-q7s-debug'
}
}
stage('Build Q7S') {
agent {
docker {
image 'eive-fsw-build-q7s:gcc8'
reuseNode true
}
}
steps {
dir(BUILDDIR_Q7) {
sh 'cmake -DTGT_BSP="arm/q7s" -DCMAKE_BUILD_TYPE=Debug ..'
dir('build-q7s-debug') {
sh 'cmake -DTGT_BSP="arm/q7s" -DCMAKE_BUILD_TYPE=Debug -DFSFW_OSAL=linux ..'
sh 'cmake --build . -j'
}
}
}
stage('Unittests') {
stage('Deploy') {
when {
tag 'v*.*.*'
}
steps {
dir(BUILDDIR_LINUX) {
sh 'cmake ..'
sh 'cmake --build . -t eive-unittest -j'
sh './eive-unittest'
}
sh 'echo Deploying'
}
}
}

View File

@ -1,7 +0,0 @@
target_sources(${OBSW_NAME} PUBLIC
InitMission.cpp
main.cpp
ObjectFactory.cpp
)
add_subdirectory(boardconfig)

View File

@ -1,192 +0,0 @@
#include "InitMission.h"
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/objectmanager/ObjectManagerIF.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
#include <fsfw/tasks/PeriodicTaskIF.h>
#include <fsfw/tasks/TaskFactory.h>
#include <mission/utility/InitMission.h>
#include <iostream>
#include "OBSWConfig.h"
#include "ObjectFactory.h"
#include "objects/systemObjectList.h"
#include "pollingsequence/pollingSequenceFactory.h"
ServiceInterfaceStream sif::debug("DEBUG");
ServiceInterfaceStream sif::info("INFO");
ServiceInterfaceStream sif::warning("WARNING");
ServiceInterfaceStream sif::error("ERROR");
ObjectManagerIF* objectManager = nullptr;
void initmission::initMission() {
sif::info << "Make sure the systemd service ser2net on the egse has been stopped "
<< "(alias stop-ser2net)" << std::endl;
sif::info << "Make sure the power lines of the star tracker have been enabled "
<< "(alias enable-startracker)" << std::endl;
sif::info << "Building global objects.." << std::endl;
/* Instantiate global object manager and also create all objects */
ObjectManager::instance()->setObjectFactoryFunction(ObjectFactory::produce, nullptr);
sif::info << "Initializing all objects.." << std::endl;
ObjectManager::instance()->initialize();
/* This function creates and starts all tasks */
initTasks();
}
void initmission::initTasks() {
TaskFactory* factory = TaskFactory::instance();
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if (factory == nullptr) {
/* Should never happen ! */
return;
}
#if OBSW_PRINT_MISSED_DEADLINES == 1
void (*missedDeadlineFunc)(void) = TaskFactory::printMissedDeadline;
#else
void (*missedDeadlineFunc)(void) = nullptr;
#endif
/* TMTC Distribution */
PeriodicTaskIF* tmtcDistributor = factory->createPeriodicTask(
"DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmtcDistributor->addComponent(objects::CCSDS_PACKET_DISTRIBUTOR);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
result = tmtcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
result = tmtcDistributor->addComponent(objects::TM_FUNNEL);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
PeriodicTaskIF* tmtcBridgeTask = factory->createPeriodicTask(
"TMTC_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmtcBridgeTask->addComponent(objects::TMTC_BRIDGE);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component TMTC Bridge failed" << std::endl;
}
PeriodicTaskIF* tmtcPollingTask = factory->createPeriodicTask(
"TMTC_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = tmtcPollingTask->addComponent(objects::TMTC_POLLING_TASK);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component TMTC Polling failed" << std::endl;
}
/* PUS Services */
std::vector<PeriodicTaskIF*> pusTasks;
createPusTasks(*factory, missedDeadlineFunc, pusTasks);
std::vector<PeriodicTaskIF*> pstTasks;
FixedTimeslotTaskIF* pst = factory->createFixedTimeslotTask(
"STAR_TRACKER_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.5, missedDeadlineFunc);
result = pst::pstUart(pst);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl;
}
pstTasks.push_back(pst);
PeriodicTaskIF* strHelperTask = factory->createPeriodicTask(
"STR_HELPER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = strHelperTask->addComponent(objects::STR_HELPER);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("STR_HELPER", objects::STR_HELPER);
}
pstTasks.push_back(strHelperTask);
auto taskStarter = [](std::vector<PeriodicTaskIF*>& taskVector, std::string name) {
for (const auto& task : taskVector) {
if (task != nullptr) {
task->startTask();
} else {
sif::error << "Task in vector " << name << " is invalid!" << std::endl;
}
}
};
sif::info << "Starting tasks.." << std::endl;
tmtcDistributor->startTask();
tmtcBridgeTask->startTask();
tmtcPollingTask->startTask();
taskStarter(pstTasks, "PST Tasks");
taskStarter(pusTasks, "PUS Tasks");
sif::info << "Tasks started.." << std::endl;
}
void initmission::createPusTasks(TaskFactory& factory,
TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
PeriodicTaskIF* pusVerification = factory.createPeriodicTask(
"PUS_VERIF", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
taskVec.push_back(pusVerification);
PeriodicTaskIF* pusEvents = factory.createPeriodicTask(
"PUS_EVENTS", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
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);
}
taskVec.push_back(pusEvents);
PeriodicTaskIF* pusHighPrio = factory.createPeriodicTask(
"PUS_HIGH_PRIO", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
}
result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS9", objects::PUS_SERVICE_9_TIME_MGMT);
}
taskVec.push_back(pusHighPrio);
PeriodicTaskIF* pusMedPrio = factory.createPeriodicTask(
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS8", objects::PUS_SERVICE_8_FUNCTION_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS200", objects::PUS_SERVICE_200_MODE_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_20_PARAMETERS);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS20", objects::PUS_SERVICE_20_PARAMETERS);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_3_HOUSEKEEPING);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS3", objects::PUS_SERVICE_3_HOUSEKEEPING);
}
taskVec.push_back(pusMedPrio);
PeriodicTaskIF* pusLowPrio = factory.createPeriodicTask(
"PUS_LOW_PRIO", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.6, missedDeadlineFunc);
result = pusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS17", objects::PUS_SERVICE_17_TEST);
}
result = pusLowPrio->addComponent(objects::INTERNAL_ERROR_REPORTER);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("INT_ERR_RPRT", objects::INTERNAL_ERROR_REPORTER);
}
taskVec.push_back(pusLowPrio);
}

View File

@ -1,21 +0,0 @@
#ifndef BSP_LINUX_INITMISSION_H_
#define BSP_LINUX_INITMISSION_H_
#include <vector>
#include "fsfw/tasks/Typedef.h"
class PeriodicTaskIF;
class TaskFactory;
namespace initmission {
void initMission();
void initTasks();
void createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec);
void createPusTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec);
}; // namespace initmission
#endif /* BSP_LINUX_INITMISSION_H_ */

View File

@ -1,49 +0,0 @@
#include "ObjectFactory.h"
#include <devConf.h>
#include <fsfw_hal/linux/uart/UartComIF.h>
#include <fsfw_hal/linux/uart/UartCookie.h>
#include <mission/devices/GPSHyperionHandler.h>
#include "OBSWConfig.h"
#include "busConf.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/tmtcpacket/pus/tm.h"
#include "fsfw/tmtcservices/CommandingServiceBase.h"
#include "fsfw/tmtcservices/PusServiceBase.h"
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
#include "linux/devices/startracker/StarTrackerHandler.h"
#include "mission/core/GenericFactory.h"
#include "mission/utility/TmFunnel.h"
#include "objects/systemObjectList.h"
#include "tmtc/apid.h"
#include "tmtc/pusIds.h"
void Factory::setStaticFrameworkObjectIds() {
PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR;
PusServiceBase::packetDestination = objects::TM_FUNNEL;
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
TmFunnel::storageDestination = objects::NO_OBJECT;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
}
void ObjectFactory::produce(void* args) {
Factory::setStaticFrameworkObjectIds();
ObjectFactory::produceGenericObjects();
UartCookie* starTrackerCookie =
new UartCookie(objects::STAR_TRACKER, egse::STAR_TRACKER_UART, UartModes::NON_CANONICAL,
uart::STAR_TRACKER_BAUD, startracker::MAX_FRAME_SIZE * 2 + 2);
new UartComIF(objects::UART_COM_IF);
starTrackerCookie->setNoFixedSizeReply();
StrHelper* strHelper = new StrHelper(objects::STR_HELPER);
StarTrackerHandler* starTrackerHandler = new StarTrackerHandler(
objects::STAR_TRACKER, objects::UART_COM_IF, starTrackerCookie, strHelper);
starTrackerHandler->setStartUpImmediately();
}

View File

@ -1,8 +0,0 @@
#ifndef BSP_LINUX_OBJECTFACTORY_H_
#define BSP_LINUX_OBJECTFACTORY_H_
namespace ObjectFactory {
void produce(void* args);
}; // namespace ObjectFactory
#endif /* BSP_LINUX_OBJECTFACTORY_H_ */

View File

@ -1,7 +0,0 @@
target_sources(${OBSW_NAME} PRIVATE
print.c
)
target_include_directories(${OBSW_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@ -1,8 +0,0 @@
#ifndef BSP_EGSE_BOARDCONFIG_BUSCONF_H_
#define BSP_EGSE_BOARDCONFIG_BUSCONF_H_
namespace egse {
static constexpr char STAR_TRACKER_UART[] = "/dev/serial0";
}
#endif /* BSP_EGSE_BOARDCONFIG_BUSCONF_H_ */

View File

@ -1,38 +0,0 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2019 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_PROFILE_H__
#define __ETL_PROFILE_H__
#define ETL_CHECK_PUSH_POP
#define ETL_CPP11_SUPPORTED 1
#define ETL_NO_NULLPTR_SUPPORT 0
#endif

View File

@ -1,15 +0,0 @@
#ifndef LINUX_GCOV_H_
#define LINUX_GCOV_H_
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
#ifdef GCOV
extern "C" void __gcov_flush();
#else
void __gcov_flush() {
sif::info << "GCC GCOV: Please supply GCOV=1 in Makefile if "
"coverage information is desired.\n"
<< std::flush;
}
#endif
#endif /* LINUX_GCOV_H_ */

View File

@ -1,10 +0,0 @@
#include <bsp_egse/boardconfig/print.h>
#include <stdio.h>
void printChar(const char* character, bool errStream) {
if (errStream) {
putc(*character, stderr);
return;
}
putc(*character, stdout);
}

View File

@ -1,8 +0,0 @@
#ifndef HOSTED_BOARDCONFIG_PRINT_H_
#define HOSTED_BOARDCONFIG_PRINT_H_
#include <stdbool.h>
void printChar(const char* character, bool errStream);
#endif /* HOSTED_BOARDCONFIG_PRINT_H_ */

View File

@ -1,6 +0,0 @@
#ifndef BSP_RPI_BOARDCONFIG_RPI_CONFIG_H_
#define BSP_RPI_BOARDCONFIG_RPI_CONFIG_H_
#include <cstdint>
#endif /* BSP_RPI_BOARDCONFIG_RPI_CONFIG_H_ */

View File

@ -1,28 +0,0 @@
#include <iostream>
#include "InitMission.h"
#include "OBSWConfig.h"
#include "OBSWVersion.h"
#include "fsfw/FSFWVersion.h"
#include "fsfw/tasks/TaskFactory.h"
/**
* @brief This is the main program entry point for the egse (raspberry pi 4)
* @return
*/
int main(void) {
std::cout << "-- EIVE OBSW --" << std::endl;
std::cout << "-- Compiled for EGSE from Arcsec"
<< " --" << std::endl;
std::cout << "-- OBSW " << SW_NAME << " v" << SW_VERSION << "." << SW_SUBVERSION << "."
<< SW_REVISION << ", FSFW v" << FSFW_VERSION << "." << FSFW_SUBVERSION << FSFW_REVISION
<< "--" << std::endl;
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
initmission::initMission();
for (;;) {
/* Suspend main thread by sleeping it. */
TaskFactory::delayTask(5000);
}
}

View File

@ -1,4 +1,4 @@
target_sources(${OBSW_NAME} PUBLIC
target_sources(${TARGET_NAME} PUBLIC
InitMission.cpp
main.cpp
ObjectFactory.cpp

View File

@ -1,19 +1,20 @@
#include "InitMission.h"
#include "ObjectFactory.h"
#include <OBSWConfig.h>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/objectmanager/ObjectManagerIF.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
#include <fsfw/tasks/PeriodicTaskIF.h>
#include <fsfw/tasks/TaskFactory.h>
#include <mission/utility/InitMission.h>
#include <iostream>
#include "ObjectFactory.h"
#ifdef LINUX
ServiceInterfaceStream sif::debug("DEBUG");
ServiceInterfaceStream sif::info("INFO");
@ -26,132 +27,133 @@ ServiceInterfaceStream sif::warning("WARNING", true);
ServiceInterfaceStream sif::error("ERROR", true, false, true);
#endif
ObjectManagerIF* objectManager = nullptr;
ObjectManagerIF *objectManager = nullptr;
void initmission::initMission() {
sif::info << "Building global objects.." << std::endl;
/* Instantiate global object manager and also create all objects */
ObjectManager::instance()->setObjectFactoryFunction(ObjectFactory::produce, nullptr);
sif::info << "Initializing all objects.." << std::endl;
ObjectManager::instance()->initialize();
sif::info << "Building global objects.." << std::endl;
/* Instantiate global object manager and also create all objects */
ObjectManager::instance()->setObjectFactoryFunction(ObjectFactory::produce, nullptr);
sif::info << "Initializing all objects.." << std::endl;
ObjectManager::instance()->initialize();
/* This function creates and starts all tasks */
initTasks();
/* This function creates and starts all tasks */
initTasks();
}
void initmission::initTasks() {
TaskFactory* factory = TaskFactory::instance();
if (factory == nullptr) {
/* Should never happen ! */
return;
}
TaskFactory* factory = TaskFactory::instance();
if(factory == nullptr) {
/* Should never happen ! */
return;
}
#if OBSW_PRINT_MISSED_DEADLINES == 1
void (*missedDeadlineFunc)(void) = TaskFactory::printMissedDeadline;
void (*missedDeadlineFunc) (void) = TaskFactory::printMissedDeadline;
#else
void (*missedDeadlineFunc)(void) = nullptr;
void (*missedDeadlineFunc) (void) = nullptr;
#endif
/* TMTC Distribution */
PeriodicTaskIF* tmTcDistributor = factory->createPeriodicTask(
"DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
ReturnValue_t result = tmTcDistributor->addComponent(objects::CCSDS_PACKET_DISTRIBUTOR);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
result = tmTcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
result = tmTcDistributor->addComponent(objects::TM_FUNNEL);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
/* TMTC Distribution */
PeriodicTaskIF* tmTcDistributor = factory->createPeriodicTask(
"DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
ReturnValue_t result = tmTcDistributor->addComponent(
objects::CCSDS_PACKET_DISTRIBUTOR);
if(result != HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
result = tmTcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR);
if(result != HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
result = tmTcDistributor->addComponent(objects::TM_FUNNEL);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
/* UDP bridge */
PeriodicTaskIF* tmtcBridgeTask = factory->createPeriodicTask(
"TMTC_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmtcBridgeTask->addComponent(objects::TMTC_BRIDGE);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Unix Bridge failed" << std::endl;
}
PeriodicTaskIF* tmtcPollingTask = factory->createPeriodicTask(
"UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = tmtcPollingTask->addComponent(objects::TMTC_POLLING_TASK);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Polling failed" << std::endl;
}
/* UDP bridge */
PeriodicTaskIF* tmtcBridgeTask = factory->createPeriodicTask(
"TMTC_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmtcBridgeTask->addComponent(objects::TMTC_BRIDGE);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Unix Bridge failed" << std::endl;
}
PeriodicTaskIF* tmtcPollingTask = factory->createPeriodicTask(
"UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = tmtcPollingTask->addComponent(objects::TMTC_POLLING_TASK);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Polling failed" << std::endl;
}
/* PUS Services */
PeriodicTaskIF* pusVerification = factory->createPeriodicTask(
"PUS_VERIF", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
/* PUS Services */
PeriodicTaskIF* pusVerification = factory->createPeriodicTask(
"PUS_VERIF", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
if(result != HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
PeriodicTaskIF* pusEvents = factory->createPeriodicTask(
"PUS_EVENTS", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusVerification->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS5", objects::PUS_SERVICE_5_EVENT_REPORTING);
}
PeriodicTaskIF* pusEvents = factory->createPeriodicTask(
"PUS_EVENTS", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusVerification->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING);
if(result != HasReturnvaluesIF::RETURN_OK){
initmission::printAddObjectError("PUS5", objects::PUS_SERVICE_5_EVENT_REPORTING);
}
PeriodicTaskIF* pusHighPrio = factory->createPeriodicTask(
"PUS_HIGH_PRIO", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
}
result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS9", objects::PUS_SERVICE_9_TIME_MGMT);
}
PeriodicTaskIF* pusHighPrio = factory->createPeriodicTask(
"PUS_HIGH_PRIO", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
}
result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS9", objects::PUS_SERVICE_9_TIME_MGMT);
}
PeriodicTaskIF* pusMedPrio = factory->createPeriodicTask(
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS8", objects::PUS_SERVICE_8_FUNCTION_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS200", objects::PUS_SERVICE_200_MODE_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_20_PARAMETERS);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS20", objects::PUS_SERVICE_20_PARAMETERS);
}
PeriodicTaskIF* pusMedPrio = factory->createPeriodicTask(
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS8", objects::PUS_SERVICE_8_FUNCTION_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS200", objects::PUS_SERVICE_200_MODE_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_20_PARAMETERS);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS20", objects::PUS_SERVICE_20_PARAMETERS);
}
PeriodicTaskIF* pusLowPrio = factory->createPeriodicTask(
"PUS_LOW_PRIO", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.6, missedDeadlineFunc);
result = pusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS17", objects::PUS_SERVICE_17_TEST);
}
PeriodicTaskIF* pusLowPrio = factory->createPeriodicTask(
"PUS_LOW_PRIO", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.6, missedDeadlineFunc);
result = pusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS17", objects::PUS_SERVICE_17_TEST);
}
PeriodicTaskIF* testTask = factory->createPeriodicTask(
"TEST_TASK", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
PeriodicTaskIF* testTask = factory->createPeriodicTask(
"TEST_TASK", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
#if OBSW_ADD_TEST_CODE == 1
result = testTask->addComponent(objects::TEST_TASK);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("TEST_TASK", objects::TEST_TASK);
}
result = testTask->addComponent(objects::TEST_TASK);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("TEST_TASK", objects::TEST_TASK);
}
#endif /* OBSW_ADD_TEST_CODE == 1 */
sif::info << "Starting tasks.." << std::endl;
tmTcDistributor->startTask();
tmtcBridgeTask->startTask();
tmtcPollingTask->startTask();
sif::info << "Starting tasks.." << std::endl;
tmTcDistributor->startTask();
tmtcBridgeTask->startTask();
tmtcPollingTask->startTask();
pusVerification->startTask();
pusEvents->startTask();
pusHighPrio->startTask();
pusMedPrio->startTask();
pusLowPrio->startTask();
pusVerification->startTask();
pusEvents->startTask();
pusHighPrio->startTask();
pusMedPrio->startTask();
pusLowPrio->startTask();
#if OBSW_ADD_TEST_CODE == 1
testTask->startTask();
testTask->startTask();
#endif /* OBSW_ADD_TEST_CODE == 1 */
sif::info << "Tasks started.." << std::endl;
sif::info << "Tasks started.." << std::endl;
}

View File

@ -4,6 +4,6 @@
namespace initmission {
void initMission();
void initTasks();
}; // namespace initmission
};
#endif /* BSP_LINUX_INITMISSION_H_ */

View File

@ -1,14 +1,14 @@
#include "ObjectFactory.h"
#include <fsfw/tmtcservices/CommandingServiceBase.h>
#include <fsfw/tmtcservices/PusServiceBase.h>
#include <mission/core/GenericFactory.h>
#include <mission/utility/TmFunnel.h>
#include "OBSWConfig.h"
#include <objects/systemObjectList.h>
#include <tmtc/apid.h>
#include <tmtc/pusIds.h>
#include "OBSWConfig.h"
#include <fsfw/tmtcservices/CommandingServiceBase.h>
#include <fsfw/tmtcservices/PusServiceBase.h>
#include <mission/core/GenericFactory.h>
#include <mission/utility/TmFunnel.h>
#if OBSW_USE_TMTC_TCP_BRIDGE == 0
#include "fsfw/osal/common/UdpTcPollingTask.h"
@ -20,28 +20,42 @@
#include <fsfw/tmtcpacket/pus/tm.h>
#if OBSW_ADD_TEST_CODE == 1
#include <test/testtasks/TestTask.h>
#endif
void Factory::setStaticFrameworkObjectIds() {
PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR;
PusServiceBase::packetDestination = objects::TM_FUNNEL;
void Factory::setStaticFrameworkObjectIds(){
PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR;
PusServiceBase::packetDestination = objects::TM_FUNNEL;
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
// No storage object for now.
TmFunnel::storageDestination = objects::NO_OBJECT;
TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
// No storage object for now.
TmFunnel::storageDestination = objects::NO_OBJECT;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
}
void ObjectFactory::produce(void* args) {
Factory::setStaticFrameworkObjectIds();
ObjectFactory::produceGenericObjects();
void ObjectFactory::produce(void* args){
Factory::setStaticFrameworkObjectIds();
ObjectFactory::produceGenericObjects();
#if OBSW_USE_TMTC_TCP_BRIDGE == 0
sif::info << "Setting up UDP TMTC bridge with listener port " <<
UdpTmTcBridge::DEFAULT_SERVER_PORT << std::endl;
new UdpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
new UdpTcPollingTask(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE);
#else
sif::info << "Setting up TCP TMTC bridge with listener port " <<
TcpTmTcServer::DEFAULT_SERVER_PORT << std::endl;
new TcpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
new TcpTmTcServer(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE);
#endif
new TestTask(objects::TEST_TASK);
new TestTask(objects::TEST_TASK);
}

View File

@ -1,9 +1,10 @@
#ifndef BSP_LINUX_OBJECTFACTORY_H_
#define BSP_LINUX_OBJECTFACTORY_H_
namespace ObjectFactory {
void setStatics();
void produce(void* args);
}; // namespace ObjectFactory
void setStatics();
void produce(void* args);
};
#endif /* BSP_LINUX_OBJECTFACTORY_H_ */

View File

@ -1,8 +1,8 @@
target_sources(${OBSW_NAME} PRIVATE
target_sources(${TARGET_NAME} PRIVATE
print.c
)
target_include_directories(${OBSW_NAME} PUBLIC
target_include_directories(${TARGET_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@ -32,7 +32,7 @@ SOFTWARE.
#define ETL_CHECK_PUSH_POP
#define ETL_CPP11_SUPPORTED 1
#define ETL_NO_NULLPTR_SUPPORT 0
#define ETL_CPP11_SUPPORTED 1
#define ETL_NO_NULLPTR_SUPPORT 0
#endif

View File

@ -6,9 +6,8 @@
extern "C" void __gcov_flush();
#else
void __gcov_flush() {
sif::info << "GCC GCOV: Please supply GCOV=1 in Makefile if "
"coverage information is desired.\n"
<< std::flush;
sif::info << "GCC GCOV: Please supply GCOV=1 in Makefile if "
"coverage information is desired.\n" << std::flush;
}
#endif

View File

@ -3,9 +3,13 @@
#include <stdio.h>
void printChar(const char* character, bool errStream) {
if (errStream) {
putc(*character, stderr);
return;
}
putc(*character, stdout);
if(errStream) {
putc(*character, stderr);
return;
}
putc(*character, stdout);
}

View File

@ -1,351 +1,376 @@
#include "ArduinoComIF.h"
#include <fsfw/globalfunctions/CRC.h>
#include <fsfw/globalfunctions/DleEncoder.h>
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
#include "ArduinoCookie.h"
#include <fsfw/globalfunctions/DleEncoder.h>
#include <fsfw/globalfunctions/CRC.h>
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
// This only works on Linux
#ifdef LINUX
#include <fcntl.h>
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
#elif WIN32
#include <strsafe.h>
#include <windows.h>
#include <strsafe.h>
#endif
#include <cstring>
ArduinoComIF::ArduinoComIF(object_id_t setObjectId, bool promptComIF, const char *serialDevice)
: rxBuffer(MAX_PACKET_SIZE * MAX_NUMBER_OF_SPI_DEVICES * 10, true), SystemObject(setObjectId) {
ArduinoComIF::ArduinoComIF(object_id_t setObjectId, bool promptComIF,
const char *serialDevice):
rxBuffer(MAX_PACKET_SIZE * MAX_NUMBER_OF_SPI_DEVICES*10, true),
SystemObject(setObjectId) {
#ifdef LINUX
initialized = false;
serialPort = ::open("/dev/ttyUSB0", O_RDWR);
initialized = false;
serialPort = ::open("/dev/ttyUSB0", O_RDWR);
if (serialPort < 0) {
// configuration error
printf("Error %i from open: %s\n", errno, strerror(errno));
return;
}
if (serialPort < 0) {
//configuration error
printf("Error %i from open: %s\n", errno, strerror(errno));
return;
}
struct termios tty;
memset(&tty, 0, sizeof tty);
struct termios tty;
memset(&tty, 0, sizeof tty);
// Read in existing settings, and handle any error
if (tcgetattr(serialPort, &tty) != 0) {
printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
return;
}
// Read in existing settings, and handle any error
if (tcgetattr(serialPort, &tty) != 0) {
printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
return;
}
tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity
tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication
tty.c_cflag |= CS8; // 8 bits per byte
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control
tty.c_lflag &= ~ICANON; // Disable Canonical Mode
tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
tty.c_cc[VTIME] = 0; // Non Blocking
tty.c_cc[VMIN] = 0;
tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity
tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication
tty.c_cflag |= CS8; // 8 bits per byte
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control
tty.c_lflag &= ~ICANON; //Disable Canonical Mode
tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
tty.c_cc[VTIME] = 0; // Non Blocking
tty.c_cc[VMIN] = 0;
cfsetispeed(&tty, B9600); // Baudrate
cfsetispeed(&tty, B9600); //Baudrate
if (tcsetattr(serialPort, TCSANOW, &tty) != 0) {
// printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
return;
}
if (tcsetattr(serialPort, TCSANOW, &tty) != 0) {
//printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
return;
}
initialized = true;
initialized = true;
#elif WIN32
DCB serialParams = {0};
DCB serialParams = { 0 };
// we need to ask the COM port from the user.
if (promptComIF) {
sif::info << "Please enter the COM port (c to cancel): " << std::flush;
std::string comPort;
while (hCom == INVALID_HANDLE_VALUE) {
std::getline(std::cin, comPort);
if (comPort[0] == 'c') {
break;
}
const TCHAR *pcCommPort = comPort.c_str();
hCom = CreateFileA(pcCommPort, // port name
GENERIC_READ | GENERIC_WRITE, // Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
// we need to ask the COM port from the user.
if(promptComIF) {
sif::info << "Please enter the COM port (c to cancel): " << std::flush;
std::string comPort;
while(hCom == INVALID_HANDLE_VALUE) {
if (hCom == INVALID_HANDLE_VALUE) {
if (GetLastError() == 2) {
sif::error << "COM Port does not found!" << std::endl;
} else {
TCHAR err[128];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err, sizeof(err), NULL);
// Handle the error.
sif::info << "CreateFileA Error code: " << GetLastError() << std::endl;
sif::error << err << std::flush;
}
sif::info << "Please enter a valid COM port: " << std::flush;
}
}
}
std::getline(std::cin, comPort);
if(comPort[0] == 'c') {
break;
}
const TCHAR *pcCommPort = comPort.c_str();
hCom = CreateFileA(pcCommPort, //port name
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING,// Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
serialParams.DCBlength = sizeof(serialParams);
if (baudRate == 9600) {
serialParams.BaudRate = CBR_9600;
}
if (baudRate == 115200) {
serialParams.BaudRate = CBR_115200;
} else {
serialParams.BaudRate = baudRate;
}
if (hCom == INVALID_HANDLE_VALUE)
{
if(GetLastError() == 2) {
sif::error << "COM Port does not found!" << std::endl;
}
else {
TCHAR err[128];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
err, sizeof(err), NULL);
// Handle the error.
sif::info << "CreateFileA Error code: " << GetLastError()
<< std::endl;
sif::error << err << std::flush;
}
sif::info << "Please enter a valid COM port: " << std::flush;
}
}
serialParams.ByteSize = 8;
serialParams.Parity = NOPARITY;
serialParams.StopBits = ONESTOPBIT;
SetCommState(hCom, &serialParams);
}
COMMTIMEOUTS timeout = {0};
// This will set the read operation to be blocking until data is received
// and then read continuously until there is a gap of one millisecond.
timeout.ReadIntervalTimeout = 1;
timeout.ReadTotalTimeoutConstant = 0;
timeout.ReadTotalTimeoutMultiplier = 0;
timeout.WriteTotalTimeoutConstant = 0;
timeout.WriteTotalTimeoutMultiplier = 0;
SetCommTimeouts(hCom, &timeout);
// Serial port should now be read for operations.
serialParams.DCBlength = sizeof(serialParams);
if(baudRate == 9600) {
serialParams.BaudRate = CBR_9600;
}
if(baudRate == 115200) {
serialParams.BaudRate = CBR_115200;
}
else {
serialParams.BaudRate = baudRate;
}
serialParams.ByteSize = 8;
serialParams.Parity = NOPARITY;
serialParams.StopBits = ONESTOPBIT;
SetCommState(hCom, &serialParams);
COMMTIMEOUTS timeout = { 0 };
// This will set the read operation to be blocking until data is received
// and then read continuously until there is a gap of one millisecond.
timeout.ReadIntervalTimeout = 1;
timeout.ReadTotalTimeoutConstant = 0;
timeout.ReadTotalTimeoutMultiplier = 0;
timeout.WriteTotalTimeoutConstant = 0;
timeout.WriteTotalTimeoutMultiplier = 0;
SetCommTimeouts(hCom, &timeout);
// Serial port should now be read for operations.
#endif
}
ArduinoComIF::~ArduinoComIF() {
#ifdef LINUX
::close(serialPort);
::close(serialPort);
#elif WIN32
CloseHandle(hCom);
CloseHandle(hCom);
#endif
}
ReturnValue_t ArduinoComIF::initializeInterface(CookieIF *cookie) {
return HasReturnvaluesIF::RETURN_OK;
ReturnValue_t ArduinoComIF::initializeInterface(CookieIF * cookie) {
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t ArduinoComIF::sendMessage(CookieIF *cookie, const uint8_t *data, size_t len) {
ArduinoCookie *arduinoCookie = dynamic_cast<ArduinoCookie *>(cookie);
if (arduinoCookie == nullptr) {
return INVALID_COOKIE_TYPE;
}
ReturnValue_t ArduinoComIF::sendMessage(CookieIF *cookie, const uint8_t *data,
size_t len) {
ArduinoCookie *arduinoCookie = dynamic_cast<ArduinoCookie*>(cookie);
if (arduinoCookie == nullptr) {
return INVALID_COOKIE_TYPE;
}
return sendMessage(arduinoCookie->command, arduinoCookie->address, data, len);
return sendMessage(arduinoCookie->command, arduinoCookie->address, data,
len);
}
ReturnValue_t ArduinoComIF::getSendSuccess(CookieIF *cookie) { return RETURN_OK; }
ReturnValue_t ArduinoComIF::requestReceiveMessage(CookieIF *cookie, size_t requestLen) {
return RETURN_OK;
ReturnValue_t ArduinoComIF::getSendSuccess(CookieIF *cookie) {
return RETURN_OK;
}
ReturnValue_t ArduinoComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) {
handleSerialPortRx();
ArduinoCookie *arduinoCookie = dynamic_cast<ArduinoCookie *>(cookie);
if (arduinoCookie == nullptr) {
return INVALID_COOKIE_TYPE;
}
*buffer = arduinoCookie->replyBuffer.data();
*size = arduinoCookie->receivedDataLen;
return HasReturnvaluesIF::RETURN_OK;
ReturnValue_t ArduinoComIF::requestReceiveMessage(CookieIF *cookie,
size_t requestLen) {
return RETURN_OK;
}
ReturnValue_t ArduinoComIF::sendMessage(uint8_t command, uint8_t address, const uint8_t *data,
size_t dataLen) {
if (dataLen > UINT16_MAX) {
return TOO_MUCH_DATA;
}
ReturnValue_t ArduinoComIF::readReceivedMessage(CookieIF *cookie,
uint8_t **buffer, size_t *size) {
// being conservative here
uint8_t sendBuffer[(dataLen + 6) * 2 + 2];
handleSerialPortRx();
sendBuffer[0] = DleEncoder::STX_CHAR;
ArduinoCookie *arduinoCookie = dynamic_cast<ArduinoCookie*>(cookie);
if (arduinoCookie == nullptr) {
return INVALID_COOKIE_TYPE;
}
uint8_t *currentPosition = sendBuffer + 1;
size_t remainingLen = sizeof(sendBuffer) - 1;
size_t encodedLen = 0;
*buffer = arduinoCookie->replyBuffer.data();
*size = arduinoCookie->receivedDataLen;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t result =
DleEncoder::encode(&command, 1, currentPosition, remainingLen, &encodedLen, false);
if (result != RETURN_OK) {
return result;
}
currentPosition += encodedLen;
remainingLen -= encodedLen; // DleEncoder will never return encodedLen > remainingLen
ReturnValue_t ArduinoComIF::sendMessage(uint8_t command,
uint8_t address, const uint8_t *data, size_t dataLen) {
if (dataLen > UINT16_MAX) {
return TOO_MUCH_DATA;
}
result = DleEncoder::encode(&address, 1, currentPosition, remainingLen, &encodedLen, false);
if (result != RETURN_OK) {
return result;
}
currentPosition += encodedLen;
remainingLen -= encodedLen; // DleEncoder will never return encodedLen > remainingLen
//being conservative here
uint8_t sendBuffer[(dataLen + 6) * 2 + 2];
uint8_t temporaryBuffer[2];
sendBuffer[0] = DleEncoder::STX_CHAR;
// note to Lukas: yes we _could_ use Serialize here, but for 16 bit it is a bit too much...
temporaryBuffer[0] = dataLen >> 8; // we checked dataLen above
temporaryBuffer[1] = dataLen;
uint8_t *currentPosition = sendBuffer + 1;
size_t remainingLen = sizeof(sendBuffer) - 1;
size_t encodedLen = 0;
result =
DleEncoder::encode(temporaryBuffer, 2, currentPosition, remainingLen, &encodedLen, false);
if (result != RETURN_OK) {
return result;
}
currentPosition += encodedLen;
remainingLen -= encodedLen; // DleEncoder will never return encodedLen > remainingLen
ReturnValue_t result = DleEncoder::encode(&command, 1, currentPosition,
remainingLen, &encodedLen, false);
if (result != RETURN_OK) {
return result;
}
currentPosition += encodedLen;
remainingLen -= encodedLen; //DleEncoder will never return encodedLen > remainingLen
// encoding the actual data
result = DleEncoder::encode(data, dataLen, currentPosition, remainingLen, &encodedLen, false);
if (result != RETURN_OK) {
return result;
}
currentPosition += encodedLen;
remainingLen -= encodedLen; // DleEncoder will never return encodedLen > remainingLen
result = DleEncoder::encode(&address, 1, currentPosition, remainingLen,
&encodedLen, false);
if (result != RETURN_OK) {
return result;
}
currentPosition += encodedLen;
remainingLen -= encodedLen; //DleEncoder will never return encodedLen > remainingLen
uint16_t crc = CRC::crc16ccitt(&command, 1);
crc = CRC::crc16ccitt(&address, 1, crc);
// fortunately the length is still there
crc = CRC::crc16ccitt(temporaryBuffer, 2, crc);
crc = CRC::crc16ccitt(data, dataLen, crc);
uint8_t temporaryBuffer[2];
temporaryBuffer[0] = crc >> 8;
temporaryBuffer[1] = crc;
//note to Lukas: yes we _could_ use Serialize here, but for 16 bit it is a bit too much...
temporaryBuffer[0] = dataLen >> 8; //we checked dataLen above
temporaryBuffer[1] = dataLen;
result =
DleEncoder::encode(temporaryBuffer, 2, currentPosition, remainingLen, &encodedLen, false);
if (result != RETURN_OK) {
return result;
}
currentPosition += encodedLen;
remainingLen -= encodedLen; // DleEncoder will never return encodedLen > remainingLen
result = DleEncoder::encode(temporaryBuffer, 2, currentPosition,
remainingLen, &encodedLen, false);
if (result != RETURN_OK) {
return result;
}
currentPosition += encodedLen;
remainingLen -= encodedLen; //DleEncoder will never return encodedLen > remainingLen
if (remainingLen > 0) {
*currentPosition = DleEncoder::ETX_CHAR;
}
remainingLen -= 1;
//encoding the actual data
result = DleEncoder::encode(data, dataLen, currentPosition, remainingLen,
&encodedLen, false);
if (result != RETURN_OK) {
return result;
}
currentPosition += encodedLen;
remainingLen -= encodedLen; //DleEncoder will never return encodedLen > remainingLen
encodedLen = sizeof(sendBuffer) - remainingLen;
uint16_t crc = CRC::crc16ccitt(&command, 1);
crc = CRC::crc16ccitt(&address, 1, crc);
//fortunately the length is still there
crc = CRC::crc16ccitt(temporaryBuffer, 2, crc);
crc = CRC::crc16ccitt(data, dataLen, crc);
temporaryBuffer[0] = crc >> 8;
temporaryBuffer[1] = crc;
result = DleEncoder::encode(temporaryBuffer, 2, currentPosition,
remainingLen, &encodedLen, false);
if (result != RETURN_OK) {
return result;
}
currentPosition += encodedLen;
remainingLen -= encodedLen; //DleEncoder will never return encodedLen > remainingLen
if (remainingLen > 0) {
*currentPosition = DleEncoder::ETX_CHAR;
}
remainingLen -= 1;
encodedLen = sizeof(sendBuffer) - remainingLen;
#ifdef LINUX
ssize_t writtenlen = ::write(serialPort, sendBuffer, encodedLen);
if (writtenlen < 0) {
// we could try to find out what happened...
return RETURN_FAILED;
}
if (writtenlen != encodedLen) {
// the OS failed us, we do not try to block until everything is written, as
// we can not block the whole system here
return RETURN_FAILED;
}
return RETURN_OK;
ssize_t writtenlen = ::write(serialPort, sendBuffer, encodedLen);
if (writtenlen < 0) {
//we could try to find out what happened...
return RETURN_FAILED;
}
if (writtenlen != encodedLen) {
//the OS failed us, we do not try to block until everything is written, as
//we can not block the whole system here
return RETURN_FAILED;
}
return RETURN_OK;
#elif WIN32
return HasReturnvaluesIF::RETURN_OK;
return HasReturnvaluesIF::RETURN_OK;
#endif
}
void ArduinoComIF::handleSerialPortRx() {
#ifdef LINUX
uint32_t availableSpace = rxBuffer.availableWriteSpace();
uint32_t availableSpace = rxBuffer.availableWriteSpace();
uint8_t dataFromSerial[availableSpace];
uint8_t dataFromSerial[availableSpace];
ssize_t bytesRead = read(serialPort, dataFromSerial, sizeof(dataFromSerial));
ssize_t bytesRead = read(serialPort, dataFromSerial,
sizeof(dataFromSerial));
if (bytesRead < 0) {
return;
}
if (bytesRead < 0) {
return;
}
rxBuffer.writeData(dataFromSerial, bytesRead);
rxBuffer.writeData(dataFromSerial, bytesRead);
uint8_t dataReceivedSoFar[rxBuffer.getMaxSize()];
uint8_t dataReceivedSoFar[rxBuffer.getMaxSize()];
uint32_t dataLenReceivedSoFar = 0;
uint32_t dataLenReceivedSoFar = 0;
rxBuffer.readData(dataReceivedSoFar, sizeof(dataReceivedSoFar), true, &dataLenReceivedSoFar);
rxBuffer.readData(dataReceivedSoFar, sizeof(dataReceivedSoFar), true,
&dataLenReceivedSoFar);
// look for STX
size_t firstSTXinRawData = 0;
while ((firstSTXinRawData < dataLenReceivedSoFar) &&
(dataReceivedSoFar[firstSTXinRawData] != DleEncoder::STX_CHAR)) {
firstSTXinRawData++;
}
//look for STX
size_t firstSTXinRawData = 0;
while ((firstSTXinRawData < dataLenReceivedSoFar)
&& (dataReceivedSoFar[firstSTXinRawData] != DleEncoder::STX_CHAR)) {
firstSTXinRawData++;
}
if (dataReceivedSoFar[firstSTXinRawData] != DleEncoder::STX_CHAR) {
// there is no STX in our data, throw it away...
rxBuffer.deleteData(dataLenReceivedSoFar);
return;
}
if (dataReceivedSoFar[firstSTXinRawData] != DleEncoder::STX_CHAR) {
//there is no STX in our data, throw it away...
rxBuffer.deleteData(dataLenReceivedSoFar);
return;
}
uint8_t packet[MAX_PACKET_SIZE];
size_t packetLen = 0;
uint8_t packet[MAX_PACKET_SIZE];
size_t packetLen = 0;
size_t readSize = 0;
size_t readSize = 0;
ReturnValue_t result = DleEncoder::decode(dataReceivedSoFar + firstSTXinRawData,
dataLenReceivedSoFar - firstSTXinRawData, &readSize,
packet, sizeof(packet), &packetLen);
ReturnValue_t result = DleEncoder::decode(
dataReceivedSoFar + firstSTXinRawData,
dataLenReceivedSoFar - firstSTXinRawData, &readSize, packet,
sizeof(packet), &packetLen);
size_t toDelete = firstSTXinRawData;
if (result == HasReturnvaluesIF::RETURN_OK) {
handlePacket(packet, packetLen);
size_t toDelete = firstSTXinRawData;
if (result == HasReturnvaluesIF::RETURN_OK) {
handlePacket(packet, packetLen);
// after handling the packet, we can delete it from the raw stream,
// it has been copied to packet
toDelete += readSize;
}
// after handling the packet, we can delete it from the raw stream,
// it has been copied to packet
toDelete += readSize;
}
// remove Data which was processed
rxBuffer.deleteData(toDelete);
//remove Data which was processed
rxBuffer.deleteData(toDelete);
#elif WIN32
#endif
}
void ArduinoComIF::setBaudrate(uint32_t baudRate) { this->baudRate = baudRate; }
void ArduinoComIF::setBaudrate(uint32_t baudRate) {
this->baudRate = baudRate;
}
void ArduinoComIF::handlePacket(uint8_t *packet, size_t packetLen) {
uint16_t crc = CRC::crc16ccitt(packet, packetLen);
if (crc != 0) {
// CRC error
return;
}
uint16_t crc = CRC::crc16ccitt(packet, packetLen);
if (crc != 0) {
//CRC error
return;
}
uint8_t command = packet[0];
uint8_t address = packet[1];
uint8_t command = packet[0];
uint8_t address = packet[1];
uint16_t size = (packet[2] << 8) + packet[3];
uint16_t size = (packet[2] << 8) + packet[3];
if (size != packetLen - 6) {
// Invalid Length
return;
}
if (size != packetLen - 6) {
//Invalid Length
return;
}
switch (command) {
case ArduinoCookie::SPI: {
// ArduinoCookie **itsComplicated;
auto findIter = spiMap.find(address);
if (findIter == spiMap.end()) {
// we do no know this address
return;
}
ArduinoCookie &cookie = findIter->second;
if (packetLen > cookie.maxReplySize + 6) {
packetLen = cookie.maxReplySize + 6;
}
std::memcpy(cookie.replyBuffer.data(), packet + 4, packetLen - 6);
cookie.receivedDataLen = packetLen - 6;
} break;
default:
return;
}
switch (command) {
case ArduinoCookie::SPI: {
//ArduinoCookie **itsComplicated;
auto findIter = spiMap.find(address);
if (findIter == spiMap.end()) {
//we do no know this address
return;
}
ArduinoCookie& cookie = findIter->second;
if (packetLen > cookie.maxReplySize + 6) {
packetLen = cookie.maxReplySize + 6;
}
std::memcpy(cookie.replyBuffer.data(), packet + 4, packetLen - 6);
cookie.receivedDataLen = packetLen - 6;
}
break;
default:
return;
}
}

View File

@ -4,8 +4,8 @@
#include <fsfw/container/FixedMap.h>
#include <fsfw/container/SimpleRingBuffer.h>
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <cstdint>
#include <map>
@ -14,53 +14,56 @@
#include <windows.h>
#endif
// Forward declaration, so users don't peek
//Forward declaration, so users don't peek
class ArduinoCookie;
class ArduinoComIF : public SystemObject, public DeviceCommunicationIF {
public:
static const uint8_t MAX_NUMBER_OF_SPI_DEVICES = 8;
static const uint8_t MAX_PACKET_SIZE = 64;
class ArduinoComIF: public SystemObject,
public DeviceCommunicationIF {
public:
static const uint8_t MAX_NUMBER_OF_SPI_DEVICES = 8;
static const uint8_t MAX_PACKET_SIZE = 64;
static const uint8_t COMMAND_INVALID = -1;
static const uint8_t COMMAND_SPI = 1;
static const uint8_t COMMAND_INVALID = -1;
static const uint8_t COMMAND_SPI = 1;
ArduinoComIF(object_id_t setObjectId, bool promptComIF = false,
const char *serialDevice = nullptr);
void setBaudrate(uint32_t baudRate);
ArduinoComIF(object_id_t setObjectId, bool promptComIF = false,
const char *serialDevice = nullptr);
void setBaudrate(uint32_t baudRate);
virtual ~ArduinoComIF();
virtual ~ArduinoComIF();
/** DeviceCommunicationIF overrides */
virtual ReturnValue_t initializeInterface(CookieIF *cookie) override;
virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t *sendData,
size_t sendLen) override;
virtual ReturnValue_t getSendSuccess(CookieIF *cookie) override;
virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) override;
virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer,
size_t *size) override;
/** DeviceCommunicationIF overrides */
virtual ReturnValue_t initializeInterface(CookieIF * cookie) override;
virtual ReturnValue_t sendMessage(CookieIF *cookie,
const uint8_t * sendData, size_t sendLen) override;
virtual ReturnValue_t getSendSuccess(CookieIF *cookie) override;
virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie,
size_t requestLen) override;
virtual ReturnValue_t readReceivedMessage(CookieIF *cookie,
uint8_t **buffer, size_t *size) override;
private:
private:
#ifdef LINUX
#elif WIN32
HANDLE hCom = INVALID_HANDLE_VALUE;
HANDLE hCom = INVALID_HANDLE_VALUE;
#endif
// remembering if the initialization in the ctor worked
// if not, all calls are disabled
bool initialized = false;
int serialPort = 0;
// Default baud rate is 9600 for now.
uint32_t baudRate = 9600;
// remembering if the initialization in the ctor worked
// if not, all calls are disabled
bool initialized = false;
int serialPort = 0;
// Default baud rate is 9600 for now.
uint32_t baudRate = 9600;
// used to know where to put the data if a reply is received
std::map<uint8_t, ArduinoCookie> spiMap;
//used to know where to put the data if a reply is received
std::map<uint8_t, ArduinoCookie> spiMap;
SimpleRingBuffer rxBuffer;
SimpleRingBuffer rxBuffer;
ReturnValue_t sendMessage(uint8_t command, uint8_t address, const uint8_t *data, size_t dataLen);
void handleSerialPortRx();
ReturnValue_t sendMessage(uint8_t command, uint8_t address,
const uint8_t *data, size_t dataLen);
void handleSerialPortRx();
void handlePacket(uint8_t *packet, size_t packetLen);
void handlePacket(uint8_t *packet, size_t packetLen);
};
#endif /* MISSION_ARDUINOCOMMINTERFACE_H_ */

View File

@ -1,8 +1,8 @@
#include <bsp_hosted/comIF/ArduinoCookie.h>
ArduinoCookie::ArduinoCookie(Protocol_t protocol, uint8_t address, const size_t maxReplySize)
: protocol(protocol),
command(protocol),
address(address),
maxReplySize(maxReplySize),
replyBuffer(maxReplySize) {}
ArduinoCookie::ArduinoCookie(Protocol_t protocol, uint8_t address,
const size_t maxReplySize) :
protocol(protocol), command(protocol), address(address),
maxReplySize(maxReplySize), replyBuffer(maxReplySize) {
}

View File

@ -2,21 +2,26 @@
#define MISSION_ARDUINO_ARDUINOCOOKIE_H_
#include <fsfw/devicehandlers/CookieIF.h>
#include <vector>
class ArduinoCookie : public CookieIF {
public:
enum Protocol_t : uint8_t { INVALID, SPI, I2C };
class ArduinoCookie: public CookieIF {
public:
enum Protocol_t: uint8_t {
INVALID,
SPI,
I2C
};
ArduinoCookie(Protocol_t protocol, uint8_t address, const size_t maxReplySize);
ArduinoCookie(Protocol_t protocol, uint8_t address,
const size_t maxReplySize);
Protocol_t protocol;
uint8_t command;
uint8_t address;
std::vector<uint8_t> replyBuffer;
size_t receivedDataLen = 0;
size_t maxReplySize;
Protocol_t protocol;
uint8_t command;
uint8_t address;
std::vector<uint8_t> replyBuffer;
size_t receivedDataLen = 0;
size_t maxReplySize;
};
#endif /* MISSION_ARDUINO_ARDUINOCOOKIE_H_ */

View File

@ -1,27 +1,21 @@
target_sources(${OBSW_NAME} PRIVATE
target_sources(${TARGET_NAME} PRIVATE
ipc/MissionMessageTypes.cpp
)
target_include_directories(${OBSW_NAME} PUBLIC
target_include_directories(${TARGET_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
# If a special translation file for object IDs exists, compile it.
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp")
target_sources(${OBSW_NAME} PRIVATE
objects/translateObjects.cpp
)
target_sources(${UNITTEST_NAME} PRIVATE
target_sources(${TARGET_NAME} PRIVATE
objects/translateObjects.cpp
)
endif()
# If a special translation file for events exists, compile it.
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp")
target_sources(${OBSW_NAME} PRIVATE
events/translateEvents.cpp
)
target_sources(${UNITTEST_NAME} PRIVATE
target_sources(${TARGET_NAME} PRIVATE
events/translateEvents.cpp
)
endif()

View File

@ -14,12 +14,6 @@
debugging. */
#define OBSW_VEBOSE_LEVEL 1
#define OBSW_USE_CCSDS_IP_CORE 0
// Set to 1 if all telemetry should be sent to the PTME IP Core
#define OBSW_TM_TO_PTME 0
// Set to 1 if telecommands are received via the PDEC IP Core
#define OBSW_TC_FROM_PDEC 0
#ifdef __cplusplus
#include "objects/systemObjectList.h"

View File

@ -1,57 +1,59 @@
#ifndef FSFWCONFIG_DEVICES_GPIOIDS_H_
#define FSFWCONFIG_DEVICES_GPIOIDS_H_
#include <linux/gpio/GpioIF.h>
namespace gpioIds {
enum gpioId_t {
HEATER_0,
HEATER_1,
HEATER_2,
HEATER_3,
HEATER_4,
HEATER_5,
HEATER_6,
HEATER_7,
DEPLSA1,
DEPLSA2,
enum gpioId_t {
HEATER_0,
HEATER_1,
HEATER_2,
HEATER_3,
HEATER_4,
HEATER_5,
HEATER_6,
HEATER_7,
DEPLSA1,
DEPLSA2,
MGM_0_LIS3_CS,
MGM_1_RM3100_CS,
GYRO_0_ADIS_CS,
GYRO_1_L3G_CS,
GYRO_2_L3G_CS,
MGM_2_LIS3_CS,
MGM_3_RM3100_CS,
MGM_0_LIS3_CS,
MGM_1_RM3100_CS,
GYRO_0_ADIS_CS,
GYRO_1_L3G_CS,
GYRO_2_L3G_CS,
MGM_2_LIS3_CS,
MGM_3_RM3100_CS,
TEST_ID_0,
TEST_ID_1,
TEST_ID_0,
TEST_ID_1,
RTD_IC_3,
RTD_IC_4,
RTD_IC_5,
RTD_IC_6,
RTD_IC_7,
RTD_IC_8,
RTD_IC_9,
RTD_IC_10,
RTD_IC_11,
RTD_IC_12,
RTD_IC_13,
RTD_IC_14,
RTD_IC_15,
RTD_IC_16,
RTD_IC_17,
RTD_IC_18,
RTD_IC3,
RTD_IC4,
RTD_IC5,
RTD_IC6,
RTD_IC7,
RTD_IC8,
RTD_IC9,
RTD_IC10,
RTD_IC11,
RTD_IC12,
RTD_IC13,
RTD_IC14,
RTD_IC15,
RTD_IC16,
RTD_IC17,
RTD_IC18,
SPI_MUX_BIT_1,
SPI_MUX_BIT_2,
SPI_MUX_BIT_3,
SPI_MUX_BIT_4,
SPI_MUX_BIT_5,
SPI_MUX_BIT_6,
CS_RAD_SENSOR,
ENABLE_RADFET
};
SPI_MUX_BIT_1,
SPI_MUX_BIT_2,
SPI_MUX_BIT_3,
SPI_MUX_BIT_4,
SPI_MUX_BIT_5,
SPI_MUX_BIT_6
};
}
#endif /* FSFWCONFIG_DEVICES_GPIOIDS_H_ */

View File

@ -4,54 +4,55 @@
#include <OBSWConfig.h>
namespace pcduSwitches {
/* Switches are uint8_t datatype and go from 0 to 255 */
enum SwitcherList {
Q7S,
PAYLOAD_PCDU_CH1,
RW,
TCS_BOARD_8V_HEATER_IN,
SUS_REDUNDANT,
DEPLOYMENT_MECHANISM,
PAYLOAD_PCDU_CH6,
ACS_BOARD_SIDE_B,
PAYLOAD_CAMERA,
TCS_BOARD_3V3,
SYRLINKS,
STAR_TRACKER,
MGT,
SUS_NOMINAL,
SOLAR_CELL_EXP,
PLOC,
ACS_BOARD_SIDE_A,
NUMBER_OF_SWITCHES
};
/* Switches are uint8_t datatype and go from 0 to 255 */
enum SwitcherList {
Q7S,
PAYLOAD_PCDU_CH1,
RW,
TCS_BOARD_8V_HEATER_IN,
SUS_REDUNDANT,
DEPLOYMENT_MECHANISM,
PAYLOAD_PCDU_CH6,
ACS_BOARD_SIDE_B,
PAYLOAD_CAMERA,
TCS_BOARD_3V3,
SYRLINKS,
STAR_TRACKER,
MGT,
SUS_NOMINAL,
SOLAR_CELL_EXP,
PLOC,
ACS_BOARD_SIDE_A,
NUMBER_OF_SWITCHES
};
static const uint8_t ON = 1;
static const uint8_t OFF = 0;
static const uint8_t ON = 1;
static const uint8_t OFF = 0;
/* Output states after reboot of the PDUs */
static const uint8_t INIT_STATE_Q7S = ON;
static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH1 = OFF;
static const uint8_t INIT_STATE_RW = OFF;
/* Output states after reboot of the PDUs */
static const uint8_t INIT_STATE_Q7S = ON;
static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH1 = OFF;
static const uint8_t INIT_STATE_RW = OFF;
#if BOARD_TE0720 == 1
/* Because the TE0720 is not connected to the PCDU, this switch is always on */
static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = ON;
/* Because the TE0720 is not connected to the PCDU, this switch is always on */
static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = ON;
#else
static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = OFF;
static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = OFF;
#endif
static const uint8_t INIT_STATE_SUS_REDUNDANT = OFF;
static const uint8_t INIT_STATE_DEPLOYMENT_MECHANISM = OFF;
static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH6 = OFF;
static const uint8_t INIT_STATE_ACS_BOARD_SIDE_B = OFF;
static const uint8_t INIT_STATE_PAYLOAD_CAMERA = OFF;
static const uint8_t INIT_STATE_TCS_BOARD_3V3 = OFF;
static const uint8_t INIT_STATE_SYRLINKS = OFF;
static const uint8_t INIT_STATE_STAR_TRACKER = OFF;
static const uint8_t INIT_STATE_MGT = OFF;
static const uint8_t INIT_STATE_SUS_NOMINAL = OFF;
static const uint8_t INIT_STATE_SOLAR_CELL_EXP = OFF;
static const uint8_t INIT_STATE_PLOC = OFF;
static const uint8_t INIT_STATE_ACS_BOARD_SIDE_A = OFF;
} // namespace pcduSwitches
static const uint8_t INIT_STATE_SUS_REDUNDANT = OFF;
static const uint8_t INIT_STATE_DEPLOYMENT_MECHANISM = OFF;
static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH6 = OFF;
static const uint8_t INIT_STATE_ACS_BOARD_SIDE_B = OFF;
static const uint8_t INIT_STATE_PAYLOAD_CAMERA = OFF;
static const uint8_t INIT_STATE_TCS_BOARD_3V3 = OFF;
static const uint8_t INIT_STATE_SYRLINKS = OFF;
static const uint8_t INIT_STATE_STAR_TRACKER = OFF;
static const uint8_t INIT_STATE_MGT = OFF;
static const uint8_t INIT_STATE_SUS_NOMINAL = OFF;
static const uint8_t INIT_STATE_SOLAR_CELL_EXP = OFF;
static const uint8_t INIT_STATE_PLOC = OFF;
static const uint8_t INIT_STATE_ACS_BOARD_SIDE_A = OFF;
}
#endif /* FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ */

View File

@ -2,7 +2,6 @@
#define CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_
#include <common/config/commonSubsystemIds.h>
#include <cstdint>
/**
@ -10,7 +9,9 @@
* Numbers 0-80 are reserved for FSFW Subsystem IDs (framework/events/)
*/
namespace SUBSYSTEM_ID {
enum : uint8_t { SUBSYSTEM_ID_START = COMMON_SUBSYSTEM_ID_END };
enum: uint8_t {
SUBSYSTEM_ID_START = COMMON_SUBSYSTEM_ID_END
};
}
#endif /* CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_ */

View File

@ -89,176 +89,176 @@ 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 *translateEvents(Event event) {
switch ((event & 0xffff)) {
case (2200):
return STORE_SEND_WRITE_FAILED_STRING;
case (2201):
return STORE_WRITE_FAILED_STRING;
case (2202):
return STORE_SEND_READ_FAILED_STRING;
case (2203):
return STORE_READ_FAILED_STRING;
case (2204):
return UNEXPECTED_MSG_STRING;
case (2205):
return STORING_FAILED_STRING;
case (2206):
return TM_DUMP_FAILED_STRING;
case (2207):
return STORE_INIT_FAILED_STRING;
case (2208):
return STORE_INIT_EMPTY_STRING;
case (2209):
return STORE_CONTENT_CORRUPTED_STRING;
case (2210):
return STORE_INITIALIZE_STRING;
case (2211):
return INIT_DONE_STRING;
case (2212):
return DUMP_FINISHED_STRING;
case (2213):
return DELETION_FINISHED_STRING;
case (2214):
return DELETION_FAILED_STRING;
case (2215):
return AUTO_CATALOGS_SENDING_FAILED_STRING;
case (2600):
return GET_DATA_FAILED_STRING;
case (2601):
return STORE_DATA_FAILED_STRING;
case (2800):
return DEVICE_BUILDING_COMMAND_FAILED_STRING;
case (2801):
return DEVICE_SENDING_COMMAND_FAILED_STRING;
case (2802):
return DEVICE_REQUESTING_REPLY_FAILED_STRING;
case (2803):
return DEVICE_READING_REPLY_FAILED_STRING;
case (2804):
return DEVICE_INTERPRETING_REPLY_FAILED_STRING;
case (2805):
return DEVICE_MISSED_REPLY_STRING;
case (2806):
return DEVICE_UNKNOWN_REPLY_STRING;
case (2807):
return DEVICE_UNREQUESTED_REPLY_STRING;
case (2808):
return INVALID_DEVICE_COMMAND_STRING;
case (2809):
return MONITORING_LIMIT_EXCEEDED_STRING;
case (2810):
return MONITORING_AMBIGUOUS_STRING;
case (4201):
return FUSE_CURRENT_HIGH_STRING;
case (4202):
return FUSE_WENT_OFF_STRING;
case (4204):
return POWER_ABOVE_HIGH_LIMIT_STRING;
case (4205):
return POWER_BELOW_LOW_LIMIT_STRING;
case (4300):
return SWITCH_WENT_OFF_STRING;
case (5000):
return HEATER_ON_STRING;
case (5001):
return HEATER_OFF_STRING;
case (5002):
return HEATER_TIMEOUT_STRING;
case (5003):
return HEATER_STAYED_ON_STRING;
case (5004):
return HEATER_STAYED_OFF_STRING;
case (5200):
return TEMP_SENSOR_HIGH_STRING;
case (5201):
return TEMP_SENSOR_LOW_STRING;
case (5202):
return TEMP_SENSOR_GRADIENT_STRING;
case (5901):
return COMPONENT_TEMP_LOW_STRING;
case (5902):
return COMPONENT_TEMP_HIGH_STRING;
case (5903):
return COMPONENT_TEMP_OOL_LOW_STRING;
case (5904):
return COMPONENT_TEMP_OOL_HIGH_STRING;
case (5905):
return TEMP_NOT_IN_OP_RANGE_STRING;
case (7101):
return FDIR_CHANGED_STATE_STRING;
case (7102):
return FDIR_STARTS_RECOVERY_STRING;
case (7103):
return FDIR_TURNS_OFF_DEVICE_STRING;
case (7201):
return MONITOR_CHANGED_STATE_STRING;
case (7202):
return VALUE_BELOW_LOW_LIMIT_STRING;
case (7203):
return VALUE_ABOVE_HIGH_LIMIT_STRING;
case (7204):
return VALUE_OUT_OF_RANGE_STRING;
case (7301):
return SWITCHING_TM_FAILED_STRING;
case (7400):
return CHANGING_MODE_STRING;
case (7401):
return MODE_INFO_STRING;
case (7402):
return FALLBACK_FAILED_STRING;
case (7403):
return MODE_TRANSITION_FAILED_STRING;
case (7404):
return CANT_KEEP_MODE_STRING;
case (7405):
return OBJECT_IN_INVALID_MODE_STRING;
case (7406):
return FORCING_MODE_STRING;
case (7407):
return MODE_CMD_REJECTED_STRING;
case (7506):
return HEALTH_INFO_STRING;
case (7507):
return CHILD_CHANGED_HEALTH_STRING;
case (7508):
return CHILD_PROBLEMS_STRING;
case (7509):
return OVERWRITING_HEALTH_STRING;
case (7510):
return TRYING_RECOVERY_STRING;
case (7511):
return RECOVERY_STEP_STRING;
case (7512):
return RECOVERY_DONE_STRING;
case (7900):
return RF_AVAILABLE_STRING;
case (7901):
return RF_LOST_STRING;
case (7902):
return BIT_LOCK_STRING;
case (7903):
return BIT_LOCK_LOST_STRING;
case (7905):
return FRAME_PROCESSING_FAILED_STRING;
case (8900):
return CLOCK_SET_STRING;
case (8901):
return CLOCK_SET_FAILURE_STRING;
case (9700):
return TEST_STRING;
case (10600):
return CHANGE_OF_SETUP_PARAMETER_STRING;
case (11101):
return MEMORY_READ_RPT_CRC_FAILURE_STRING;
case (11102):
return ACK_FAILURE_STRING;
case (11103):
return EXE_FAILURE_STRING;
case (11104):
return CRC_FAILURE_EVENT_STRING;
default:
return "UNKNOWN_EVENT";
}
return 0;
const char * translateEvents(Event event) {
switch( (event & 0xffff) ) {
case(2200):
return STORE_SEND_WRITE_FAILED_STRING;
case(2201):
return STORE_WRITE_FAILED_STRING;
case(2202):
return STORE_SEND_READ_FAILED_STRING;
case(2203):
return STORE_READ_FAILED_STRING;
case(2204):
return UNEXPECTED_MSG_STRING;
case(2205):
return STORING_FAILED_STRING;
case(2206):
return TM_DUMP_FAILED_STRING;
case(2207):
return STORE_INIT_FAILED_STRING;
case(2208):
return STORE_INIT_EMPTY_STRING;
case(2209):
return STORE_CONTENT_CORRUPTED_STRING;
case(2210):
return STORE_INITIALIZE_STRING;
case(2211):
return INIT_DONE_STRING;
case(2212):
return DUMP_FINISHED_STRING;
case(2213):
return DELETION_FINISHED_STRING;
case(2214):
return DELETION_FAILED_STRING;
case(2215):
return AUTO_CATALOGS_SENDING_FAILED_STRING;
case(2600):
return GET_DATA_FAILED_STRING;
case(2601):
return STORE_DATA_FAILED_STRING;
case(2800):
return DEVICE_BUILDING_COMMAND_FAILED_STRING;
case(2801):
return DEVICE_SENDING_COMMAND_FAILED_STRING;
case(2802):
return DEVICE_REQUESTING_REPLY_FAILED_STRING;
case(2803):
return DEVICE_READING_REPLY_FAILED_STRING;
case(2804):
return DEVICE_INTERPRETING_REPLY_FAILED_STRING;
case(2805):
return DEVICE_MISSED_REPLY_STRING;
case(2806):
return DEVICE_UNKNOWN_REPLY_STRING;
case(2807):
return DEVICE_UNREQUESTED_REPLY_STRING;
case(2808):
return INVALID_DEVICE_COMMAND_STRING;
case(2809):
return MONITORING_LIMIT_EXCEEDED_STRING;
case(2810):
return MONITORING_AMBIGUOUS_STRING;
case(4201):
return FUSE_CURRENT_HIGH_STRING;
case(4202):
return FUSE_WENT_OFF_STRING;
case(4204):
return POWER_ABOVE_HIGH_LIMIT_STRING;
case(4205):
return POWER_BELOW_LOW_LIMIT_STRING;
case(4300):
return SWITCH_WENT_OFF_STRING;
case(5000):
return HEATER_ON_STRING;
case(5001):
return HEATER_OFF_STRING;
case(5002):
return HEATER_TIMEOUT_STRING;
case(5003):
return HEATER_STAYED_ON_STRING;
case(5004):
return HEATER_STAYED_OFF_STRING;
case(5200):
return TEMP_SENSOR_HIGH_STRING;
case(5201):
return TEMP_SENSOR_LOW_STRING;
case(5202):
return TEMP_SENSOR_GRADIENT_STRING;
case(5901):
return COMPONENT_TEMP_LOW_STRING;
case(5902):
return COMPONENT_TEMP_HIGH_STRING;
case(5903):
return COMPONENT_TEMP_OOL_LOW_STRING;
case(5904):
return COMPONENT_TEMP_OOL_HIGH_STRING;
case(5905):
return TEMP_NOT_IN_OP_RANGE_STRING;
case(7101):
return FDIR_CHANGED_STATE_STRING;
case(7102):
return FDIR_STARTS_RECOVERY_STRING;
case(7103):
return FDIR_TURNS_OFF_DEVICE_STRING;
case(7201):
return MONITOR_CHANGED_STATE_STRING;
case(7202):
return VALUE_BELOW_LOW_LIMIT_STRING;
case(7203):
return VALUE_ABOVE_HIGH_LIMIT_STRING;
case(7204):
return VALUE_OUT_OF_RANGE_STRING;
case(7301):
return SWITCHING_TM_FAILED_STRING;
case(7400):
return CHANGING_MODE_STRING;
case(7401):
return MODE_INFO_STRING;
case(7402):
return FALLBACK_FAILED_STRING;
case(7403):
return MODE_TRANSITION_FAILED_STRING;
case(7404):
return CANT_KEEP_MODE_STRING;
case(7405):
return OBJECT_IN_INVALID_MODE_STRING;
case(7406):
return FORCING_MODE_STRING;
case(7407):
return MODE_CMD_REJECTED_STRING;
case(7506):
return HEALTH_INFO_STRING;
case(7507):
return CHILD_CHANGED_HEALTH_STRING;
case(7508):
return CHILD_PROBLEMS_STRING;
case(7509):
return OVERWRITING_HEALTH_STRING;
case(7510):
return TRYING_RECOVERY_STRING;
case(7511):
return RECOVERY_STEP_STRING;
case(7512):
return RECOVERY_DONE_STRING;
case(7900):
return RF_AVAILABLE_STRING;
case(7901):
return RF_LOST_STRING;
case(7902):
return BIT_LOCK_STRING;
case(7903):
return BIT_LOCK_LOST_STRING;
case(7905):
return FRAME_PROCESSING_FAILED_STRING;
case(8900):
return CLOCK_SET_STRING;
case(8901):
return CLOCK_SET_FAILURE_STRING;
case(9700):
return TEST_STRING;
case(10600):
return CHANGE_OF_SETUP_PARAMETER_STRING;
case(11101):
return MEMORY_READ_RPT_CRC_FAILURE_STRING;
case(11102):
return ACK_FAILURE_STRING;
case(11103):
return EXE_FAILURE_STRING;
case(11104):
return CRC_FAILURE_EVENT_STRING;
default:
return "UNKNOWN_EVENT";
}
return 0;
}

View File

@ -3,6 +3,6 @@
#include <fsfw/events/Event.h>
const char* translateEvents(Event event);
const char * translateEvents(Event event);
#endif /* FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_ */

View File

@ -0,0 +1,7 @@
CXXSRC += $(wildcard $(CURRENTPATH)/cdatapool/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/ipc/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/objects/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/pollingsequence/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/events/*.cpp)
INCLUDES += $(CURRENTPATH)

View File

@ -1,10 +1,11 @@
#include "MissionMessageTypes.h"
#include <fsfw/ipc/CommandMessage.h>
void messagetypes::clearMissionMessage(CommandMessage* message) {
switch (message->getMessageType()) {
default:
break;
}
switch(message->getMessageType()) {
default:
break;
}
}

View File

@ -13,10 +13,10 @@ class CommandMessage;
*/
namespace messagetypes {
enum MESSAGE_TYPE {
MISSION_MESSAGE_TYPE_START = FW_MESSAGES_COUNT,
MISSION_MESSAGE_TYPE_START = FW_MESSAGES_COUNT,
};
void clearMissionMessage(CommandMessage* message);
} // namespace messagetypes
}
#endif /* CONFIG_IPC_MISSIONMESSAGETYPES_H_ */

View File

@ -1,32 +1,31 @@
#ifndef HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_
#define HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_
#include <commonObjects.h>
#include <cstdint>
#include <commonObjects.h>
// The objects will be instantiated in the ID order
namespace objects {
enum sourceObjects : uint32_t {
enum sourceObjects: uint32_t {
PUS_SERVICE_3 = 0x51000300,
PUS_SERVICE_5 = 0x51000400,
PUS_SERVICE_6 = 0x51000500,
PUS_SERVICE_8 = 0x51000800,
PUS_SERVICE_23 = 0x51002300,
PUS_SERVICE_201 = 0x51020100,
PUS_SERVICE_3 = 0x51000300,
PUS_SERVICE_5 = 0x51000400,
PUS_SERVICE_6 = 0x51000500,
PUS_SERVICE_8 = 0x51000800,
PUS_SERVICE_23 = 0x51002300,
PUS_SERVICE_201 = 0x51020100,
TM_FUNNEL = 0x52000002,
TM_FUNNEL = 0x52000002,
/* Test Task */
/* Test Task */
TEST_TASK = 0x42694269,
DUMMY_INTERFACE = 0xCAFECAFE,
DUMMY_HANDLER = 0x4400AFFE,
TEST_TASK = 0x42694269,
DUMMY_INTERFACE = 0xCAFECAFE,
DUMMY_HANDLER = 0x4400AFFE,
/* 0x49 ('I') for Communication Interfaces **/
ARDUINO_COM_IF = 0x49000001
};
/* 0x49 ('I') for Communication Interfaces **/
ARDUINO_COM_IF = 0x49000001
};
}
#endif /* BSP_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ */

View File

@ -1,4 +1,4 @@
/**
/**
* @brief Auto-generated object translation file.
* @details
* Contains 31 translations.
@ -38,72 +38,72 @@ const char *FSFW_OBJECTS_END_STRING = "FSFW_OBJECTS_END";
const char *DUMMY_INTERFACE_STRING = "DUMMY_INTERFACE";
const char *NO_OBJECT_STRING = "NO_OBJECT";
const char *translateObject(object_id_t object) {
switch ((object & 0xFFFFFFFF)) {
case 0x42694269:
return TEST_TASK_STRING;
case 0x4400AFFE:
return DUMMY_HANDLER_STRING;
case 0x49000001:
return ARDUINO_COM_IF_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:
return PUS_SERVICE_1_VERIFICATION_STRING;
case 0x53000002:
return PUS_SERVICE_2_DEVICE_ACCESS_STRING;
case 0x53000003:
return PUS_SERVICE_3_HOUSEKEEPING_STRING;
case 0x53000005:
return PUS_SERVICE_5_EVENT_REPORTING_STRING;
case 0x53000008:
return PUS_SERVICE_8_FUNCTION_MGMT_STRING;
case 0x53000009:
return PUS_SERVICE_9_TIME_MGMT_STRING;
case 0x53000017:
return PUS_SERVICE_17_TEST_STRING;
case 0x53000020:
return PUS_SERVICE_20_PARAMETERS_STRING;
case 0x53000200:
return PUS_SERVICE_200_MODE_MGMT_STRING;
case 0x53010000:
return HEALTH_TABLE_STRING;
case 0x53010100:
return MODE_STORE_STRING;
case 0x53030000:
return EVENT_MANAGER_STRING;
case 0x53040000:
return INTERNAL_ERROR_REPORTER_STRING;
case 0x534f0100:
return TC_STORE_STRING;
case 0x534f0200:
return TM_STORE_STRING;
case 0x534f0300:
return IPC_STORE_STRING;
case 0x53500010:
return TIME_STAMPER_STRING;
case 0x53ffffff:
return FSFW_OBJECTS_END_STRING;
case 0xCAFECAFE:
return DUMMY_INTERFACE_STRING;
case 0xFFFFFFFF:
return NO_OBJECT_STRING;
default:
return "UNKNOWN_OBJECT";
}
return 0;
const char* translateObject(object_id_t object) {
switch( (object & 0xFFFFFFFF) ) {
case 0x42694269:
return TEST_TASK_STRING;
case 0x4400AFFE:
return DUMMY_HANDLER_STRING;
case 0x49000001:
return ARDUINO_COM_IF_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:
return PUS_SERVICE_1_VERIFICATION_STRING;
case 0x53000002:
return PUS_SERVICE_2_DEVICE_ACCESS_STRING;
case 0x53000003:
return PUS_SERVICE_3_HOUSEKEEPING_STRING;
case 0x53000005:
return PUS_SERVICE_5_EVENT_REPORTING_STRING;
case 0x53000008:
return PUS_SERVICE_8_FUNCTION_MGMT_STRING;
case 0x53000009:
return PUS_SERVICE_9_TIME_MGMT_STRING;
case 0x53000017:
return PUS_SERVICE_17_TEST_STRING;
case 0x53000020:
return PUS_SERVICE_20_PARAMETERS_STRING;
case 0x53000200:
return PUS_SERVICE_200_MODE_MGMT_STRING;
case 0x53010000:
return HEALTH_TABLE_STRING;
case 0x53010100:
return MODE_STORE_STRING;
case 0x53030000:
return EVENT_MANAGER_STRING;
case 0x53040000:
return INTERNAL_ERROR_REPORTER_STRING;
case 0x534f0100:
return TC_STORE_STRING;
case 0x534f0200:
return TM_STORE_STRING;
case 0x534f0300:
return IPC_STORE_STRING;
case 0x53500010:
return TIME_STAMPER_STRING;
case 0x53ffffff:
return FSFW_OBJECTS_END_STRING;
case 0xCAFECAFE:
return DUMMY_INTERFACE_STRING;
case 0xFFFFFFFF:
return NO_OBJECT_STRING;
default:
return "UNKNOWN_OBJECT";
}
return 0;
}

View File

@ -1,9 +1,8 @@
#ifndef CONFIG_RETURNVALUES_CLASSIDS_H_
#define CONFIG_RETURNVALUES_CLASSIDS_H_
#include <fsfw/returnvalues/FwClassIds.h>
#include "commonClassIds.h"
#include <fsfw/returnvalues/FwClassIds.h>
/**
* Source IDs starts at 73 for now
@ -12,8 +11,9 @@
*/
namespace CLASS_ID {
enum {
CLASS_ID_START = COMMON_CLASS_ID_END,
CLASS_ID_START = COMMON_CLASS_ID_END,
};
}
#endif /* CONFIG_RETURNVALUES_CLASSIDS_H_ */

View File

@ -12,7 +12,8 @@
* APID is a 11 bit number
*/
namespace apid {
static const uint16_t EIVE_OBSW = 0x65;
static const uint16_t EIVE_OBSW = 0x65;
}
#endif /* FSFWCONFIG_TMTC_APID_H_ */

View File

@ -2,21 +2,21 @@
#define CONFIG_TMTC_PUSIDS_HPP_
namespace pus {
enum Ids {
PUS_SERVICE_1 = 1,
PUS_SERVICE_2 = 2,
PUS_SERVICE_3 = 3,
PUS_SERVICE_3_PSB = 3,
PUS_SERVICE_5 = 5,
PUS_SERVICE_6 = 6,
PUS_SERVICE_8 = 8,
PUS_SERVICE_9 = 9,
PUS_SERVICE_17 = 17,
PUS_SERVICE_19 = 19,
PUS_SERVICE_20 = 20,
PUS_SERVICE_23 = 23,
PUS_SERVICE_200 = 200,
PUS_SERVICE_201 = 201,
enum Ids{
PUS_SERVICE_1 = 1,
PUS_SERVICE_2 = 2,
PUS_SERVICE_3 = 3,
PUS_SERVICE_3_PSB = 3,
PUS_SERVICE_5 = 5,
PUS_SERVICE_6 = 6,
PUS_SERVICE_8 = 8,
PUS_SERVICE_9 = 9,
PUS_SERVICE_17 = 17,
PUS_SERVICE_19 = 19,
PUS_SERVICE_20 = 20,
PUS_SERVICE_23 = 23,
PUS_SERVICE_200 = 200,
PUS_SERVICE_201 = 201,
};
};

View File

@ -1,9 +1,10 @@
#include <iostream>
#include "InitMission.h"
#include "OBSWVersion.h"
#include "fsfw/FSFWVersion.h"
#include "fsfw/tasks/TaskFactory.h"
#include <iostream>
#ifdef WIN32
static const char* COMPILE_PRINTOUT = "Windows";
#elif LINUX
@ -16,18 +17,21 @@ static const char* COMPILE_PRINTOUT = "unknown OS";
* Linux and Windows.
* @return
*/
int main(void) {
std::cout << "-- EIVE OBSW --" << std::endl;
std::cout << "-- Compiled for " << COMPILE_PRINTOUT << " --" << std::endl;
std::cout << "-- OBSW " << SW_NAME << " v" << SW_VERSION << "." << SW_SUBVERSION << "."
<< SW_REVISION << ", FSFW v" << FSFW_VERSION << "." << FSFW_SUBVERSION << "."
<< FSFW_REVISION << "--" << std::endl;
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
int main(void)
{
std::cout << "-- EIVE OBSW --" << std::endl;
std::cout << "-- Compiled for " << COMPILE_PRINTOUT << " --" << std::endl;
std::cout << "-- OBSW " << SW_NAME << " v" << SW_VERSION << "." << SW_SUBVERSION <<
"." << SW_REVISION << ", FSFW v" << FSFW_VERSION << "." << FSFW_SUBVERSION << "." <<
FSFW_REVISION << "--" << std::endl;
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
initmission::initMission();
initmission::initMission();
for (;;) {
// suspend main thread by sleeping it.
TaskFactory::delayTask(5000);
}
for(;;) {
// suspend main thread by sleeping it.
TaskFactory::delayTask(5000);
}
}

View File

@ -1,4 +1,4 @@
target_sources(${OBSW_NAME} PUBLIC
target_sources(${TARGET_NAME} PUBLIC
InitMission.cpp
main.cpp
ObjectFactory.cpp

View File

@ -1,245 +1,247 @@
#include "InitMission.h"
#include "ObjectFactory.h"
#include <fsfw/objectmanager/ObjectManager.h>
#include "objects/systemObjectList.h"
#include "OBSWConfig.h"
#include "pollingsequence/pollingSequenceFactory.h"
#include <mission/utility/InitMission.h>
#include <fsfw/objectmanager/ObjectManagerIF.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
#include <fsfw/tasks/PeriodicTaskIF.h>
#include <fsfw/tasks/TaskFactory.h>
#include <mission/utility/InitMission.h>
#include <iostream>
#include "OBSWConfig.h"
#include "ObjectFactory.h"
#include "objects/systemObjectList.h"
#include "pollingsequence/pollingSequenceFactory.h"
ServiceInterfaceStream sif::debug("DEBUG");
ServiceInterfaceStream sif::info("INFO");
ServiceInterfaceStream sif::warning("WARNING");
ServiceInterfaceStream sif::error("ERROR");
ObjectManagerIF* objectManager = nullptr;
ObjectManagerIF *objectManager = nullptr;
void initmission::initMission() {
sif::info << "Building global objects.." << std::endl;
/* Instantiate global object manager and also create all objects */
ObjectManager::instance()->setObjectFactoryFunction(ObjectFactory::produce, nullptr);
sif::info << "Initializing all objects.." << std::endl;
ObjectManager::instance()->initialize();
sif::info << "Building global objects.." << std::endl;
/* Instantiate global object manager and also create all objects */
ObjectManager::instance()->setObjectFactoryFunction(ObjectFactory::produce, nullptr);
sif::info << "Initializing all objects.." << std::endl;
ObjectManager::instance()->initialize();
/* This function creates and starts all tasks */
initTasks();
/* This function creates and starts all tasks */
initTasks();
}
void initmission::initTasks() {
TaskFactory* factory = TaskFactory::instance();
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if (factory == nullptr) {
/* Should never happen ! */
return;
}
TaskFactory* factory = TaskFactory::instance();
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if(factory == nullptr) {
/* Should never happen ! */
return;
}
#if OBSW_PRINT_MISSED_DEADLINES == 1
void (*missedDeadlineFunc)(void) = TaskFactory::printMissedDeadline;
void (*missedDeadlineFunc) (void) = TaskFactory::printMissedDeadline;
#else
void (*missedDeadlineFunc)(void) = nullptr;
void (*missedDeadlineFunc) (void) = nullptr;
#endif
/* TMTC Distribution */
PeriodicTaskIF* tmTcDistributor = factory->createPeriodicTask(
"DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmTcDistributor->addComponent(objects::CCSDS_PACKET_DISTRIBUTOR);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
result = tmTcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
result = tmTcDistributor->addComponent(objects::TM_FUNNEL);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
/* UDP bridge */
PeriodicTaskIF* tmtcBridgeTask = factory->createPeriodicTask(
"TMTC_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmtcBridgeTask->addComponent(objects::TMTC_BRIDGE);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component TMTC Bridge failed" << std::endl;
}
PeriodicTaskIF* tmtcPollingTask = factory->createPeriodicTask(
"TMTC_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = tmtcPollingTask->addComponent(objects::TMTC_POLLING_TASK);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component TMTC Polling failed" << std::endl;
}
/* PUS Services */
std::vector<PeriodicTaskIF*> pusTasks;
createPusTasks(*factory, missedDeadlineFunc, pusTasks);
std::vector<PeriodicTaskIF*> pstTasks;
createPstTasks(*factory, missedDeadlineFunc, pstTasks);
#if OBSW_ADD_TEST_CODE == 1
std::vector<PeriodicTaskIF*> testTasks;
createTestTasks(*factory, missedDeadlineFunc, pstTasks);
#endif /* OBSW_ADD_TEST_CODE == 1 */
auto taskStarter = [](std::vector<PeriodicTaskIF*>& taskVector, std::string name) {
for (const auto& task : taskVector) {
if (task != nullptr) {
task->startTask();
} else {
sif::error << "Task in vector " << name << " is invalid!" << std::endl;
}
/* TMTC Distribution */
PeriodicTaskIF* tmTcDistributor = factory->createPeriodicTask(
"DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmTcDistributor->addComponent(objects::CCSDS_PACKET_DISTRIBUTOR);
if(result != HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
result = tmTcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR);
if(result != HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
result = tmTcDistributor->addComponent(objects::TM_FUNNEL);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
};
sif::info << "Starting tasks.." << std::endl;
tmTcDistributor->startTask();
tmtcBridgeTask->startTask();
tmtcPollingTask->startTask();
/* UDP bridge */
PeriodicTaskIF* udpBridgeTask = factory->createPeriodicTask(
"UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = udpBridgeTask->addComponent(objects::TMTC_BRIDGE);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Unix Bridge failed" << std::endl;
}
PeriodicTaskIF* udpPollingTask = factory->createPeriodicTask(
"UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = udpPollingTask->addComponent(objects::TMTC_POLLING_TASK);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Polling failed" << std::endl;
}
taskStarter(pusTasks, "PUS Tasks");
/* PUS Services */
std::vector<PeriodicTaskIF*> pusTasks;
createPusTasks(*factory, missedDeadlineFunc, pusTasks);
std::vector<PeriodicTaskIF*> pstTasks;
createPstTasks(*factory, missedDeadlineFunc, pstTasks);
#if OBSW_ADD_TEST_CODE == 1
taskStarter(testTasks, "Test Tasks");
std::vector<PeriodicTaskIF*> testTasks;
createTestTasks(*factory, missedDeadlineFunc, pstTasks);
#endif /* OBSW_ADD_TEST_CODE == 1 */
taskStarter(pstTasks, "PST Tasks");
auto taskStarter = [](std::vector<PeriodicTaskIF*>& taskVector, std::string name) {
for(const auto& task: taskVector) {
if(task != nullptr) {
task->startTask();
}
else {
sif::error << "Task in vector " << name << " is invalid!" << std::endl;
}
}
};
sif::info << "Starting tasks.." << std::endl;
tmTcDistributor->startTask();
udpBridgeTask->startTask();
udpPollingTask->startTask();
taskStarter(pusTasks, "PUS Tasks");
#if OBSW_ADD_TEST_CODE == 1
taskStarter(testTasks, "Test Tasks");
#endif /* OBSW_ADD_TEST_CODE == 1 */
taskStarter(pstTasks, "PST Tasks");
#if OBSW_ADD_TEST_PST == 1
if (startTestPst) {
pstTestTask->startTask();
}
if(startTestPst) {
pstTestTask->startTask();
}
#endif /* RPI_TEST_ACS_BOARD == 1 */
sif::info << "Tasks started.." << std::endl;
sif::info << "Tasks started.." << std::endl;
}
void initmission::createPusTasks(TaskFactory& factory,
TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
PeriodicTaskIF* pusVerification = factory.createPeriodicTask(
"PUS_VERIF", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
taskVec.push_back(pusVerification);
TaskDeadlineMissedFunction missedDeadlineFunc, std::vector<PeriodicTaskIF*>& taskVec) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
PeriodicTaskIF* pusVerification = factory.createPeriodicTask(
"PUS_VERIF", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
if(result != HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
taskVec.push_back(pusVerification);
PeriodicTaskIF* pusEvents = factory.createPeriodicTask(
"PUS_EVENTS", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
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);
}
taskVec.push_back(pusEvents);
PeriodicTaskIF* pusEvents = factory.createPeriodicTask(
"PUS_EVENTS", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
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);
}
taskVec.push_back(pusEvents);
PeriodicTaskIF* pusHighPrio = factory.createPeriodicTask(
"PUS_HIGH_PRIO", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
}
result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS9", objects::PUS_SERVICE_9_TIME_MGMT);
}
taskVec.push_back(pusHighPrio);
PeriodicTaskIF* pusHighPrio = factory.createPeriodicTask(
"PUS_HIGH_PRIO", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
}
result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS9", objects::PUS_SERVICE_9_TIME_MGMT);
}
taskVec.push_back(pusHighPrio);
PeriodicTaskIF* pusMedPrio = factory.createPeriodicTask(
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS8", objects::PUS_SERVICE_8_FUNCTION_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS200", objects::PUS_SERVICE_200_MODE_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_20_PARAMETERS);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS20", objects::PUS_SERVICE_20_PARAMETERS);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_3_HOUSEKEEPING);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS3", objects::PUS_SERVICE_3_HOUSEKEEPING);
}
taskVec.push_back(pusMedPrio);
PeriodicTaskIF* pusMedPrio = factory.createPeriodicTask(
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS8", objects::PUS_SERVICE_8_FUNCTION_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS200", objects::PUS_SERVICE_200_MODE_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_20_PARAMETERS);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS20", objects::PUS_SERVICE_20_PARAMETERS);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_3_HOUSEKEEPING);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS3", objects::PUS_SERVICE_3_HOUSEKEEPING);
}
taskVec.push_back(pusMedPrio);
PeriodicTaskIF* pusLowPrio = factory.createPeriodicTask(
"PUS_LOW_PRIO", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.6, missedDeadlineFunc);
result = pusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS17", objects::PUS_SERVICE_17_TEST);
}
result = pusLowPrio->addComponent(objects::INTERNAL_ERROR_REPORTER);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("INT_ERR_RPRT", objects::INTERNAL_ERROR_REPORTER);
}
taskVec.push_back(pusLowPrio);
PeriodicTaskIF* pusLowPrio = factory.createPeriodicTask(
"PUS_LOW_PRIO", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.6, missedDeadlineFunc);
result = pusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS17", objects::PUS_SERVICE_17_TEST);
}
result = pusLowPrio->addComponent(objects::INTERNAL_ERROR_REPORTER);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("INT_ERR_RPRT",
objects::INTERNAL_ERROR_REPORTER);
}
taskVec.push_back(pusLowPrio);
}
void initmission::createPstTasks(TaskFactory& factory,
TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
TaskDeadlineMissedFunction missedDeadlineFunc, std::vector<PeriodicTaskIF*> &taskVec) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
#if OBSW_ADD_SPI_TEST_CODE == 0
FixedTimeslotTaskIF* spiPst = factory.createFixedTimeslotTask(
"SPI_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, missedDeadlineFunc);
result = pst::pstSpi(spiPst);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl;
}
taskVec.push_back(spiPst);
FixedTimeslotTaskIF* spiPst = factory.createFixedTimeslotTask(
"SPI_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0,
missedDeadlineFunc);
result = pst::pstSpi(spiPst);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl;
}
taskVec.push_back(spiPst);
#endif
}
void initmission::createTestTasks(TaskFactory& factory,
TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
PeriodicTaskIF* testTask = factory.createPeriodicTask(
"TEST_TASK", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = testTask->addComponent(objects::TEST_TASK);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("TEST_TASK", objects::TEST_TASK);
}
#if OBSW_ADD_SPI_TEST_CODE == 1
result = testTask->addComponent(objects::SPI_TEST);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("SPI_TEST", objects::SPI_TEST);
}
TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*> &taskVec) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
PeriodicTaskIF* testTask = factory.createPeriodicTask(
"TEST_TASK", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = testTask->addComponent(objects::TEST_TASK);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("TEST_TASK", objects::TEST_TASK);
}
#if RPI_ADD_SPI_TEST == 1
result = testTask->addComponent(objects::SPI_TEST);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("SPI_TEST", objects::SPI_TEST);
}
#endif /* RPI_ADD_SPI_TEST == 1 */
#if RPI_ADD_GPIO_TEST == 1
result = testTask->addComponent(objects::LIBGPIOD_TEST);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("GPIOD_TEST", objects::LIBGPIOD_TEST);
}
result = testTask->addComponent(objects::LIBGPIOD_TEST);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("GPIOD_TEST", objects::LIBGPIOD_TEST);
}
#endif /* RPI_ADD_GPIO_TEST == 1 */
#if OBSW_ADD_UART_TEST_CODE == 1
result = testTask->addComponent(objects::UART_TEST);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("UART_TEST", objects::UART_TEST);
}
#if RPI_ADD_UART_TEST == 1
result = testTask->addComponent(objects::UART_TEST);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("UART_TEST", objects::UART_TEST);
}
#endif /* RPI_ADD_GPIO_TEST == 1 */
taskVec.push_back(testTask);
bool startTestPst = true;
static_cast<void>(startTestPst);
bool startTestPst = true;
static_cast<void>(startTestPst);
#if OBSW_ADD_TEST_PST == 1
FixedTimeslotTaskIF* pstTestTask = factory->createFixedTimeslotTask(
"TEST_PST", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 2.0, missedDeadlineFunc);
result = pst::pstTest(pstTestTask);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::info << "initmission::initTasks: ACS PST empty or invalid" << std::endl;
startTestPst = false;
}
FixedTimeslotTaskIF* pstTestTask = factory->createFixedTimeslotTask("TEST_PST", 50,
PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 2.0, missedDeadlineFunc);
result = pst::pstTest(pstTestTask);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::info << "initmission::initTasks: ACS PST empty or invalid" << std::endl;
startTestPst = false;
}
#endif /* RPI_TEST_ACS_BOARD == 1 */
}

View File

@ -1,9 +1,8 @@
#ifndef BSP_LINUX_INITMISSION_H_
#define BSP_LINUX_INITMISSION_H_
#include <vector>
#include "fsfw/tasks/Typedef.h"
#include <vector>
class PeriodicTaskIF;
class TaskFactory;
@ -12,12 +11,14 @@ namespace initmission {
void initMission();
void initTasks();
void createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec);
void createTestTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec);
void createPstTasks(TaskFactory& factory,
TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*> &taskVec);
void createTestTasks(TaskFactory& factory,
TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*> &taskVec);
void createPusTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec);
}; // namespace initmission
std::vector<PeriodicTaskIF*>& taskVec);
};
#endif /* BSP_LINUX_INITMISSION_H_ */

View File

@ -1,230 +1,236 @@
#include <devConf.h>
#include "ObjectFactory.h"
#include "OBSWConfig.h"
#include "devConf.h"
#include "objects/systemObjectList.h"
#include "devices/addresses.h"
#include "devices/gpioIds.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/tasks/TaskFactory.h"
#include "fsfw/tmtcpacket/pus/tm.h"
#include "fsfw/tmtcservices/CommandingServiceBase.h"
#include "fsfw/tmtcservices/PusServiceBase.h"
#include "OBSWConfig.h"
#include "tmtc/apid.h"
#include "tmtc/pusIds.h"
#include "linux/boardtest/LibgpiodTest.h"
#include "linux/boardtest/SpiTestClass.h"
#include "linux/boardtest/UartTestClass.h"
#include "mission/core/GenericFactory.h"
#include "mission/devices/GPSHyperionHandler.h"
#include "mission/devices/GyroADIS1650XHandler.h"
#include "mission/utility/TmFunnel.h"
#include "objects/systemObjectList.h"
#include "tmtc/apid.h"
#include "tmtc/pusIds.h"
#include <mission/devices/GPSHyperionHandler.h>
#include "mission/devices/GyroADIS16507Handler.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/tmtcservices/CommandingServiceBase.h"
#include "fsfw/tmtcservices/PusServiceBase.h"
#include "fsfw/tmtcpacket/pus/tm.h"
#include "fsfw/tasks/TaskFactory.h"
/* UDP server includes */
#if OBSW_USE_TMTC_TCP_BRIDGE == 1
#include <fsfw/src/fsfw/osal/common/TcpTmTcBridge.h>
#include <fsfw/src/fsfw/osal/common/TcpTmTcServer.h>
#else
#include "fsfw/osal/common/UdpTcPollingTask.h"
#include "fsfw/osal/common/UdpTmTcBridge.h"
#include "fsfw/osal/common/UdpTcPollingTask.h"
#endif
#include "fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h"
#include "fsfw_hal/devicehandlers/MgmRM3100Handler.h"
#include "fsfw_hal/devicehandlers/GyroL3GD20Handler.h"
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
#include "fsfw_hal/linux/rpi/GpioRPi.h"
#include "fsfw_hal/common/gpio/GpioCookie.h"
#include "fsfw_hal/linux/spi/SpiCookie.h"
#include "fsfw_hal/linux/spi/SpiComIF.h"
#include <fsfw_hal/linux/uart/UartComIF.h>
#include <fsfw_hal/linux/uart/UartCookie.h>
#include "fsfw_hal/common/gpio/GpioCookie.h"
#include "fsfw_hal/devicehandlers/GyroL3GD20Handler.h"
#include "fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h"
#include "fsfw_hal/devicehandlers/MgmRM3100Handler.h"
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
#include "fsfw_hal/linux/rpi/GpioRPi.h"
#include "fsfw_hal/linux/spi/SpiComIF.h"
#include "fsfw_hal/linux/spi/SpiCookie.h"
void Factory::setStaticFrameworkObjectIds() {
PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR;
PusServiceBase::packetDestination = objects::TM_FUNNEL;
PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR;
PusServiceBase::packetDestination = objects::TM_FUNNEL;
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
// No storage object for now.
TmFunnel::storageDestination = objects::NO_OBJECT;
TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
// No storage object for now.
TmFunnel::storageDestination = objects::NO_OBJECT;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
}
void ObjectFactory::produce(void* args) {
Factory::setStaticFrameworkObjectIds();
ObjectFactory::produceGenericObjects();
GpioIF* gpioIF = new LinuxLibgpioIF(objects::GPIO_IF);
GpioCookie* gpioCookie = nullptr;
static_cast<void>(gpioCookie);
new SpiComIF(objects::SPI_COM_IF, gpioIF);
void ObjectFactory::produce(void* args){
Factory::setStaticFrameworkObjectIds();
ObjectFactory::produceGenericObjects();
std::string spiDev;
SpiCookie* spiCookie = nullptr;
static_cast<void>(spiCookie);
#if OBSW_USE_TMTC_TCP_BRIDGE == 1
auto tmtcBridge = new TcpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
tmtcBridge->setMaxNumberOfPacketsStored(50);
new TcpTmTcServer(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE);
#else
auto tmtcBridge = new UdpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
tmtcBridge->setMaxNumberOfPacketsStored(50);
new UdpTcPollingTask(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE);
#endif
GpioIF* gpioIF = new LinuxLibgpioIF(objects::GPIO_IF);
GpioCookie* gpioCookie = nullptr;
static_cast<void>(gpioCookie);
new SpiComIF(objects::SPI_COM_IF, gpioIF);
std::string spiDev;
SpiCookie* spiCookie = nullptr;
static_cast<void>(spiCookie);
#if OBSW_ADD_ACS_BOARD == 1
if (gpioCookie == nullptr) {
gpioCookie = new GpioCookie();
}
// TODO: Missing pin for Gyro 2
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_0_LIS3_CS, gpio::MGM_0_BCM_PIN, "MGM_0_LIS3",
gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_1_RM3100_CS, gpio::MGM_1_BCM_PIN,
"MGM_1_RM3100", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_2_LIS3_CS, gpio::MGM_2_BCM_PIN, "MGM_2_LIS3",
gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_3_RM3100_CS, gpio::MGM_3_BCM_PIN,
"MGM_3_RM3100", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_0_ADIS_CS, gpio::GYRO_0_BCM_PIN,
"GYRO_0_ADIS", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_1_L3G_CS, gpio::GYRO_1_BCM_PIN, "GYRO_1_L3G",
gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_2_ADIS_CS, gpio::GYRO_2_BCM_PIN,
"GYRO_2_ADIS", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_3_L3G_CS, gpio::GYRO_3_BCM_PIN, "GYRO_3_L3G",
gpio::Direction::OUT, 1);
gpioIF->addGpios(gpioCookie);
if(gpioCookie == nullptr) {
gpioCookie = new GpioCookie();
}
// TODO: Missing pin for Gyro 2
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_0_LIS3_CS, gpio::MGM_0_BCM_PIN,
"MGM_0_LIS3", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_1_RM3100_CS, gpio::MGM_1_BCM_PIN,
"MGM_1_RM3100", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_2_LIS3_CS, gpio::MGM_2_BCM_PIN,
"MGM_2_LIS3", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_3_RM3100_CS, gpio::MGM_3_BCM_PIN,
"MGM_3_RM3100", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_0_ADIS_CS, gpio::GYRO_0_BCM_PIN,
"GYRO_0_ADIS", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_1_L3G_CS, gpio::GYRO_1_BCM_PIN,
"GYRO_1_L3G", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_2_ADIS_CS, gpio::GYRO_2_BCM_PIN,
"GYRO_2_ADIS", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_3_L3G_CS, gpio::GYRO_3_BCM_PIN,
"GYRO_3_L3G", gpio::Direction::OUT, 1);
gpioIF->addGpios(gpioCookie);
spiDev = "/dev/spidev0.1";
spiCookie =
new SpiCookie(addresses::MGM_0_LIS3, gpioIds::MGM_0_LIS3_CS, spiDev,
MGMLIS3MDL::MAX_BUFFER_SIZE, spi::DEFAULT_LIS3_MODE, spi::DEFAULT_LIS3_SPEED);
auto mgmLis3Handler =
new MgmLIS3MDLHandler(objects::MGM_0_LIS3_HANDLER, objects::SPI_COM_IF, spiCookie, 0);
mgmLis3Handler->setStartUpImmediately();
spiDev = "/dev/spidev0.1";
spiCookie = new SpiCookie(addresses::MGM_0_LIS3, gpioIds::MGM_0_LIS3_CS, spiDev,
MGMLIS3MDL::MAX_BUFFER_SIZE, spi::DEFAULT_LIS3_MODE, spi::DEFAULT_LIS3_SPEED);
auto mgmLis3Handler = new MgmLIS3MDLHandler(objects::MGM_0_LIS3_HANDLER,
objects::SPI_COM_IF, spiCookie, 0);
mgmLis3Handler->setStartUpImmediately();
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
mgmLis3Handler->setToGoToNormalMode(true);
mgmLis3Handler->setToGoToNormalMode(true);
#endif
spiCookie =
new SpiCookie(addresses::MGM_1_RM3100, gpioIds::MGM_1_RM3100_CS, spiDev,
RM3100::MAX_BUFFER_SIZE, spi::DEFAULT_RM3100_MODE, spi::DEFAULT_RM3100_SPEED);
auto mgmRm3100Handler =
new MgmRM3100Handler(objects::MGM_1_RM3100_HANDLER, objects::SPI_COM_IF, spiCookie, 0);
mgmRm3100Handler->setStartUpImmediately();
spiCookie = new SpiCookie(addresses::MGM_1_RM3100, gpioIds::MGM_1_RM3100_CS, spiDev,
RM3100::MAX_BUFFER_SIZE, spi::DEFAULT_RM3100_MODE, spi::DEFAULT_RM3100_SPEED);
auto mgmRm3100Handler = new MgmRM3100Handler(objects::MGM_1_RM3100_HANDLER,
objects::SPI_COM_IF, spiCookie, 0);
mgmRm3100Handler->setStartUpImmediately();
#if FSFW_HAL_RM3100_MGM_DEBUG == 1
mgmRm3100Handler->setToGoToNormalMode(true);
mgmRm3100Handler->setToGoToNormalMode(true);
#endif
spiCookie =
new SpiCookie(addresses::MGM_2_LIS3, gpioIds::MGM_2_LIS3_CS, spiDev,
MGMLIS3MDL::MAX_BUFFER_SIZE, spi::DEFAULT_LIS3_MODE, spi::DEFAULT_LIS3_SPEED);
mgmLis3Handler =
new MgmLIS3MDLHandler(objects::MGM_2_LIS3_HANDLER, objects::SPI_COM_IF, spiCookie, 0);
mgmLis3Handler->setStartUpImmediately();
spiCookie = new SpiCookie(addresses::MGM_2_LIS3, gpioIds::MGM_2_LIS3_CS, spiDev,
MGMLIS3MDL::MAX_BUFFER_SIZE, spi::DEFAULT_LIS3_MODE, spi::DEFAULT_LIS3_SPEED);
mgmLis3Handler = new MgmLIS3MDLHandler(objects::MGM_2_LIS3_HANDLER,
objects::SPI_COM_IF, spiCookie, 0);
mgmLis3Handler->setStartUpImmediately();
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
mgmLis3Handler->setToGoToNormalMode(true);
mgmLis3Handler->setToGoToNormalMode(true);
#endif
spiCookie =
new SpiCookie(addresses::MGM_3_RM3100, gpioIds::MGM_3_RM3100_CS, spiDev,
RM3100::MAX_BUFFER_SIZE, spi::DEFAULT_RM3100_MODE, spi::DEFAULT_RM3100_SPEED);
mgmRm3100Handler =
new MgmRM3100Handler(objects::MGM_3_RM3100_HANDLER, objects::SPI_COM_IF, spiCookie, 0);
mgmRm3100Handler->setStartUpImmediately();
spiCookie = new SpiCookie(addresses::MGM_3_RM3100, gpioIds::MGM_3_RM3100_CS, spiDev,
RM3100::MAX_BUFFER_SIZE, spi::DEFAULT_RM3100_MODE, spi::DEFAULT_RM3100_SPEED);
mgmRm3100Handler = new MgmRM3100Handler(objects::MGM_3_RM3100_HANDLER,
objects::SPI_COM_IF, spiCookie, 0);
mgmRm3100Handler->setStartUpImmediately();
#if FSFW_HAL_RM3100_MGM_DEBUG == 1
mgmRm3100Handler->setToGoToNormalMode(true);
mgmRm3100Handler->setToGoToNormalMode(true);
#endif
spiCookie =
new SpiCookie(addresses::GYRO_0_ADIS, gpioIds::GYRO_0_ADIS_CS, spiDev,
ADIS16507::MAXIMUM_REPLY_SIZE, spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
auto adisHandler =
new GyroADIS16507Handler(objects::GYRO_0_ADIS_HANDLER, objects::SPI_COM_IF, spiCookie);
adisHandler->setStartUpImmediately();
spiCookie =
new SpiCookie(addresses::GYRO_1_L3G, gpioIds::GYRO_1_L3G_CS, spiDev, L3GD20H::MAX_BUFFER_SIZE,
spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
auto gyroL3gHandler =
new GyroHandlerL3GD20H(objects::GYRO_1_L3G_HANDLER, objects::SPI_COM_IF, spiCookie, 0);
gyroL3gHandler->setStartUpImmediately();
#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1
gyroL3gHandler->setToGoToNormalMode(true);
spiCookie = new SpiCookie(addresses::GYRO_0_ADIS, gpioIds::GYRO_0_ADIS_CS, spiDev,
ADIS16507::MAXIMUM_REPLY_SIZE, spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
auto adisHandler = new GyroADIS16507Handler(objects::GYRO_0_ADIS_HANDLER, objects::SPI_COM_IF,
spiCookie);
adisHandler->setStartUpImmediately();
spiCookie = new SpiCookie(addresses::GYRO_1_L3G, gpioIds::GYRO_1_L3G_CS, spiDev,
L3GD20H::MAX_BUFFER_SIZE, spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
auto gyroL3gHandler = new GyroHandlerL3GD20H(objects::GYRO_1_L3G_HANDLER, objects::SPI_COM_IF,
spiCookie, 0);
gyroL3gHandler->setStartUpImmediately();
#if FSFW_HAL_L3GD20_GYRO_DEBUG== 1
gyroL3gHandler->setToGoToNormalMode(true);
#endif
spiCookie =
new SpiCookie(addresses::GYRO_2_ADIS, gpioIds::GYRO_2_ADIS_CS, spiDev,
ADIS16507::MAXIMUM_REPLY_SIZE, spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
adisHandler =
new GyroADIS16507Handler(objects::GYRO_2_ADIS_HANDLER, objects::SPI_COM_IF, spiCookie);
adisHandler->setStartUpImmediately();
spiCookie = new SpiCookie(addresses::GYRO_2_ADIS, gpioIds::GYRO_2_ADIS_CS, spiDev,
ADIS16507::MAXIMUM_REPLY_SIZE, spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
adisHandler = new GyroADIS16507Handler(objects::GYRO_2_ADIS_HANDLER, objects::SPI_COM_IF,
spiCookie);
adisHandler->setStartUpImmediately();
spiCookie =
new SpiCookie(addresses::GYRO_3_L3G, gpioIds::GYRO_3_L3G_CS, spiDev, L3GD20H::MAX_BUFFER_SIZE,
spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
gyroL3gHandler =
new GyroHandlerL3GD20H(objects::GYRO_3_L3G_HANDLER, objects::SPI_COM_IF, spiCookie, 0);
gyroL3gHandler->setStartUpImmediately();
#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1
gyroL3gHandler->setToGoToNormalMode(true);
spiCookie = new SpiCookie(addresses::GYRO_3_L3G, gpioIds::GYRO_3_L3G_CS, spiDev,
L3GD20H::MAX_BUFFER_SIZE, spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
gyroL3gHandler = new GyroHandlerL3GD20H(objects::GYRO_3_L3G_HANDLER, objects::SPI_COM_IF,
spiCookie, 0);
gyroL3gHandler->setStartUpImmediately();
#if FSFW_HAL_L3GD20_GYRO_DEBUG== 1
gyroL3gHandler->setToGoToNormalMode(true);
#endif
#endif /* RPI_TEST_ACS_BOARD == 1 */
#if OBSW_ADD_TEST_CODE == 1
createTestTasks();
createTestTasks();
#endif /* OBSW_ADD_TEST_CODE == 1 */
}
void ObjectFactory::createTestTasks() {
new TestTask(objects::TEST_TASK);
#if OBSW_ADD_SPI_TEST_CODE == 1
new SpiTestClass(objects::SPI_TEST, gpioIF);
new TestTask(objects::TEST_TASK);
#if RPI_ADD_SPI_TEST == 1
new SpiTestClass(objects::SPI_TEST, gpioIF);
#endif
#if OBSW_ADD_UART_TEST_CODE == 1
new UartTestClass(objects::UART_TEST);
#if RPI_ADD_UART_TEST == 1
new UartTestClass(objects::UART_TEST);
#else
new UartComIF(objects::UART_COM_IF);
new UartComIF(objects::UART_COM_IF);
#endif
#if RPI_LOOPBACK_TEST_GPIO == 1
GpioCookie* gpioCookieLoopback = new GpioCookie();
/* Loopback pins. Adapt according to setup */
gpioId_t gpioIdSender = gpioIds::TEST_ID_0;
int bcmPinSender = 26;
gpioId_t gpioIdReader = gpioIds::TEST_ID_1;
int bcmPinReader = 16;
gpio::createRpiGpioConfig(gpioCookieLoopback, gpioIdSender, bcmPinSender, "GPIO_LB_SENDER",
gpio::Direction::OUT, 0);
gpio::createRpiGpioConfig(gpioCookieLoopback, gpioIdReader, bcmPinReader, "GPIO_LB_READER",
gpio::Direction::IN, 0);
new LibgpiodTest(objects::LIBGPIOD_TEST, objects::GPIO_IF, gpioCookieLoopback);
GpioCookie* gpioCookieLoopback = new GpioCookie();
/* Loopback pins. Adapt according to setup */
gpioId_t gpioIdSender = gpioIds::TEST_ID_0;
int bcmPinSender = 26;
gpioId_t gpioIdReader = gpioIds::TEST_ID_1;
int bcmPinReader = 16;
gpio::createRpiGpioConfig(gpioCookieLoopback, gpioIdSender, bcmPinSender, "GPIO_LB_SENDER",
gpio::Direction::OUT, 0);
gpio::createRpiGpioConfig(gpioCookieLoopback, gpioIdReader, bcmPinReader, "GPIO_LB_READER",
gpio::Direction::IN, 0);
new LibgpiodTest(objects::LIBGPIOD_TEST, objects::GPIO_IF, gpioCookieLoopback);
#endif /* RPI_LOOPBACK_TEST_GPIO == 1 */
#if RPI_TEST_ADIS16507 == 1
if (gpioCookie == nullptr) {
gpioCookie = new GpioCookie();
}
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_0_ADIS_CS, gpio::GYRO_0_BCM_PIN,
"GYRO_0_ADIS", gpio::Direction::OUT, 1);
gpioIF->addGpios(gpioCookie);
if(gpioCookie == nullptr) {
gpioCookie = new GpioCookie();
}
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_0_ADIS_CS, gpio::GYRO_0_BCM_PIN,
"GYRO_0_ADIS", gpio::Direction::OUT, 1);
gpioIF->addGpios(gpioCookie);
spiDev = "/dev/spidev0.1";
spiCookie = new SpiCookie(addresses::GYRO_0_ADIS, gpioIds::GYRO_0_ADIS_CS, spiDev,
ADIS16507::MAXIMUM_REPLY_SIZE, spi::DEFAULT_ADIS16507_MODE,
spi::DEFAULT_ADIS16507_SPEED, nullptr, nullptr);
auto adisGyroHandler =
new GyroADIS16507Handler(objects::GYRO_0_ADIS_HANDLER, objects::SPI_COM_IF, spiCookie);
adisGyroHandler->setStartUpImmediately();
spiDev = "/dev/spidev0.1";
spiCookie = new SpiCookie(addresses::GYRO_0_ADIS, gpioIds::GYRO_0_ADIS_CS, spiDev,
ADIS16507::MAXIMUM_REPLY_SIZE, spi::DEFAULT_ADIS16507_MODE, spi::DEFAULT_ADIS16507_SPEED,
nullptr, nullptr);
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, false);
gpsHandler->setStartUpImmediately();
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, false);
gpsHandler->setStartUpImmediately();
#endif
}

View File

@ -1,11 +1,12 @@
#ifndef BSP_LINUX_OBJECTFACTORY_H_
#define BSP_LINUX_OBJECTFACTORY_H_
namespace ObjectFactory {
void setStatics();
void produce(void* args);
void createTestTasks();
}; // namespace ObjectFactory
namespace ObjectFactory {
void setStatics();
void produce(void* args);
void createTestTasks();
};
#endif /* BSP_LINUX_OBJECTFACTORY_H_ */

View File

@ -1,7 +1,7 @@
target_sources(${OBSW_NAME} PRIVATE
target_sources(${TARGET_NAME} PRIVATE
print.c
)
target_include_directories(${OBSW_NAME} PUBLIC
target_include_directories(${TARGET_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@ -32,7 +32,7 @@ SOFTWARE.
#define ETL_CHECK_PUSH_POP
#define ETL_CPP11_SUPPORTED 1
#define ETL_NO_NULLPTR_SUPPORT 0
#define ETL_CPP11_SUPPORTED 1
#define ETL_NO_NULLPTR_SUPPORT 0
#endif

View File

@ -6,9 +6,8 @@
extern "C" void __gcov_flush();
#else
void __gcov_flush() {
sif::info << "GCC GCOV: Please supply GCOV=1 in Makefile if "
"coverage information is desired.\n"
<< std::flush;
sif::info << "GCC GCOV: Please supply GCOV=1 in Makefile if "
"coverage information is desired.\n" << std::flush;
}
#endif

View File

@ -1,10 +1,14 @@
#include <bsp_linux_board/boardconfig/print.h>
#include <bsp_q7s/boardconfig/print.h>
#include <stdio.h>
void printChar(const char* character, bool errStream) {
if (errStream) {
putc(*character, stderr);
return;
}
putc(*character, stdout);
if(errStream) {
putc(*character, stderr);
return;
}
putc(*character, stdout);
}

View File

@ -1,4 +1,4 @@
target_sources(${OBSW_NAME} PRIVATE
target_sources(${TARGET_NAME} PRIVATE
)

View File

@ -1,11 +1,12 @@
#include <iostream>
#include "InitMission.h"
#include "OBSWConfig.h"
#include "OBSWVersion.h"
#include "fsfw/FSFWVersion.h"
#include "fsfw/tasks/TaskFactory.h"
#include <iostream>
#ifdef RASPBERRY_PI
static const char* const BOARD_NAME = "Raspberry Pi";
#elif defined(BEAGLEBONEBLACK)
@ -18,18 +19,21 @@ static const char* const BOARD_NAME = "Unknown Board";
* @brief This is the main program and entry point for the Raspberry Pi.
* @return
*/
int main(void) {
std::cout << "-- EIVE OBSW --" << std::endl;
std::cout << "-- Compiled for Linux board " << BOARD_NAME << " --" << std::endl;
std::cout << "-- OBSW " << SW_NAME << " v" << SW_VERSION << "." << SW_SUBVERSION << "."
<< SW_REVISION << ", FSFW v" << FSFW_VERSION << "." << FSFW_SUBVERSION << FSFW_REVISION
<< "--" << std::endl;
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
int main(void)
{
std::cout << "-- EIVE OBSW --" << std::endl;
std::cout << "-- Compiled for Linux board " << BOARD_NAME << " --" << std::endl;
std::cout << "-- OBSW " << SW_NAME << " v" << SW_VERSION << "." << SW_SUBVERSION <<
"." << SW_REVISION << ", FSFW v" << FSFW_VERSION << "." << FSFW_SUBVERSION <<
FSFW_REVISION << "--" << std::endl;
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
initmission::initMission();
initmission::initMission();
for (;;) {
/* Suspend main thread by sleeping it. */
TaskFactory::delayTask(5000);
}
for(;;) {
/* Suspend main thread by sleeping it. */
TaskFactory::delayTask(5000);
}
}

View File

@ -1,25 +1,17 @@
#simple mode
add_executable(${SIMPLE_OBSW_NAME} EXCLUDE_FROM_ALL)
target_compile_definitions(${SIMPLE_OBSW_NAME} PRIVATE "Q7S_SIMPLE_MODE")
target_sources(${SIMPLE_OBSW_NAME} PUBLIC
main.cpp
)
#I think this is unintentional? (produces linker errors for stuff in /linux)
target_link_libraries(${SIMPLE_OBSW_NAME} PUBLIC
${LIB_FSFW_NAME}
)
target_compile_definitions(${SIMPLE_OBSW_NAME} PRIVATE "Q7S_SIMPLE_MODE")
add_subdirectory(simple)
target_sources(${OBSW_NAME} PUBLIC
target_sources(${TARGET_NAME} PUBLIC
main.cpp
)
add_subdirectory(boardtest)
add_subdirectory(boardconfig)
add_subdirectory(comIF)
add_subdirectory(core)
add_subdirectory(memory)
add_subdirectory(callbacks)
add_subdirectory(devices)
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(callbacks)
add_subdirectory(devices)
endif()

View File

@ -1,12 +1,7 @@
target_sources(${OBSW_NAME} PRIVATE
target_sources(${TARGET_NAME} PRIVATE
print.c
)
target_sources(${SIMPLE_OBSW_NAME} PRIVATE
print.c
)
target_include_directories(${OBSW_NAME} PUBLIC
target_include_directories(${TARGET_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@ -3,98 +3,98 @@
namespace q7s {
static constexpr char SPI_DEFAULT_DEV[] = "/dev/spi-main";
static constexpr char SPI_RW_DEV[] = "/dev/spi-rw";
static constexpr char SPI_DEFAULT_DEV[] = "/dev/spidev2.0";
static constexpr char SPI_RW_DEV[] = "/dev/spidev3.0";
static constexpr char I2C_DEFAULT_DEV[] = "/dev/i2c-eive";
static constexpr char I2C_DEFAULT_DEV[] = "/dev/i2c-1";
static constexpr char UART_GNSS_DEV[] = "/dev/ul-gps";
static constexpr char UART_PLOC_MPSOC_DEV[] = "/dev/ul-plmpsoc";
static constexpr char UART_PLOC_SUPERVSIOR_DEV[] = "/dev/ul-plsv";
static constexpr char UART_SYRLINKS_DEV[] = "/dev/ul-syrlinks";
static constexpr char UART_STAR_TRACKER_DEV[] = "/dev/ul-str";
static constexpr char UART_PLOC_MPSOC_DEV[] = "/dev/ttyUL3";
static constexpr char UART_PLOC_SUPERVSIOR_DEV[] = "/dev/ttyUL4";
static constexpr char UART_SYRLINKS_DEV[] = "/dev/ttyUL5";
static constexpr char UART_STAR_TRACKER_DEV[] = "/dev/ttyUL8";
static constexpr char UIO_PDEC_REGISTERS[] = "/dev/uio0";
static constexpr char UIO_PDEC_CONFIG_MEMORY[] = "/dev/uio2";
static constexpr char UIO_PDEC_RAM[] = "/dev/uio3";
static constexpr char UIO_PTME[] = "/dev/uio1";
static constexpr int MAP_ID_PTME_CONFIG = 3;
static constexpr char UART_GNSS_0_DEV[] = "/dev/ttyUL0";
static constexpr char UART_GNSS_1_DEV[] = "/dev/ttyUL2";
namespace uiomapids {
static const int PTME_VC0 = 0;
static const int PTME_VC1 = 1;
static const int PTME_VC2 = 2;
static const int PTME_VC3 = 3;
static const int PTME_CONFIG = 4;
} // namespace uiomapids
/**************************************************************/
/** OBC1E */
/**************************************************************/
static constexpr char GPIO_MULTIPURPOSE_1V8_OBC1D[] = "/amba_pl/gpio@42020000";
static const char* const GPIO_GYRO_ADIS_LABEL = GPIO_MULTIPURPOSE_1V8_OBC1D;
static constexpr uint32_t GPIO_GYRO_0_ADIS_CS = 0; // Package Pin: W20
static constexpr uint32_t GPIO_GYRO_2_ADIS_CS = 2; // AA22
namespace gpioNames {
/**************************************************************/
/** OBC1F B0 */
/**************************************************************/
static constexpr char GPIO_FLEX_OBC1F_B0[] = "/amba_pl/gpio@42030000";
static constexpr uint32_t GPIO_FLEX_OBC1F_B0_WIDTH = 20;
static const char* const GPIO_ACS_BOARD_DEFAULT_LABEL = GPIO_FLEX_OBC1F_B0;
static const char* const GPIO_RW_DEFAULT_LABEL = GPIO_FLEX_OBC1F_B0;
static const char* const GPIO_RAD_SENSOR_LABEL = GPIO_FLEX_OBC1F_B0;
static constexpr char GYRO_0_ADIS_CS[] = "gyro_0_adis_chip_select";
static constexpr char GYRO_1_L3G_CS[] = "gyro_1_l3g_chip_select";
static constexpr char GYRO_2_ADIS_CS[] = "gyro_2_adis_chip_select";
static constexpr char GYRO_3_L3G_CS[] = "gyro_3_l3g_chip_select";
static constexpr char MGM_0_CS[] = "mgm_0_lis3_chip_select";
static constexpr char MGM_1_CS[] = "mgm_1_rm3100_chip_select";
static constexpr char MGM_2_CS[] = "mgm_2_lis3_chip_select";
static constexpr char MGM_3_CS[] = "mgm_3_rm3100_chip_select";
static constexpr char RESET_GNSS_0[] = "reset_gnss_0";
static constexpr char RESET_GNSS_1[] = "reset_gnss_1";
static constexpr char GNSS_0_ENABLE[] = "enable_gnss_0";
static constexpr char GNSS_1_ENABLE[] = "enable_gnss_1";
static constexpr char GYRO_0_ENABLE[] = "enable_gyro_0";
static constexpr char GYRO_2_ENABLE[] = "enable_gyro_2";
static constexpr char GNSS_SELECT[] = "gnss_mux_select";
static constexpr char GNSS_MUX_SELECT[] = "gnss_mux_select";
static constexpr char HEATER_0[] = "heater0";
static constexpr char HEATER_1[] = "heater1";
static constexpr char HEATER_2[] = "heater2";
static constexpr char HEATER_3[] = "heater3";
static constexpr char HEATER_4[] = "heater4";
static constexpr char HEATER_5[] = "heater5";
static constexpr char HEATER_6[] = "heater6";
static constexpr char HEATER_7[] = "heater7";
static constexpr char SA_DPL_PIN_0[] = "sa_dpl_0";
static constexpr char SA_DPL_PIN_1[] = "sa_dpl_1";
static constexpr char SPI_MUX_BIT_0_PIN[] = "spi_mux_bit_0";
static constexpr char SPI_MUX_BIT_1_PIN[] = "spi_mux_bit_1";
static constexpr char SPI_MUX_BIT_2_PIN[] = "spi_mux_bit_2";
static constexpr char SPI_MUX_BIT_3_PIN[] = "spi_mux_bit_3";
static constexpr char SPI_MUX_BIT_4_PIN[] = "spi_mux_bit_4";
static constexpr char SPI_MUX_BIT_5_PIN[] = "spi_mux_bit_5";
static constexpr char EN_RW_CS[] = "en_rw_cs";
static constexpr char EN_RW_1[] = "enable_rw_1";
static constexpr char EN_RW_2[] = "enable_rw_2";
static constexpr char EN_RW_3[] = "enable_rw_3";
static constexpr char EN_RW_4[] = "enable_rw_4";
static constexpr uint32_t GPIO_RW_0_CS = 7; // B20
static constexpr uint32_t GPIO_RW_1_CS = 3; // G22
static constexpr uint32_t GPIO_RW_2_CS = 11; // E18
static constexpr uint32_t GPIO_RW_3_CS = 6; // B19
static constexpr char RAD_SENSOR_CHIP_SELECT[] = "rad_sensor_chip_select";
static constexpr char ENABLE_RADFET[] = "enable_radfet";
static constexpr char PAPB_BUSY_SIGNAL_VC0[] = "papb_busy_signal_vc0";
static constexpr char PAPB_EMPTY_SIGNAL_VC0[] = "papb_empty_signal_vc0";
static constexpr char PAPB_BUSY_SIGNAL_VC1[] = "papb_busy_signal_vc1";
static constexpr char PAPB_EMPTY_SIGNAL_VC1[] = "papb_empty_signal_vc1";
static constexpr char PAPB_BUSY_SIGNAL_VC2[] = "papb_busy_signal_vc2";
static constexpr char PAPB_EMPTY_SIGNAL_VC2[] = "papb_empty_signal_vc2";
static constexpr char PAPB_BUSY_SIGNAL_VC3[] = "papb_busy_signal_vc3";
static constexpr char PAPB_EMPTY_SIGNAL_VC3[] = "papb_empty_signal_vc3";
static constexpr char RS485_EN_TX_CLOCK[] = "tx_clock_enable_ltc2872";
static constexpr char RS485_EN_TX_DATA[] = "tx_data_enable_ltc2872";
static constexpr char RS485_EN_RX_CLOCK[] = "rx_clock_enable_ltc2872";
static constexpr char RS485_EN_RX_DATA[] = "rx_data_enable_ltc2872";
static constexpr char PDEC_RESET[] = "pdec_reset";
static constexpr uint32_t GPIO_GYRO_1_L3G_CS = 18; // N22
static constexpr uint32_t GPIO_GYRO_3_L3G_CS = 1; // M21
static constexpr uint32_t GPIO_MGM_0_LIS3_CS = 5; // C18
static constexpr uint32_t GPIO_MGM_1_RM3100_CS = 16; // A16
static constexpr uint32_t GPIO_MGM_3_RM3100_CS = 10; // C17
static constexpr char PL_PCDU_ENABLE_VBAT0[] = "enable_plpcdu_vbat0";
static constexpr char PL_PCDU_ENABLE_VBAT1[] = "enable_plpcdu_vbat1";
static constexpr char PL_PCDU_ENABLE_DRO[] = "enable_plpcdu_dro";
static constexpr char PL_PCDU_ENABLE_X8[] = "enable_plpcdu_x8";
static constexpr char PL_PCDU_ENABLE_TX[] = "enable_plpcdu_tx";
static constexpr char PL_PCDU_ENABLE_HPA[] = "enable_plpcdu_hpa";
static constexpr char PL_PCDU_ENABLE_MPA[] = "enable_plpcdu_mpa";
static constexpr char PL_PCDU_ADC_CS[] = "plpcdu_adc_chip_select";
// Active low enable pin (needs to be driven low for regular operations)
static constexpr uint32_t GPIO_GYRO_0_ENABLE = 2; // H22
} // namespace gpioNames
} // namespace q7s
// Active low reset pin (needs to be driven high for regular operations)
static constexpr uint32_t GPIO_RESET_GNSS_0 = 9; // C22
static constexpr uint32_t GPIO_RESET_GNSS_1 = 12; // B21
static constexpr uint32_t GPIO_RAD_SENSOR_CS = 19; // R18
/**************************************************************/
/** OBC1F B1 */
/**************************************************************/
static constexpr char GPIO_FLEX_OBC1F_B1[] = "/amba_pl/gpio@42030000";
// Need to use chip name here for now because the label name is the name for
// gpiochip 5 and gpiochip6
static constexpr char GPIO_FLEX_OBC1F_B1_CHIP[] = "gpiochip6";
static const char* const GPIO_MGM2_LIS3_LABEL = GPIO_FLEX_OBC1F_B1_CHIP;
static constexpr uint32_t GPIO_MGM_2_LIS3_CS = 0; // D18
/**************************************************************/
/** OBC1C */
/**************************************************************/
static constexpr char GPIO_3V3_OBC1C[] = "/amba_pl/gpio@42040000";
static const char* const GPIO_HEATER_LABEL = GPIO_3V3_OBC1C;
static const char* const GPIO_SOLAR_ARR_DEPL_LABEL = GPIO_3V3_OBC1C;
static constexpr uint32_t GPIO_HEATER_0_PIN = 6;
static constexpr uint32_t GPIO_HEATER_1_PIN = 12;
static constexpr uint32_t GPIO_HEATER_2_PIN = 7;
static constexpr uint32_t GPIO_HEATER_3_PIN = 5;
static constexpr uint32_t GPIO_HEATER_4_PIN = 3;
static constexpr uint32_t GPIO_HEATER_5_PIN = 0;
static constexpr uint32_t GPIO_HEATER_6_PIN = 1;
static constexpr uint32_t GPIO_HEATER_7_PIN = 11;
static constexpr uint32_t GPIO_GYRO_2_ENABLE = 18; // F22
static constexpr uint32_t GPIO_SOL_DEPL_SA_0_PIN = 4;
static constexpr uint32_t GPIO_SOL_DEPL_SA_1_PIN = 2;
static constexpr char GPIO_RW_SPI_MUX_LABEL[] = "zynq_gpio";
// Uses EMIO interface to PL, starts at 54
static constexpr uint32_t GPIO_RW_SPI_MUX_CS = 54;
static constexpr uint32_t SPI_MUX_BIT_1 = 13;
static constexpr uint32_t SPI_MUX_BIT_2 = 14;
static constexpr uint32_t SPI_MUX_BIT_3 = 15;
static constexpr uint32_t SPI_MUX_BIT_4 = 16;
static constexpr uint32_t SPI_MUX_BIT_5 = 17;
static constexpr uint32_t SPI_MUX_BIT_6 = 9;
static constexpr uint32_t EN_RW_CS = 17;
}
#endif /* BSP_Q7S_BOARDCONFIG_BUSCONF_H_ */

View File

@ -32,7 +32,7 @@ SOFTWARE.
#define ETL_CHECK_PUSH_POP
#define ETL_CPP11_SUPPORTED 1
#define ETL_NO_NULLPTR_SUPPORT 0
#define ETL_CPP11_SUPPORTED 1
#define ETL_NO_NULLPTR_SUPPORT 0
#endif

View File

@ -6,9 +6,8 @@
extern "C" void __gcov_flush();
#else
void __gcov_flush() {
sif::info << "GCC GCOV: Please supply GCOV=1 in Makefile if "
"coverage information is desired.\n"
<< std::flush;
sif::info << "GCC GCOV: Please supply GCOV=1 in Makefile if "
"coverage information is desired.\n" << std::flush;
}
#endif

View File

@ -2,9 +2,13 @@
#include <stdio.h>
void printChar(const char* character, bool errStream) {
if (errStream) {
putc(*character, stderr);
return;
}
putc(*character, stdout);
if(errStream) {
putc(*character, stderr);
return;
}
putc(*character, stdout);
}

View File

@ -3,6 +3,8 @@
#include <cstdint>
#cmakedefine01 Q7S_SIMPLE_MODE
/*******************************************************************/
/** All of the following flags should be enabled for mission code */
/*******************************************************************/

View File

@ -1,10 +1,8 @@
target_sources(${OBSW_NAME} PRIVATE
target_sources(${TARGET_NAME} PRIVATE
FileSystemTest.cpp
Q7STestTask.cpp
)
if(EIVE_BUILD_Q7S_SIMPLE_MODE)
target_sources(${SIMPLE_OBSW_NAME} PRIVATE
FileSystemTest.cpp
)
endif()

View File

@ -1,23 +1,26 @@
#include "FileSystemTest.h"
#include <cstdlib>
#include <iostream>
#include "fsfw/timemanager/Stopwatch.h"
enum SdCard { SDC0, SDC1 };
#include <iostream>
#include <cstdlib>
enum SdCard {
SDC0,
SDC1
};
FileSystemTest::FileSystemTest() {
using namespace std;
SdCard sdCard = SdCard::SDC0;
cout << "SD Card Test for SD card " << static_cast<int>(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);
using namespace std;
SdCard sdCard = SdCard::SDC0;
cout << "SD Card Test for SD card " << static_cast<int>(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() {}
FileSystemTest::~FileSystemTest() {
}

View File

@ -2,11 +2,12 @@
#define BSP_Q7S_BOARDTEST_FILESYSTEMTEST_H_
class FileSystemTest {
public:
FileSystemTest();
virtual ~FileSystemTest();
private:
public:
FileSystemTest();
virtual~ FileSystemTest();
private:
};
#endif /* BSP_Q7S_BOARDTEST_FILESYSTEMTEST_H_ */

View File

@ -1,397 +1,337 @@
#include "Q7STestTask.h"
#include <bsp_q7s/core/CoreController.h>
#include <bsp_q7s/memory/FileSystemHandler.h>
#include <fsfw/objectmanager/ObjectManager.h>
#include <gps.h>
#include <libgpsmm.h>
#include <cstdio>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <nlohmann/json.hpp>
#include "Q7STestTask.h"
#include "bsp_q7s/memory/SdCardManager.h"
#include "bsp_q7s/memory/scratchApi.h"
#include "fsfw/tasks/TaskFactory.h"
#include "fsfw/timemanager/Stopwatch.h"
#include "fsfw/tasks/TaskFactory.h"
#include "test/DummyParameter.h"
Q7STestTask::Q7STestTask(object_id_t objectId) : TestTask(objectId) {
doTestSdCard = false;
doTestScratchApi = false;
doTestGps = false;
#include <nlohmann/json.hpp>
#include <iostream>
#include <fstream>
#include <cstdio>
Q7STestTask::Q7STestTask(object_id_t objectId): TestTask(objectId) {
}
ReturnValue_t Q7STestTask::performOneShotAction() {
if (doTestSdCard) {
testSdCard();
}
if (doTestScratchApi) {
testScratchApi();
}
// testJsonLibDirect();
// testDummyParams();
// testProtHandler();
FsOpCodes opCode = FsOpCodes::APPEND_TO_FILE;
testFileSystemHandlerDirect(opCode);
return TestTask::performOneShotAction();
}
ReturnValue_t Q7STestTask::performPeriodicAction() {
if (doTestGps) {
testGpsDaemon();
}
return TestTask::performPeriodicAction();
//testSdCard();
//testScratchApi();
//testJsonLibDirect();
//testDummyParams();
//testProtHandler();
//FsOpCodes opCode = FsOpCodes::ATTEMPT_DIR_REMOVAL_NON_EMPTY;
//testFileSystemHandlerDirect(opCode);
return TestTask::performOneShotAction();
}
void Q7STestTask::testSdCard() {
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<int>(idx) << " is on" << endl;
} else if (word == "off") {
sif::info << "SD card " << static_cast<int>(idx) << " is off" << endl;
}
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;
}
idx++;
}
std::remove("/tmp/sd_status.txt");
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<int>(idx) << " is on" << endl;
}
else if(word == "off") {
sif::info << "SD card " << static_cast<int>(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();
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\"");
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);
sif::info << "Q7STestTask::testScratchApi: Value for key \"TEST\": " << number << std::endl;
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::debug << "Q7STestTask::scratchApiTest: Reading number failed" << std::endl;
}
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);
sif::info << "Q7STestTask::testScratchApi: Value for key \"TEST\": " << number << std::endl;
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::debug << "Q7STestTask::scratchApiTest: Reading number failed" << std::endl;
}
result = scratch::writeString("TEST2", "halloWelt");
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::debug << "Q7STestTask::scratchApiTest: Writing string failed" << std::endl;
}
std::string string;
result = scratch::readString("TEST2", string);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::debug << "Q7STestTask::scratchApiTest: Reading number failed" << std::endl;
}
sif::info << "Q7STestTask::testScratchApi: Value for key \"TEST2\": " << string << std::endl;
result = scratch::writeString("TEST2", "halloWelt");
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::debug << "Q7STestTask::scratchApiTest: Writing string failed" << std::endl;
}
std::string string;
result = scratch::readString("TEST2", string);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::debug << "Q7STestTask::scratchApiTest: Reading number failed" << std::endl;
}
sif::info << "Q7STestTask::testScratchApi: Value for key \"TEST2\": " << string << std::endl;
result = scratch::clearValue("TEST");
result = scratch::clearValue("TEST2");
result = scratch::clearValue("TEST");
result = scratch::clearValue("TEST2");
}
void Q7STestTask::testJsonLibDirect() {
Stopwatch stopwatch;
// for convenience
using json = nlohmann::json;
json helloTest;
// add a number that is stored as double (note the implicit conversion of j to an object)
helloTest["pi"] = 3.141;
std::string mntPrefix = SdCardManager::instance()->getCurrentMountPrefix();
std::string fileName = mntPrefix + "/pretty.json";
std::ofstream o(fileName);
o << std::setw(4) << helloTest << std::endl;
Stopwatch stopwatch;
// for convenience
using json = nlohmann::json;
json helloTest;
// add a number that is stored as double (note the implicit conversion of j to an object)
helloTest["pi"] = 3.141;
std::string mntPrefix = SdCardManager::instance()->getCurrentMountPrefix();
std::string fileName = mntPrefix + "/pretty.json";
std::ofstream o(fileName);
o << std::setw(4) << helloTest << std::endl;
}
void Q7STestTask::testDummyParams() {
std::string mntPrefix = SdCardManager::instance()->getCurrentMountPrefix();
DummyParameter param(mntPrefix, "dummy_json.txt");
param.printKeys();
param.print();
if (not param.getJsonFileExists()) {
std::string mntPrefix = SdCardManager::instance()->getCurrentMountPrefix();
DummyParameter param(mntPrefix, "dummy_json.txt");
param.printKeys();
param.print();
if(not param.getJsonFileExists()) {
param.writeJsonFile();
}
ReturnValue_t result = param.readJsonFile();
if(result != HasReturnvaluesIF::RETURN_OK) {
}
param.setValue(DummyParameter::DUMMY_KEY_PARAM_1, 3);
param.setValue(DummyParameter::DUMMY_KEY_PARAM_2, "blirb");
param.writeJsonFile();
}
param.print();
ReturnValue_t result = param.readJsonFile();
if (result != HasReturnvaluesIF::RETURN_OK) {
}
param.setValue(DummyParameter::DUMMY_KEY_PARAM_1, 3);
param.setValue(DummyParameter::DUMMY_KEY_PARAM_2, "blirb");
param.writeJsonFile();
param.print();
int test = 0;
result = param.getValue<int>(DummyParameter::DUMMY_KEY_PARAM_1, test);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testDummyParams: Key " << DummyParameter::DUMMY_KEY_PARAM_1
<< " does not exist" << std::endl;
}
std::string test2;
result = param.getValue<std::string>(DummyParameter::DUMMY_KEY_PARAM_2, test2);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testDummyParams: Key " << DummyParameter::DUMMY_KEY_PARAM_1
<< " does not exist" << std::endl;
}
sif::info << "Test value (3 expected): " << test << std::endl;
sif::info << "Test value 2 (\"blirb\" expected): " << test2 << std::endl;
int test = param.getValue<int>(DummyParameter::DUMMY_KEY_PARAM_1);
std::string test2 = param.getValue<std::string>(DummyParameter::DUMMY_KEY_PARAM_2);
sif::info << "Test value (3 expected): " << test << std::endl;
sif::info << "Test value 2 (\"blirb\" expected): " << test2 << std::endl;
}
ReturnValue_t Q7STestTask::initialize() {
coreController = ObjectManager::instance()->get<CoreController>(objects::CORE_CONTROLLER);
if (coreController == nullptr) {
sif::warning << "Q7STestTask::initialize: Could not retrieve CORE_CONTROLLER object"
<< std::endl;
}
return TestTask::initialize();
coreController = ObjectManager::instance()->get<CoreController>(objects::CORE_CONTROLLER);
if(coreController == nullptr) {
sif::warning << "Q7STestTask::initialize: Could not retrieve CORE_CONTROLLER object" <<
std::endl;
}
return TestTask::initialize();
}
void Q7STestTask::testProtHandler() {
bool opPerformed = false;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
// If any chips are unlocked, lock them here
result = coreController->setBootCopyProtection(xsc::Chip::ALL_CHIP, xsc::Copy::ALL_COPY, true,
opPerformed, true);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
bool opPerformed = false;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
// If any chips are unlocked, lock them here
result = coreController->setBootCopyProtection(
CoreController::Chip::ALL_CHIP, CoreController::Copy::ALL_COPY, true,
opPerformed, true);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
// unlock own copy
result = coreController->setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, false,
opPerformed, true);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
if (not opPerformed) {
sif::warning << "Q7STestTask::testProtHandler: No op performed" << std::endl;
}
int retval = std::system("print-chip-prot-status.sh");
if (retval != 0) {
utility::handleSystemError(retval, "Q7STestTask::testProtHandler");
}
// unlock own copy
result = coreController->setBootCopyProtection(
CoreController::Chip::SELF_CHIP, CoreController::Copy::SELF_COPY, false,
opPerformed, true);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
if(not opPerformed) {
sif::warning << "Q7STestTask::testProtHandler: No op performed" << std::endl;
}
int retval = std::system("print-chip-prot-status.sh");
if(retval != 0) {
utility::handleSystemError(retval, "Q7STestTask::testProtHandler");
}
// lock own copy
result = coreController->setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true,
opPerformed, true);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
if (not opPerformed) {
sif::warning << "Q7STestTask::testProtHandler: No op performed" << std::endl;
}
retval = std::system("print-chip-prot-status.sh");
if (retval != 0) {
utility::handleSystemError(retval, "Q7STestTask::testProtHandler");
}
// lock own copy
result = coreController->setBootCopyProtection(
CoreController::Chip::SELF_CHIP, CoreController::Copy::SELF_COPY, true,
opPerformed, true);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
if(not opPerformed) {
sif::warning << "Q7STestTask::testProtHandler: No op performed" << std::endl;
}
retval = std::system("print-chip-prot-status.sh");
if(retval != 0) {
utility::handleSystemError(retval, "Q7STestTask::testProtHandler");
}
// unlock specific copy
result = coreController->setBootCopyProtection(xsc::Chip::CHIP_1, xsc::Copy::COPY_1, false,
opPerformed, true);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
if (not opPerformed) {
sif::warning << "Q7STestTask::testProtHandler: No op performed" << std::endl;
}
retval = std::system("print-chip-prot-status.sh");
if (retval != 0) {
utility::handleSystemError(retval, "Q7STestTask::testProtHandler");
}
// unlock specific copy
result = coreController->setBootCopyProtection(
CoreController::Chip::CHIP_1, CoreController::Copy::COPY_1, false,
opPerformed, true);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
if(not opPerformed) {
sif::warning << "Q7STestTask::testProtHandler: No op performed" << std::endl;
}
retval = std::system("print-chip-prot-status.sh");
if(retval != 0) {
utility::handleSystemError(retval, "Q7STestTask::testProtHandler");
}
// lock specific copy
result = coreController->setBootCopyProtection(xsc::Chip::CHIP_1, xsc::Copy::COPY_1, true,
opPerformed, true);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
if (not opPerformed) {
sif::warning << "Q7STestTask::testProtHandler: No op performed" << std::endl;
}
retval = std::system("print-chip-prot-status.sh");
if (retval != 0) {
utility::handleSystemError(retval, "Q7STestTask::testProtHandler");
}
}
void Q7STestTask::testGpsDaemon() {
gpsmm gpsmm(GPSD_SHARED_MEMORY, 0);
gps_data_t* gps;
gps = gpsmm.read();
if (gps == nullptr) {
sif::warning << "Q7STestTask: Reading GPS data failed" << std::endl;
}
sif::info << "-- Q7STestTask: GPS shared memory read test --" << std::endl;
time_t timeRaw = gps->fix.time.tv_sec;
std::tm* time = gmtime(&timeRaw);
sif::info << "Time: " << std::put_time(time, "%c %Z") << std::endl;
sif::info << "Visible satellites: " << gps->satellites_visible << std::endl;
sif::info << "Satellites used: " << gps->satellites_used << std::endl;
sif::info << "Fix (0:Not Seen|1:No Fix|2:2D|3:3D): " << gps->fix.mode << std::endl;
sif::info << "Latitude: " << gps->fix.latitude << std::endl;
sif::info << "Longitude: " << gps->fix.longitude << std::endl;
sif::info << "Altitude(MSL): " << gps->fix.altMSL << std::endl;
sif::info << "Speed(m/s): " << gps->fix.speed << std::endl;
// lock specific copy
result = coreController->setBootCopyProtection(
CoreController::Chip::CHIP_1, CoreController::Copy::COPY_1, true,
opPerformed, true);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
if(not opPerformed) {
sif::warning << "Q7STestTask::testProtHandler: No op performed" << std::endl;
}
retval = std::system("print-chip-prot-status.sh");
if(retval != 0) {
utility::handleSystemError(retval, "Q7STestTask::testProtHandler");
}
}
void Q7STestTask::testFileSystemHandlerDirect(FsOpCodes opCode) {
auto fsHandler = ObjectManager::instance()->get<FileSystemHandler>(objects::FILE_SYSTEM_HANDLER);
if (fsHandler == nullptr) {
sif::warning << "Q7STestTask::testFileSystemHandlerDirect: No FS handler running.."
<< std::endl;
}
FileSystemHandler::FsCommandCfg cfg = {};
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
auto fsHandler = ObjectManager::instance()->
get<FileSystemHandler>(objects::FILE_SYSTEM_HANDLER);
if(fsHandler == nullptr) {
sif::warning << "Q7STestTask::testFileSystemHandlerDirect: No FS handler running.."
<< std::endl;
}
FileSystemHandler::FsCommandCfg cfg = {};
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
// Lambda for common code
auto createNonEmptyTmpDir = [&]() {
if (not std::filesystem::exists("/tmp/test")) {
result = fsHandler->createDirectory("/tmp", "test", false, &cfg);
if (result != HasReturnvaluesIF::RETURN_OK) {
// Lambda for common code
auto createNonEmptyTmpDir = [&]() {
if(not std::filesystem::exists("/tmp/test")) {
result = fsHandler->createDirectory("/tmp/test", &cfg);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
// Creating sample files
sif::info << "Creating sample files in directory" << std::endl;
result = fsHandler->createFile("/tmp/test", "test1.txt", nullptr, 0, &cfg);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = fsHandler->createFile("/tmp/test", "test2.txt", nullptr, 0, &cfg);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return result;
}
}
// Creating sample files
sif::info << "Creating sample files in directory" << std::endl;
result = fsHandler->createFile("/tmp/test", "test1.txt", nullptr, 0, &cfg);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = fsHandler->createFile("/tmp/test", "test2.txt", nullptr, 0, &cfg);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return result;
};
};
switch (opCode) {
case (FsOpCodes::CREATE_EMPTY_FILE_IN_TMP): {
// No mount prefix, cause file is created in tmp
cfg.useMountPrefix = false;
sif::info << "Creating empty file in /tmp folder" << std::endl;
// Do not delete file, user can check existence in shell
fsHandler->createFile("/tmp/", "test.txt", nullptr, 0, &cfg);
break;
switch(opCode) {
case(FsOpCodes::CREATE_EMPTY_FILE_IN_TMP): {
// No mount prefix, cause file is created in tmp
cfg.useMountPrefix = false;
sif::info << "Creating empty file in /tmp folder" << std::endl;
// Do not delete file, user can check existence in shell
fsHandler->createFile("/tmp", "test.txt", nullptr, 0, &cfg);
break;
}
case (FsOpCodes::REMOVE_TMP_FILE): {
sif::info << "Deleting /tmp/test.txt sample file" << std::endl;
// No mount prefix, cause file is created in tmp
cfg.useMountPrefix = false;
if (not std::filesystem::exists("/tmp/test.txt")) {
// Creating sample file
sif::info << "Creating sample file /tmp/test.txt to delete" << std::endl;
fsHandler->createFile("/tmp/", "test.txt", nullptr, 0, &cfg);
}
result = fsHandler->removeFile("/tmp", "test.txt", &cfg);
if (result == HasReturnvaluesIF::RETURN_OK) {
sif::info << "File removed successfully" << std::endl;
} else {
sif::warning << "File removal failed!" << std::endl;
}
break;
case(FsOpCodes::REMOVE_TMP_FILE): {
sif::info << "Deleting /tmp/test.txt sample file" << std::endl;
// No mount prefix, cause file is created in tmp
cfg.useMountPrefix = false;
if(not std::filesystem::exists("/tmp/test.txt")) {
// Creating sample file
sif::info << "Creating sample file /tmp/test.txt to delete" << std::endl;
fsHandler->createFile("/tmp", "test.txt", nullptr, 0, &cfg);
}
result = fsHandler->removeFile("/tmp", "test.txt", &cfg);
if(result == HasReturnvaluesIF::RETURN_OK) {
sif::info << "File removed successfully" << std::endl;
}
else {
sif::warning << "File removal failed!" << std::endl;
}
break;
}
case (FsOpCodes::CREATE_DIR_IN_TMP): {
// No mount prefix, cause file is created in tmp
cfg.useMountPrefix = false;
sif::info << "Creating empty file in /tmp folder" << std::endl;
// Do not delete file, user can check existence in shell
ReturnValue_t result = fsHandler->createDirectory("/tmp/", "test", false, &cfg);
if (result == HasReturnvaluesIF::RETURN_OK) {
sif::info << "Directory created successfully" << std::endl;
} else {
sif::warning << "Directory creation failed!" << std::endl;
}
break;
case(FsOpCodes::CREATE_DIR_IN_TMP): {
// No mount prefix, cause file is created in tmp
cfg.useMountPrefix = false;
sif::info << "Creating empty file in /tmp folder" << std::endl;
// Do not delete file, user can check existence in shell
ReturnValue_t result = fsHandler->createDirectory("/tmp/test", &cfg);
if(result == HasReturnvaluesIF::RETURN_OK) {
sif::info << "Directory created successfully" << std::endl;
}
else {
sif::warning << "Directory creation failed!" << std::endl;
}
break;
}
case (FsOpCodes::REMOVE_EMPTY_DIR_IN_TMP): {
// No mount prefix, cause file is created in tmp
cfg.useMountPrefix = false;
if (not std::filesystem::exists("/tmp/test")) {
result = fsHandler->createDirectory("/tmp", "test", false, &cfg);
} else {
// Delete any leftover files to regular dir removal works
std::remove("/tmp/test/*");
}
result = fsHandler->removeDirectory("/tmp/", "test", false, &cfg);
if (result == HasReturnvaluesIF::RETURN_OK) {
sif::info << "Directory removed successfully" << std::endl;
} else {
sif::warning << "Directory removal failed!" << std::endl;
}
break;
case(FsOpCodes::REMOVE_EMPTY_DIR_IN_TMP): {
// No mount prefix, cause file is created in tmp
cfg.useMountPrefix = false;
if(not std::filesystem::exists("/tmp/test")) {
result = fsHandler->createDirectory("/tmp/test", &cfg);
}
else {
// Delete any leftover files to regular dir removal works
std::remove("/tmp/test/*");
}
result = fsHandler->removeDirectory("/tmp/test", false, &cfg);
if(result == HasReturnvaluesIF::RETURN_OK) {
sif::info << "Directory removed successfully" << std::endl;
}
else {
sif::warning << "Directory removal failed!" << std::endl;
}
break;
}
case (FsOpCodes::REMOVE_FILLED_DIR_IN_TMP): {
result = createNonEmptyTmpDir();
if (result != HasReturnvaluesIF::RETURN_OK) {
return;
}
result = fsHandler->removeDirectory("/tmp/", "test", true, &cfg);
if (result == HasReturnvaluesIF::RETURN_OK) {
sif::info << "Directory removed recursively successfully" << std::endl;
} else {
sif::warning << "Recursive directory removal failed!" << std::endl;
}
break;
case(FsOpCodes::REMOVE_FILLED_DIR_IN_TMP): {
result = createNonEmptyTmpDir();
if(result != HasReturnvaluesIF::RETURN_OK) {
return;
}
result = fsHandler->removeDirectory("/tmp/test", true, &cfg);
if(result == HasReturnvaluesIF::RETURN_OK) {
sif::info << "Directory removed recursively successfully" << std::endl;
}
else {
sif::warning << "Recursive directory removal failed!" << std::endl;
}
break;
}
case (FsOpCodes::ATTEMPT_DIR_REMOVAL_NON_EMPTY): {
result = createNonEmptyTmpDir();
if (result != HasReturnvaluesIF::RETURN_OK) {
return;
}
result = fsHandler->removeDirectory("/tmp/", "test", false, &cfg);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::info << "Directory removal attempt failed as expected" << std::endl;
} else {
sif::warning << "Directory removal worked when it should not have!" << std::endl;
}
break;
case(FsOpCodes::ATTEMPT_DIR_REMOVAL_NON_EMPTY): {
result = createNonEmptyTmpDir();
if(result != HasReturnvaluesIF::RETURN_OK) {
return;
}
result = fsHandler->removeDirectory("/tmp/test", false, &cfg);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::info << "Directory removal attempt failed as expected" << std::endl;
}
else {
sif::warning << "Directory removal worked when it should not have!" << std::endl;
}
}
case (FsOpCodes::RENAME_FILE): {
// No mount prefix, cause file is created in tmp
cfg.useMountPrefix = false;
if (std::filesystem::exists("/tmp/test.txt")) {
fsHandler->removeDirectory("/tmp/", "test", false, &cfg);
}
sif::info << "Creating empty file /tmp/test.txt and rename to /tmp/test2.txt" << std::endl;
// Do not delete file, user can check existence in shell
fsHandler->createFile("/tmp/", "test.txt", nullptr, 0, &cfg);
fsHandler->renameFile("/tmp/", "test.txt", "test2.txt", &cfg);
break;
}
case (FsOpCodes::APPEND_TO_FILE): {
// No mount prefix, cause file is created in tmp
cfg.useMountPrefix = false;
if (std::filesystem::exists("/tmp/test.txt")) {
fsHandler->removeDirectory("/tmp/", "test", false, &cfg);
}
if (std::filesystem::exists("/tmp/test.txt")) {
fsHandler->removeDirectory("/tmp/", "test", false, &cfg);
}
sif::info << "Creating empty file /tmp/test.txt and adding content" << std::endl;
std::string content = "Hello World\n";
// Do not delete file, user can check existence in shell
fsHandler->createFile("/tmp/", "test.txt", nullptr, 0, &cfg);
fsHandler->appendToFile("/tmp/", "test.txt", reinterpret_cast<const uint8_t*>(content.data()),
content.size(), 0, &cfg);
}
}
}

View File

@ -3,44 +3,33 @@
#include "test/testtasks/TestTask.h"
class CoreController;
class Q7STestTask: public TestTask {
public:
Q7STestTask(object_id_t objectId);
class Q7STestTask : public TestTask {
public:
Q7STestTask(object_id_t objectId);
ReturnValue_t initialize() override;
private:
CoreController* coreController = nullptr;
ReturnValue_t performOneShotAction() override;
ReturnValue_t initialize() override;
void testSdCard();
void fileTests();
private:
bool doTestSdCard = false;
bool doTestScratchApi = false;
bool doTestGps = false;
void testScratchApi();
void testJsonLibDirect();
void testDummyParams();
void testProtHandler();
CoreController* coreController = nullptr;
ReturnValue_t performOneShotAction() override;
ReturnValue_t performPeriodicAction() override;
void testGpsDaemon();
void testSdCard();
void fileTests();
void testScratchApi();
void testJsonLibDirect();
void testDummyParams();
void testProtHandler();
enum FsOpCodes {
CREATE_EMPTY_FILE_IN_TMP,
REMOVE_TMP_FILE,
CREATE_DIR_IN_TMP,
REMOVE_EMPTY_DIR_IN_TMP,
ATTEMPT_DIR_REMOVAL_NON_EMPTY,
REMOVE_FILLED_DIR_IN_TMP,
RENAME_FILE,
APPEND_TO_FILE,
};
void testFileSystemHandlerDirect(FsOpCodes opCode);
enum FsOpCodes {
CREATE_EMPTY_FILE_IN_TMP,
REMOVE_TMP_FILE,
CREATE_DIR_IN_TMP,
REMOVE_EMPTY_DIR_IN_TMP,
ATTEMPT_DIR_REMOVAL_NON_EMPTY,
REMOVE_FILLED_DIR_IN_TMP,
};
void testFileSystemHandlerDirect(FsOpCodes opCode);
};
#endif /* BSP_Q7S_BOARDTEST_Q7STESTTASK_H_ */

View File

@ -1,6 +1,4 @@
target_sources(${OBSW_NAME} PRIVATE
target_sources(${TARGET_NAME} PRIVATE
rwSpiCallback.cpp
gnssCallback.cpp
pcduSwitchCb.cpp
gpioCallbacks.cpp
)

View File

@ -1,25 +1,26 @@
#include "gnssCallback.h"
#include "devices/gpioIds.h"
#include "fsfw/tasks/TaskFactory.h"
ReturnValue_t gps::triggerGpioResetPin(void* args) {
ResetArgs* resetArgs = reinterpret_cast<ResetArgs*>(args);
if (args == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if (resetArgs->gpioComIF == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
gpioId_t gpioId;
if (resetArgs->gnss1) {
gpioId = gpioIds::GNSS_1_NRESET;
ReturnValue_t gps::triggerGpioResetPin(void *args) {
ResetArgs* resetArgs = reinterpret_cast<ResetArgs*>(args);
if(args == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if (resetArgs->gpioComIF == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
gpioId_t gpioId;
if(resetArgs->gnss1) {
gpioId = gpioIds::GNSS_1_NRESET;
} else {
gpioId = gpioIds::GNSS_0_NRESET;
}
resetArgs->gpioComIF->pullLow(gpioId);
TaskFactory::delayTask(resetArgs->waitPeriodMs);
resetArgs->gpioComIF->pullHigh(gpioId);
return HasReturnvaluesIF::RETURN_OK;
}
else {
gpioId = gpioIds::GNSS_0_NRESET;
}
resetArgs->gpioComIF->pullLow(gpioId);
TaskFactory::delayTask(resetArgs->waitPeriodMs);
resetArgs->gpioComIF->pullHigh(gpioId);
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -1,13 +1,13 @@
#ifndef BSP_Q7S_CALLBACKS_GNSSCALLBACK_H_
#define BSP_Q7S_CALLBACKS_GNSSCALLBACK_H_
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
struct ResetArgs {
bool gnss1 = false;
LinuxLibgpioIF* gpioComIF = nullptr;
uint32_t waitPeriodMs = 100;
bool gnss1 = false;
LinuxLibgpioIF* gpioComIF = nullptr;
uint32_t waitPeriodMs = 100;
};
namespace gps {

View File

@ -1,487 +0,0 @@
#include "gpioCallbacks.h"
#include <devices/gpioIds.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw_hal/common/gpio/GpioCookie.h>
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
#include "busConf.h"
namespace gpioCallbacks {
GpioIF* gpioComInterface;
void initSpiCsDecoder(GpioIF* gpioComIF) {
using namespace gpio;
ReturnValue_t result;
if (gpioComIF == nullptr) {
sif::debug << "initSpiCsDecoder: Invalid gpioComIF" << std::endl;
return;
}
gpioComInterface = gpioComIF;
GpioCookie* spiMuxGpios = new GpioCookie;
GpiodRegularByLineName* spiMuxBit = nullptr;
/** Setting mux bit 1 to low will disable IC21 on the interface board */
spiMuxBit = new GpiodRegularByLineName(q7s::gpioNames::SPI_MUX_BIT_0_PIN, "SPI Mux Bit 1",
Direction::OUT, Levels::HIGH);
spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_0, spiMuxBit);
/** Setting mux bit 2 to low disables IC1 on the TCS board */
spiMuxBit = new GpiodRegularByLineName(q7s::gpioNames::SPI_MUX_BIT_1_PIN, "SPI Mux Bit 2",
Direction::OUT, Levels::HIGH);
spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_1, spiMuxBit);
/** Setting mux bit 3 to low disables IC2 on the TCS board and IC22 on the interface board */
spiMuxBit = new GpiodRegularByLineName(q7s::gpioNames::SPI_MUX_BIT_2_PIN, "SPI Mux Bit 3",
Direction::OUT, Levels::LOW);
spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_2, spiMuxBit);
/** The following gpios can take arbitrary initial values */
spiMuxBit = new GpiodRegularByLineName(q7s::gpioNames::SPI_MUX_BIT_3_PIN, "SPI Mux Bit 4",
Direction::OUT, Levels::LOW);
spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_3, spiMuxBit);
spiMuxBit = new GpiodRegularByLineName(q7s::gpioNames::SPI_MUX_BIT_4_PIN, "SPI Mux Bit 5",
Direction::OUT, Levels::LOW);
spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_4, spiMuxBit);
spiMuxBit = new GpiodRegularByLineName(q7s::gpioNames::SPI_MUX_BIT_5_PIN, "SPI Mux Bit 6",
Direction::OUT, Levels::LOW);
spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_5, spiMuxBit);
GpiodRegularByLineName* enRwDecoder = new GpiodRegularByLineName(
q7s::gpioNames::EN_RW_CS, "EN_RW_CS", Direction::OUT, Levels::HIGH);
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;
return;
}
}
void spiCsDecoderCallback(gpioId_t gpioId, gpio::GpioOperation gpioOp, gpio::Levels value,
void* args) {
using namespace gpio;
if (gpioComInterface == nullptr) {
sif::debug << "spiCsDecoderCallback: No gpioComIF specified. Call initSpiCsDecoder "
<< "to specify gpioComIF" << std::endl;
return;
}
/* Reading is not supported by the callback function */
if (gpioOp == gpio::GpioOperation::READ) {
return;
}
if (value == Levels::HIGH) {
switch (gpioId) {
case (gpioIds::RTD_IC_3): {
disableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_4): {
disableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_5): {
disableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_6): {
disableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_7): {
disableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_8): {
disableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_9): {
disableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_10): {
disableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_11): {
disableDecoderTcsIc2();
break;
}
case (gpioIds::RTD_IC_12): {
disableDecoderTcsIc2();
break;
}
case (gpioIds::RTD_IC_13): {
disableDecoderTcsIc2();
break;
}
case (gpioIds::RTD_IC_14): {
disableDecoderTcsIc2();
break;
}
case (gpioIds::RTD_IC_15): {
disableDecoderTcsIc2();
break;
}
case (gpioIds::RTD_IC_16): {
disableDecoderTcsIc2();
break;
}
case (gpioIds::RTD_IC_17): {
disableDecoderTcsIc2();
break;
}
case (gpioIds::RTD_IC_18): {
disableDecoderTcsIc2();
break;
}
case (gpioIds::CS_SUS_0): {
disableDecoderInterfaceBoardIc1();
break;
}
case (gpioIds::CS_SUS_1): {
disableDecoderInterfaceBoardIc1();
break;
}
case (gpioIds::CS_SUS_2): {
disableDecoderInterfaceBoardIc1();
break;
}
case (gpioIds::CS_SUS_3): {
disableDecoderInterfaceBoardIc1();
break;
}
case (gpioIds::CS_SUS_4): {
disableDecoderInterfaceBoardIc1();
break;
}
case (gpioIds::CS_SUS_5): {
disableDecoderInterfaceBoardIc1();
break;
}
case (gpioIds::CS_SUS_6): {
disableDecoderInterfaceBoardIc2();
break;
}
case (gpioIds::CS_SUS_7): {
disableDecoderInterfaceBoardIc2();
break;
}
case (gpioIds::CS_SUS_8): {
disableDecoderInterfaceBoardIc2();
break;
}
case (gpioIds::CS_SUS_9): {
disableDecoderInterfaceBoardIc2();
break;
}
case (gpioIds::CS_SUS_10): {
disableDecoderInterfaceBoardIc2();
break;
}
case (gpioIds::CS_SUS_11): {
disableDecoderInterfaceBoardIc2();
break;
}
case (gpioIds::CS_RW1): {
disableRwDecoder();
break;
}
case (gpioIds::CS_RW2): {
disableRwDecoder();
break;
}
case (gpioIds::CS_RW3): {
disableRwDecoder();
break;
}
case (gpioIds::CS_RW4): {
disableRwDecoder();
break;
}
default:
sif::debug << "spiCsDecoderCallback: Invalid gpio id " << gpioId << std::endl;
}
} else if (value == Levels::LOW) {
switch (gpioId) {
case (gpioIds::RTD_IC_3): {
selectY7();
enableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_4): {
selectY6();
enableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_5): {
selectY5();
enableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_6): {
selectY4();
enableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_7): {
selectY3();
enableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_8): {
selectY2();
enableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_9): {
selectY1();
enableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_10): {
selectY0();
enableDecoderTcsIc1();
break;
}
case (gpioIds::RTD_IC_11): {
selectY7();
enableDecoderTcsIc2();
break;
}
case (gpioIds::RTD_IC_12): {
selectY6();
enableDecoderTcsIc2();
break;
}
case (gpioIds::RTD_IC_13): {
selectY5();
enableDecoderTcsIc2();
break;
}
case (gpioIds::RTD_IC_14): {
selectY4();
enableDecoderTcsIc2();
break;
}
case (gpioIds::RTD_IC_15): {
selectY3();
enableDecoderTcsIc2();
break;
}
case (gpioIds::RTD_IC_16): {
selectY2();
enableDecoderTcsIc2();
break;
}
case (gpioIds::RTD_IC_17): {
selectY1();
enableDecoderTcsIc2();
break;
}
case (gpioIds::RTD_IC_18): {
selectY0();
enableDecoderTcsIc2();
break;
}
case (gpioIds::CS_SUS_0): {
selectY0();
enableDecoderInterfaceBoardIc1();
break;
}
case (gpioIds::CS_SUS_1): {
selectY1();
enableDecoderInterfaceBoardIc1();
break;
}
case (gpioIds::CS_SUS_2): {
selectY2();
enableDecoderInterfaceBoardIc1();
break;
}
case (gpioIds::CS_SUS_3): {
selectY3();
enableDecoderInterfaceBoardIc1();
break;
}
case (gpioIds::CS_SUS_4): {
selectY4();
enableDecoderInterfaceBoardIc1();
break;
}
case (gpioIds::CS_SUS_5): {
selectY5();
enableDecoderInterfaceBoardIc1();
break;
}
case (gpioIds::CS_SUS_6): {
selectY0();
enableDecoderInterfaceBoardIc2();
break;
}
case (gpioIds::CS_SUS_7): {
selectY1();
enableDecoderInterfaceBoardIc2();
break;
}
case (gpioIds::CS_SUS_8): {
selectY2();
enableDecoderInterfaceBoardIc2();
break;
}
case (gpioIds::CS_SUS_9): {
selectY3();
enableDecoderInterfaceBoardIc2();
break;
}
case (gpioIds::CS_SUS_10): {
selectY4();
enableDecoderInterfaceBoardIc2();
break;
}
case (gpioIds::CS_SUS_11): {
selectY5();
enableDecoderInterfaceBoardIc2();
break;
}
case (gpioIds::CS_RW1): {
selectY0();
enableRwDecoder();
break;
}
case (gpioIds::CS_RW2): {
selectY1();
enableRwDecoder();
break;
}
case (gpioIds::CS_RW3): {
selectY2();
enableRwDecoder();
break;
}
case (gpioIds::CS_RW4): {
selectY3();
enableRwDecoder();
break;
}
default:
sif::debug << "spiCsDecoderCallback: Invalid gpio id " << gpioId << std::endl;
}
} else {
sif::debug << "spiCsDecoderCallback: Invalid value. Must be 0 or 1" << std::endl;
}
}
void enableDecoderTcsIc1() {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_0);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_1);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_2);
}
void enableDecoderTcsIc2() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_0);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_1);
}
void enableDecoderInterfaceBoardIc1() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_0);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_2);
}
void enableDecoderInterfaceBoardIc2() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_0);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2);
}
void disableDecoderTcsIc1() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_0);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_1);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_2);
}
void disableDecoderTcsIc2() {
// DO NOT CHANGE THE ORDER HERE
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_0);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_2);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_1);
}
void disableDecoderInterfaceBoardIc1() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_0);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_1);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_2);
}
void disableDecoderInterfaceBoardIc2() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_0);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_1);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_2);
}
void enableRwDecoder() { gpioComInterface->pullHigh(gpioIds::EN_RW_CS); }
void disableRwDecoder() { gpioComInterface->pullLow(gpioIds::EN_RW_CS); }
void selectY0() {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
}
void selectY1() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
}
void selectY2() {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
}
void selectY3() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
}
void selectY4() {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
}
void selectY5() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
}
void selectY6() {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
}
void selectY7() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
}
void disableAllDecoder() {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_2);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_0);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
gpioComInterface->pullLow(gpioIds::EN_RW_CS);
}
} // namespace gpioCallbacks

View File

@ -1,73 +0,0 @@
#ifndef LINUX_GPIO_GPIOCALLBACKS_H_
#define LINUX_GPIO_GPIOCALLBACKS_H_
#include <fsfw_hal/common/gpio/GpioIF.h>
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
namespace gpioCallbacks {
/**
* @brief This function initializes the GPIOs used to control the SN74LVC138APWR decoders on
* the TCS Board and the interface board.
*/
void initSpiCsDecoder(GpioIF* gpioComIF);
/**
* @brief This function implements the decoding to multiply gpios by using the decoder
* chips SN74LVC138APWR on the TCS board and the interface board.
*/
void spiCsDecoderCallback(gpioId_t gpioId, gpio::GpioOperation gpioOp, gpio::Levels value,
void* args);
/**
* @brief This function sets mux bits 1-3 to a state which will only enable the decoder
* on the TCS board which is named to IC1 in the schematic.
*/
void enableDecoderTcsIc1();
/**
* @brief This function sets mux bits 1-3 to a state which will only enable the decoder
* on the TCS board which is named to IC2 in the schematic.
*/
void enableDecoderTcsIc2();
/**
* @brief This function sets mux bits 1-3 to a state which will only enable the decoder
* on the inteface board board which is named to IC21 in the schematic.
*/
void enableDecoderInterfaceBoardIc1();
/**
* @brief This function sets mux bits 1-3 to a state which will only enable the decoder
* on the inteface board board which is named to IC22 in the schematic.
*/
void enableDecoderInterfaceBoardIc2();
void disableDecoderTcsIc1();
void disableDecoderTcsIc2();
void disableDecoderInterfaceBoardIc1();
void disableDecoderInterfaceBoardIc2();
/**
* @brief Enables the reaction wheel chip select decoder (IC3).
*/
void enableRwDecoder();
void disableRwDecoder();
/**
* @brief This function disables all decoder.
*/
void disableAllDecoder();
/** The following functions enable the appropriate channel of the currently enabled decoder */
void selectY0();
void selectY1();
void selectY2();
void selectY3();
void selectY4();
void selectY5();
void selectY6();
void selectY7();
} // namespace gpioCallbacks
#endif /* LINUX_GPIO_GPIOCALLBACKS_H_ */

View File

@ -1,32 +0,0 @@
#include "pcduSwitchCb.h"
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
#include "devices/gpioIds.h"
void pcdu::switchCallback(GOMSPACE::Pdu pdu, uint8_t channel, bool state, void* args) {
LinuxLibgpioIF* gpioComIF = reinterpret_cast<LinuxLibgpioIF*>(args);
if (gpioComIF == nullptr) {
return;
}
if (pdu == GOMSPACE::Pdu::PDU1) {
PDU1::SwitchChannels typedChannel = static_cast<PDU1::SwitchChannels>(channel);
if (typedChannel == PDU1::SwitchChannels::ACS_A_SIDE) {
if (state) {
gpioComIF->pullHigh(gpioIds::GNSS_0_NRESET);
} else {
gpioComIF->pullLow(gpioIds::GNSS_0_NRESET);
}
}
} else if (pdu == GOMSPACE::Pdu::PDU2) {
PDU2::SwitchChannels typedChannel = static_cast<PDU2::SwitchChannels>(channel);
if (typedChannel == PDU2::SwitchChannels::ACS_B_SIDE) {
if (state) {
gpioComIF->pullHigh(gpioIds::GNSS_1_NRESET);
} else {
gpioComIF->pullLow(gpioIds::GNSS_1_NRESET);
}
}
}
}

View File

@ -1,14 +0,0 @@
#ifndef BSP_Q7S_CALLBACKS_PCDUSWITCHCB_H_
#define BSP_Q7S_CALLBACKS_PCDUSWITCHCB_H_
#include <cstdint>
#include "mission/devices/devicedefinitions/GomspaceDefinitions.h"
namespace pcdu {
void switchCallback(GOMSPACE::Pdu pdu, uint8_t channel, bool state, void* args);
}
#endif /* BSP_Q7S_CALLBACKS_PCDUSWITCHCB_H_ */

View File

@ -1,232 +1,237 @@
#include "rwSpiCallback.h"
#include "devices/gpioIds.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw_hal/linux/UnixFileGuard.h"
#include "fsfw_hal/linux/spi/SpiCookie.h"
#include "mission/devices/RwHandler.h"
#include "fsfw_hal/linux/spi/SpiCookie.h"
#include "fsfw_hal/linux/UnixFileGuard.h"
#include "fsfw/serviceinterface/ServiceInterface.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;
ReturnValue_t spiCallback(SpiComIF* comIf, SpiCookie *cookie, const uint8_t *sendData,
size_t sendLen, void* args) {
RwHandler* handler = reinterpret_cast<RwHandler*>(args);
if (handler == nullptr) {
sif::error << "rwSpiCallback::spiCallback: Pointer to handler is invalid" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
uint8_t writeBuffer[2];
uint8_t writeSize = 0;
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;
}
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);
result = mutex->lockMutex(timeoutType, timeoutMs);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::debug << "rwSpiCallback::spiCallback: Failed to lock mutex" << std::endl;
return result;
}
/** 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;
RwHandler* handler = reinterpret_cast<RwHandler*>(args);
if(handler == nullptr) {
sif::error << "rwSpiCallback::spiCallback: Pointer to handler is invalid"
<< std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
}
if (write(fileDescriptor, writeBuffer, writeSize) != static_cast<ssize_t>(writeSize)) {
sif::error << "rwSpiCallback::spiCallback: Write failed!" << std::endl;
closeSpi(gpioId, gpioIF, mutex);
return RwHandler::SPI_WRITE_FAILURE;
}
uint8_t writeBuffer[2];
uint8_t writeSize = 0;
/** 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;
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<ssize_t>(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<ssize_t>(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 at least 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 (idx == 0) {
if (byteRead != FLAG_BYTE) {
sif::error << "Invalid data, expected start marker" << std::endl;
sif::error << "rwSpiCallback::spiCallback: Write failed!" << std::endl;
closeSpi(gpioId, gpioIF, mutex);
return RwHandler::NO_START_MARKER;
}
return RwHandler::SPI_WRITE_FAILURE;
}
if (byteRead != FLAG_BYTE) {
break;
/** 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<ssize_t>(writeSize)) {
sif::error << "rwSpiCallback::spiCallback: Write failed!" << std::endl;
closeSpi(gpioId, gpioIF, mutex);
return RwHandler::SPI_WRITE_FAILURE;
}
idx++;
}
if (idx == 9) {
sif::error << "rwSpiCallback::spiCallback: Empty frame timeout" << std::endl;
closeSpi(gpioId, gpioIF, mutex);
return RwHandler::NO_REPLY;
}
}
/** Sending frame end sign */
writeBuffer[0] = 0x7E;
writeSize = 1;
#if FSFW_HAL_SPI_WIRETAPPING == 1
sif::info << "RW start marker detected" << std::endl;
#endif
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 == FLAG_BYTE) {
/** 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;
if (write(fileDescriptor, writeBuffer, writeSize) != static_cast<ssize_t>(writeSize)) {
sif::error << "rwSpiCallback::spiCallback: Write failed!" << std::endl;
closeSpi(gpioId, gpioIF, mutex);
result = RwHandler::INVALID_SUBSTITUTE;
break;
}
} else {
*(rxBuf + decodedFrameLen) = byteRead;
decodedFrameLen++;
continue;
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);
/**
* 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.
* 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.
*/
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;
}
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;
}
}
result = HasReturnvaluesIF::RETURN_OK;
}
cookie->setTransferSize(decodedFrameLen);
size_t decodedFrameLen = 0;
while(decodedFrameLen < replyBufferSize) {
closeSpi(gpioId, gpioIF, mutex);
/** 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;
}
}
return result;
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->setTransferSize(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;
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;
}
}
if (mutex->unlockMutex() != HasReturnvaluesIF::RETURN_OK) {
sif::error << "rwSpiCallback::closeSpi: Failed to unlock mutex" << std::endl;
;
}
}
} // namespace rwSpiCallback
}

View File

@ -2,14 +2,12 @@
#define BSP_Q7S_RW_SPI_CALLBACK_H_
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "fsfw_hal/common/gpio/GpioCookie.h"
#include "fsfw_hal/linux/spi/SpiComIF.h"
#include "fsfw_hal/common/gpio/GpioCookie.h"
namespace rwSpiCallback {
//! This is the end and start marker of the frame datalinklayer
static constexpr uint8_t FLAG_BYTE = 0x7E;
/**
* @brief This is the callback function to send commands to the nano avionics reaction wheels and
* receive the replies.
@ -30,8 +28,8 @@ static constexpr uint8_t FLAG_BYTE = 0x7E;
* 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);
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
@ -42,5 +40,5 @@ ReturnValue_t spiCallback(SpiComIF* comIf, SpiCookie* cookie, const uint8_t* sen
*/
void closeSpi(gpioId_t gpioId, GpioIF* gpioIF, MutexIF* mutex);
} // namespace rwSpiCallback
}
#endif /* BSP_Q7S_RW_SPI_CALLBACK_H_ */

View File

@ -1,4 +1,4 @@
target_sources(${OBSW_NAME} PRIVATE
target_sources(${TARGET_NAME} PRIVATE
)

View File

@ -1,10 +1,6 @@
target_sources(${OBSW_NAME} PRIVATE
target_sources(${TARGET_NAME} PRIVATE
CoreController.cpp
obsw.cpp
InitMission.cpp
ObjectFactory.cpp
)
target_sources(${SIMPLE_OBSW_NAME} PRIVATE
InitMission.cpp
)

File diff suppressed because it is too large Load Diff

View File

@ -2,224 +2,183 @@
#define BSP_Q7S_CORE_CORECONTROLLER_H_
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
#include <libxiphos.h>
#include <cstddef>
#include "bsp_q7s/memory/SdCardManager.h"
#include "events/subsystemIdRanges.h"
#include "fsfw/controller/ExtendedControllerBase.h"
#include "bsp_q7s/memory/SdCardManager.h"
#include "events/subsystemIdRanges.h"
class Timer;
class SdCardManager;
namespace xsc {
class CoreController: public ExtendedControllerBase {
public:
enum Chip: uint8_t {
CHIP_0,
CHIP_1,
NO_CHIP,
SELF_CHIP,
ALL_CHIP
};
enum Chip : int { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP };
enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY };
enum Copy: uint8_t {
COPY_0,
COPY_1,
NO_COPY,
SELF_COPY,
ALL_COPY
};
} // namespace xsc
static constexpr char CHIP_PROT_SCRIPT[] = "/home/root/scripts/get-chip-prot-status.sh";
static constexpr char CHIP_STATE_FILE[] = "/tmp/chip_prot_status.txt";
static constexpr char CURR_COPY_FILE[] = "/tmp/curr_copy.txt";
static constexpr char VERSION_FILE[] = "/conf/sd_status";
struct RebootFile {
static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10;
static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0;
static constexpr ActionId_t REBOOT_OBC = 32;
static constexpr ActionId_t MOUNT_OTHER_COPY = 33;
bool enabled = true;
size_t maxCount = DEFAULT_MAX_BOOT_CNT;
uint32_t img00Cnt = 0;
uint32_t img01Cnt = 0;
uint32_t img10Cnt = 0;
uint32_t img11Cnt = 0;
bool img00Lock = false;
bool img01Lock = false;
bool img10Lock = false;
bool img11Lock = false;
uint32_t* relevantBootCnt = &img00Cnt;
bool bootFlag = false;
xsc::Chip lastChip = xsc::Chip::CHIP_0;
xsc::Copy lastCopy = xsc::Copy::COPY_0;
xsc::Chip mechanismNextChip = xsc::Chip::NO_CHIP;
xsc::Copy mechanismNextCopy = xsc::Copy::NO_COPY;
};
class CoreController : public ExtendedControllerBase {
public:
static xsc::Chip CURRENT_CHIP;
static xsc::Copy CURRENT_COPY;
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CORE;
static constexpr char CHIP_PROT_SCRIPT[] = "/home/root/scripts/get-chip-prot-status.sh";
static constexpr char CHIP_STATE_FILE[] = "/tmp/chip_prot_status.txt";
static constexpr char CURR_COPY_FILE[] = "/tmp/curr_copy.txt";
static constexpr char CONF_FOLDER[] = "conf";
static constexpr char VERSION_FILE_NAME[] = "version.txt";
static constexpr char REBOOT_FILE_NAME[] = "reboot.txt";
const std::string VERSION_FILE =
"/" + std::string(CONF_FOLDER) + "/" + std::string(VERSION_FILE_NAME);
const std::string REBOOT_FILE =
"/" + std::string(CONF_FOLDER) + "/" + std::string(REBOOT_FILE_NAME);
static constexpr Event ALLOC_FAILURE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM);
static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0;
static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5;
static constexpr ActionId_t RESET_REBOOT_COUNTERS = 6;
static constexpr ActionId_t SWITCH_IMG_LOCK = 7;
static constexpr ActionId_t SET_MAX_REBOOT_CNT = 8;
static constexpr ActionId_t REBOOT_OBC = 32;
static constexpr ActionId_t MOUNT_OTHER_COPY = 33;
CoreController(object_id_t objectId);
virtual~ CoreController();
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CORE;
ReturnValue_t initialize() override;
static constexpr Event ALLOC_FAILURE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM);
//! [EXPORT] : [COMMENT] Software reboot occured. Can also be a systemd reboot.
//! P1: Current Chip, P2: Current Copy
static constexpr Event REBOOT_SW = event::makeEvent(SUBSYSTEM_ID, 1, severity::MEDIUM);
//! [EXPORT] : [COMMENT] The reboot mechanism was triggered.
//! P1: First 16 bits: Last Chip, Last 16 bits: Last Copy,
//! P2: Each byte is the respective reboot count for the slots
static constexpr Event REBOOT_MECHANISM_TRIGGERED =
event::makeEvent(SUBSYSTEM_ID, 2, severity::MEDIUM);
//! Trying to find a way how to determine that the reboot came from ProASIC3 or PCDU..
static constexpr Event REBOOT_HW = event::makeEvent(SUBSYSTEM_ID, 3, severity::MEDIUM);
ReturnValue_t initializeAfterTaskCreation() override;
CoreController(object_id_t objectId);
virtual ~CoreController();
ReturnValue_t executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t *data, size_t size) override;
ReturnValue_t initialize() override;
ReturnValue_t handleCommandMessage(CommandMessage *message) override;
void performControlOperation() override;
ReturnValue_t initializeAfterTaskCreation() override;
/**
* Generate a file containing the chip lock/unlock states inside /tmp/chip_prot_status.txt
* @return
*/
static ReturnValue_t generateChipStateFile();
static ReturnValue_t incrementAllocationFailureCount();
static void getCurrentBootCopy(Chip& chip, Copy& copy);
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override;
ReturnValue_t updateProtInfo(bool regenerateChipStateFile = true);
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
void performControlOperation() override;
/**
* Checks whether the target chip and copy are write protected and protect set them to a target
* state where applicable.
* @param targetChip
* @param targetCopy
* @param protect Target state
* @param protOperationPerformed [out] Can be used to determine whether any operation
* was performed
* @param updateProtFile Specify whether the protection info file is updated
* @return
*/
ReturnValue_t setBootCopyProtection(Chip targetChip, Copy targetCopy,
bool protect, bool& protOperationPerformed, bool updateProtFile = true);
/**
* Generate a file containing the chip lock/unlock states inside /tmp/chip_prot_status.txt
* @return
*/
static ReturnValue_t generateChipStateFile();
static ReturnValue_t incrementAllocationFailureCount();
static void getCurrentBootCopy(xsc::Chip& chip, xsc::Copy& copy);
bool sdInitFinished() const;
ReturnValue_t updateProtInfo(bool regenerateChipStateFile = true);
private:
static Chip CURRENT_CHIP;
static Copy CURRENT_COPY;
/**
* Checks whether the target chip and copy are write protected and protect set them to a target
* state where applicable.
* @param targetChip
* @param targetCopy
* @param protect Target state
* @param protOperationPerformed [out] Can be used to determine whether any operation
* was performed
* @param updateProtFile Specify whether the protection info file is updated
* @return
*/
ReturnValue_t setBootCopyProtection(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect,
bool& protOperationPerformed, bool updateProtFile = true);
// Designated value for rechecking FIFO open
static constexpr int RETRY_FIFO_OPEN = -2;
int watchdogFifoFd = 0;
bool sdInitFinished() const;
// States for SD state machine, which is used in non-blocking mode
enum class SdStates {
NONE,
START,
GET_INFO,
SET_STATE_SELF,
MOUNT_SELF,
// Determine operations for other SD card, depending on redundancy configuration
DETERMINE_OTHER,
SET_STATE_OTHER,
// Mount or unmount other
MOUNT_UNMOUNT_OTHER,
// Skip period because the shell command used to generate the info file sometimes is
// missing the last performed operation if executed too early
SKIP_CYCLE_BEFORE_INFO_UPDATE,
UPDATE_INFO,
// SD initialization done
IDLE,
// Used if SD switches or mount commands are issued via telecommand
SET_STATE_FROM_COMMAND,
};
static constexpr bool BLOCKING_SD_INIT = false;
private:
// Designated value for rechecking FIFO open
static constexpr int RETRY_FIFO_OPEN = -2;
int watchdogFifoFd = 0;
SdCardManager* sdcMan = nullptr;
// States for SD state machine, which is used in non-blocking mode
enum class SdStates {
NONE,
START,
GET_INFO,
SET_STATE_SELF,
MOUNT_SELF,
// Determine operations for other SD card, depending on redundancy configuration
DETERMINE_OTHER,
SET_STATE_OTHER,
// Mount or unmount other
MOUNT_UNMOUNT_OTHER,
// Skip period because the shell command used to generate the info file sometimes is
// missing the last performed operation if executed too early
SKIP_CYCLE_BEFORE_INFO_UPDATE,
UPDATE_INFO,
// SD initialization done
IDLE,
// Used if SD switches or mount commands are issued via telecommand
SET_STATE_FROM_COMMAND,
};
static constexpr bool BLOCKING_SD_INIT = false;
struct SdInfo {
sd::SdCard pref = sd::SdCard::NONE;
sd::SdState prefState = sd::SdState::OFF;
sd::SdCard other = sd::SdCard::NONE;
sd::SdState otherState = sd::SdState::OFF;
std::string prefChar = "0";
std::string otherChar = "1";
SdStates state = SdStates::START;
// Used to track whether a command was executed
bool commandExecuted = true;
bool initFinished = false;
SdCardManager::SdStatePair currentState;
uint16_t cycleCount = 0;
// These two flags are related to external commanding
bool commandIssued = false;
bool commandFinished = false;
sd::SdState currentlyCommandedState = sd::SdState::OFF;
sd::SdCard commandedCard = sd::SdCard::NONE;
sd::SdState commandedState = sd::SdState::OFF;
};
SdInfo sdInfo;
SdCardManager* sdcMan = nullptr;
/**
* Index 0: Chip 0 Copy 0
* Index 1: Chip 0 Copy 1
* Index 2: Chip 1 Copy 0
* Index 3: Chip 1 Copy 1
*/
std::array<bool, 4> protArray;
PeriodicOperationDivider opDivider;
struct SdInfo {
sd::SdCard pref = sd::SdCard::NONE;
sd::SdState prefState = sd::SdState::OFF;
sd::SdCard other = sd::SdCard::NONE;
sd::SdState otherState = sd::SdState::OFF;
std::string prefChar = "0";
std::string otherChar = "1";
SdStates state = SdStates::START;
// Used to track whether a command was executed
bool commandExecuted = true;
bool initFinished = false;
SdCardManager::SdStatePair currentState;
uint16_t cycleCount = 0;
// These two flags are related to external commanding
bool commandIssued = false;
bool commandFinished = false;
sd::SdState currentlyCommandedState = sd::SdState::OFF;
sd::SdCard commandedCard = sd::SdCard::NONE;
sd::SdState commandedState = sd::SdState::OFF;
} sdInfo;
RebootFile rebootFile = {};
bool doPerformMountedSdCardOps = true;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode);
/**
* Index 0: Chip 0 Copy 0
* Index 1: Chip 0 Copy 1
* Index 2: Chip 1 Copy 0
* Index 3: Chip 1 Copy 1
*/
std::array<bool, 4> protArray;
PeriodicOperationDivider opDivider;
ReturnValue_t initVersionFile();
ReturnValue_t initBootCopy();
ReturnValue_t initWatchdogFifo();
ReturnValue_t initSdCardBlocking();
void initPrint();
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t* msToReachTheMode);
void performMountedSdCardOperations();
ReturnValue_t initVersionFile();
ReturnValue_t initBootCopy();
ReturnValue_t initWatchdogFifo();
ReturnValue_t initSdCardBlocking();
void initPrint();
ReturnValue_t sdStateMachine();
void updateSdInfoOther();
ReturnValue_t sdCardSetup(sd::SdCard sdCard, sd::SdState targetState, std::string sdChar,
bool printOutput = true);
ReturnValue_t sdColdRedundantBlockingInit();
void currentStateSetter(sd::SdCard sdCard, sd::SdState newState);
void determinePreferredSdCard();
void executeNextExternalSdCommand();
void checkExternalSdCommandStatus();
ReturnValue_t sdStateMachine();
void updateSdInfoOther();
ReturnValue_t sdCardSetup(sd::SdCard sdCard, sd::SdState targetState, std::string sdChar,
bool printOutput = true);
ReturnValue_t sdColdRedundantBlockingInit();
ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t *data, size_t size);
ReturnValue_t actionPerformReboot(const uint8_t *data, size_t size);
void currentStateSetter(sd::SdCard sdCard, sd::SdState newState);
void determinePreferredSdCard();
void executeNextExternalSdCommand();
void checkExternalSdCommandStatus();
void performRebootFileHandling(bool recreateFile);
void performWatchdogControlOperation();
ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size);
ReturnValue_t actionPerformReboot(const uint8_t* data, size_t size);
void performWatchdogControlOperation();
ReturnValue_t handleProtInfoUpdateLine(std::string nextLine);
int handleBootCopyProtAtIndex(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect,
bool& protOperationPerformed, bool selfChip, bool selfCopy,
bool allChips, bool allCopies, uint8_t arrIdx);
void determineAndExecuteReboot(RebootFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
xsc::Copy& tgtCopy);
void resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy);
void setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy);
bool parseRebootFile(std::string path, RebootFile& file);
void rewriteRebootFile(RebootFile file);
ReturnValue_t handleProtInfoUpdateLine(std::string nextLine);
int handleBootCopyProtAtIndex(Chip targetChip, Copy targetCopy, bool protect,
bool &protOperationPerformed, bool selfChip, bool selfCopy, bool allChips,
bool allCopies, uint8_t arrIdx);
};
#endif /* BSP_Q7S_CORE_CORECONTROLLER_H_ */

View File

@ -1,27 +1,28 @@
#include "InitMission.h"
#include <iostream>
#include <vector>
#include "OBSWConfig.h"
#include "ObjectFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/objectmanager/ObjectManagerIF.h"
#include "OBSWConfig.h"
#include "pollingsequence/pollingSequenceFactory.h"
#include "mission/utility/InitMission.h"
#include "fsfw/platform.h"
#include "fsfw/objectmanager/ObjectManagerIF.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "fsfw/serviceinterface/ServiceInterfaceStream.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/tasks/FixedTimeslotTaskIF.h"
#include "fsfw/tasks/PeriodicTaskIF.h"
#include "fsfw/tasks/TaskFactory.h"
#include "mission/utility/InitMission.h"
#include "pollingsequence/pollingSequenceFactory.h"
#include <iostream>
#include <vector>
/* This is configured for linux without CR */
#ifdef PLATFORM_UNIX
ServiceInterfaceStream sif::debug("DEBUG");
ServiceInterfaceStream sif::info("INFO");
ServiceInterfaceStream sif::warning("WARNING");
ServiceInterfaceStream sif::error("ERROR");
ServiceInterfaceStream sif::error("ERROR", false, false, true);
#else
ServiceInterfaceStream sif::debug("DEBUG", true);
ServiceInterfaceStream sif::info("INFO", true);
@ -29,365 +30,288 @@ ServiceInterfaceStream sif::warning("WARNING", true);
ServiceInterfaceStream sif::error("ERROR", true, false, true);
#endif
ObjectManagerIF* objectManager = nullptr;
ObjectManagerIF *objectManager = nullptr;
void initmission::initMission() {
sif::info << "Building global objects.." << std::endl;
/* Instantiate global object manager and also create all objects */
ObjectManager::instance()->setObjectFactoryFunction(ObjectFactory::produce, nullptr);
sif::info << "Initializing all objects.." << std::endl;
ObjectManager::instance()->initialize();
/* This function creates and starts all tasks */
initTasks();
sif::info << "Building global objects.." << std::endl;
/* Instantiate global object manager and also create all objects */
ObjectManager::instance()->setObjectFactoryFunction(ObjectFactory::produce, nullptr);
sif::info << "Initializing all objects.." << std::endl;
ObjectManager::instance()->initialize();
/* This function creates and starts all tasks */
initTasks();
}
void initmission::initTasks() {
TaskFactory* factory = TaskFactory::instance();
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if (factory == nullptr) {
/* Should never happen ! */
return;
}
TaskFactory* factory = TaskFactory::instance();
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if(factory == nullptr) {
/* Should never happen ! */
return;
}
#if OBSW_PRINT_MISSED_DEADLINES == 1
void (*missedDeadlineFunc)(void) = TaskFactory::printMissedDeadline;
void (*missedDeadlineFunc) (void) = TaskFactory::printMissedDeadline;
#else
void (*missedDeadlineFunc)(void) = nullptr;
void (*missedDeadlineFunc) (void) = nullptr;
#endif
#if BOARD_TE0720 == 0
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);
}
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);
}
#endif
/* TMTC Distribution */
PeriodicTaskIF* tmTcDistributor = factory->createPeriodicTask(
"DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmTcDistributor->addComponent(objects::CCSDS_PACKET_DISTRIBUTOR);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("CCSDS_DISTRIB", objects::CCSDS_PACKET_DISTRIBUTOR);
}
result = tmTcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_PACKET_DISTRIB", objects::PUS_PACKET_DISTRIBUTOR);
}
result = tmTcDistributor->addComponent(objects::TM_FUNNEL);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("TM_FUNNEL", objects::TM_FUNNEL);
}
/* TMTC Distribution */
PeriodicTaskIF* tmTcDistributor = factory->createPeriodicTask(
"DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmTcDistributor->addComponent(objects::CCSDS_PACKET_DISTRIBUTOR);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("CCSDS_DISTRIB", objects::CCSDS_PACKET_DISTRIBUTOR);
}
result = tmTcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_PACKET_DISTRIB", objects::PUS_PACKET_DISTRIBUTOR);
}
result = tmTcDistributor->addComponent(objects::TM_FUNNEL);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("TM_FUNNEL", objects::TM_FUNNEL);
}
#if OBSW_ADD_TCPIP_BRIDGE == 1
// TMTC bridge
PeriodicTaskIF* tmtcBridgeTask = factory->createPeriodicTask(
"TCPIP_TMTC_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmtcBridgeTask->addComponent(objects::TMTC_BRIDGE);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("TMTC_BRIDGE", objects::TMTC_BRIDGE);
}
PeriodicTaskIF* tmtcPollingTask = factory->createPeriodicTask(
"TMTC_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = tmtcPollingTask->addComponent(objects::TMTC_POLLING_TASK);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("UDP_POLLING", objects::TMTC_POLLING_TASK);
}
#endif
#if OBSW_USE_CCSDS_IP_CORE == 1
PeriodicTaskIF* ccsdsHandlerTask = factory->createPeriodicTask(
"CCSDS_HANDLER", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = ccsdsHandlerTask->addComponent(objects::CCSDS_HANDLER);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("CCSDS Handler", objects::CCSDS_HANDLER);
}
// Minimal distance between two received TCs amounts to 0.6 seconds
// If a command has not been read before the next one arrives, the old command will be
// overwritten by the PDEC.
PeriodicTaskIF* pdecHandlerTask = factory->createPeriodicTask(
"PDEC_HANDLER", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, missedDeadlineFunc);
result = pdecHandlerTask->addComponent(objects::PDEC_HANDLER);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PDEC Handler", objects::PDEC_HANDLER);
}
#endif /* OBSW_USE_CCSDS_IP_CORE == 1 */
#if OBSW_ADD_ACS_HANDLERS == 1
PeriodicTaskIF* acsCtrl = factory->createPeriodicTask(
"ACS_CTRL", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc);
result = acsCtrl->addComponent(objects::GPS_CONTROLLER);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("ACS_CTRL", objects::GPS_CONTROLLER);
}
#endif /* OBSW_ADD_ACS_HANDLERS */
#if BOARD_TE0720 == 0
// FS task, task interval does not matter because it runs in permanent loop, priority low
// because it is a non-essential background task
PeriodicTaskIF* fsTask = factory->createPeriodicTask(
"FILE_SYSTEM_TASK", 25, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc);
result = fsTask->addComponent(objects::FILE_SYSTEM_HANDLER);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("FILE_SYSTEM_TASK", objects::FILE_SYSTEM_HANDLER);
}
#if OBSW_ADD_STAR_TRACKER == 1
PeriodicTaskIF* strHelperTask = factory->createPeriodicTask(
"STR_HELPER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = strHelperTask->addComponent(objects::STR_HELPER);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("STR_HELPER", objects::STR_HELPER);
}
#endif /* OBSW_ADD_STAR_TRACKER == 1 */
/* UDP bridge */
PeriodicTaskIF* tmtcBridgeTask = factory->createPeriodicTask(
"UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmtcBridgeTask->addComponent(objects::TMTC_BRIDGE);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("UDP_BRIDGE", objects::TMTC_BRIDGE);
}
PeriodicTaskIF* tmtcPollingTask = factory->createPeriodicTask(
"UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = tmtcPollingTask->addComponent(objects::TMTC_POLLING_TASK);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("UDP_POLLING", objects::TMTC_POLLING_TASK);
}
# if BOARD_TE0720 == 0
// FS task, task interval does not matter because it runs in permanent loop, priority low
// because it is a non-essential background task
PeriodicTaskIF* fsTask = factory->createPeriodicTask(
"FILE_SYSTEM_TASK", 25, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc);
result = fsTask->addComponent(objects::FILE_SYSTEM_HANDLER);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("FILE_SYSTEM_TASK", objects::FILE_SYSTEM_HANDLER);
}
#endif /* BOARD_TE0720 */
#if OBSW_TEST_CCSDS_BRIDGE == 1
PeriodicTaskIF* ptmeTestTask = factory->createPeriodicTask(
"PTME_TEST", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = ptmeTestTask->addComponent(objects::CCSDS_IP_CORE_BRIDGE);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PTME_TEST", objects::CCSDS_IP_CORE_BRIDGE);
}
#endif
std::vector<PeriodicTaskIF*> pusTasks;
createPusTasks(*factory, missedDeadlineFunc, pusTasks);
std::vector<PeriodicTaskIF*> pstTasks;
createPstTasks(*factory, missedDeadlineFunc, pstTasks);
#if OBSW_ADD_TEST_CODE == 1
std::vector<PeriodicTaskIF*> testTasks;
createTestTasks(*factory, missedDeadlineFunc, testTasks);
#endif
auto taskStarter = [](std::vector<PeriodicTaskIF*>& taskVector, std::string name) {
for (const auto& task : taskVector) {
if (task != nullptr) {
task->startTask();
} else {
sif::error << "Task in vector " << name << " is invalid!" << std::endl;
}
PeriodicTaskIF* ptmeTestTask = factory->createPeriodicTask(
"PTME_TEST", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = ptmeTestTask->addComponent(objects::CCSDS_IP_CORE_BRIDGE);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PTME_TEST", objects::CCSDS_IP_CORE_BRIDGE);
}
};
sif::info << "Starting tasks.." << std::endl;
tmTcDistributor->startTask();
#if OBSW_ADD_TCPIP_BRIDGE == 1
tmtcBridgeTask->startTask();
tmtcPollingTask->startTask();
#endif
#if OBSW_USE_CCSDS_IP_CORE == 1
ccsdsHandlerTask->startTask();
pdecHandlerTask->startTask();
#endif /* OBSW_USE_CCSDS_IP_CORE == 1 */
std::vector<PeriodicTaskIF*> pusTasks;
createPusTasks(*factory, missedDeadlineFunc, pusTasks);
std::vector<PeriodicTaskIF*> pstTasks;
createPstTasks(*factory, missedDeadlineFunc, pstTasks);
#if BOARD_TE0720 == 0
coreController->startTask();
#endif
taskStarter(pstTasks, "PST task vector");
taskStarter(pusTasks, "PUS task vector");
#if OBSW_ADD_TEST_CODE == 1
taskStarter(testTasks, "Test task vector");
std::vector<PeriodicTaskIF*> testTasks;
createTestTasks(*factory, missedDeadlineFunc, testTasks);
#endif
auto taskStarter = [](std::vector<PeriodicTaskIF*>& taskVector, std::string name) {
for(const auto& task: taskVector) {
if(task != nullptr) {
task->startTask();
}
else {
sif::error << "Task in vector " << name << " is invalid!" << std::endl;
}
}
};
sif::info << "Starting tasks.." << std::endl;
tmTcDistributor->startTask();
tmtcBridgeTask->startTask();
tmtcPollingTask->startTask();
#if BOARD_TE0720 == 0
coreController->startTask();
#endif
taskStarter(pstTasks, "PST task vector");
taskStarter(pusTasks, "PUS task vector");
#if OBSW_ADD_TEST_CODE == 1
taskStarter(testTasks, "Test task vector");
#endif
#if OBSW_TEST_CCSDS_BRIDGE == 1
ptmeTestTask->startTask();
ptmeTestTask->startTask();
#endif
#if BOARD_TE0720 == 0
fsTask->startTask();
#if OBSW_ADD_STAR_TRACKER == 1
strHelperTask > startTask();
#endif /* OBSW_ADD_STAR_TRACKER == 1 */
fsTask->startTask();
#endif
#if OBSW_ADD_ACS_HANDLERS == 1
acsCtrl->startTask();
#endif
sif::info << "Tasks started.." << std::endl;
sif::info << "Tasks started.." << std::endl;
}
void initmission::createPstTasks(TaskFactory& factory,
TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
TaskDeadlineMissedFunction missedDeadlineFunc, std::vector<PeriodicTaskIF*> &taskVec) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
#if BOARD_TE0720 == 0
/* Polling Sequence Table Default */
/* Polling Sequence Table Default */
#if OBSW_ADD_SPI_TEST_CODE == 0
FixedTimeslotTaskIF* spiPst = factory.createFixedTimeslotTask(
"PST_TASK_DEFAULT", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.5, missedDeadlineFunc);
result = pst::pstSpi(spiPst);
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != FixedTimeslotTaskIF::SLOT_LIST_EMPTY) {
sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl;
FixedTimeslotTaskIF* spiPst = factory.createFixedTimeslotTask(
"PST_TASK_DEFAULT", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0,
missedDeadlineFunc);
result = pst::pstSpi(spiPst);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl;
}
} else {
taskVec.push_back(spiPst);
}
#endif
FixedTimeslotTaskIF* uartPst = factory.createFixedTimeslotTask(
"UART_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.2, missedDeadlineFunc);
result = pst::pstUart(uartPst);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl;
}
taskVec.push_back(uartPst);
FixedTimeslotTaskIF* gpioPst = factory.createFixedTimeslotTask(
"GPIO_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.2, missedDeadlineFunc);
result = pst::pstGpio(gpioPst);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl;
}
taskVec.push_back(gpioPst);
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;
}
taskVec.push_back(uartPst);
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;
}
taskVec.push_back(gpioPst);
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;
}
#if OBSW_ADD_I2C_TEST_CODE == 0
FixedTimeslotTaskIF* i2cPst = factory.createFixedTimeslotTask(
"I2C_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.2, missedDeadlineFunc);
result = pst::pstI2c(i2cPst);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl;
}
taskVec.push_back(i2cPst);
#endif
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;
}
taskVec.push_back(gomSpacePstTask);
#else /* BOARD_TE7020 == 0 */
FixedTimeslotTaskIF* pollingSequenceTaskTE0720 = factory.createFixedTimeslotTask(
"PST_TASK_TE0720", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE * 8, 3.0, missedDeadlineFunc);
result = pst::pollingSequenceTE0720(pollingSequenceTaskTE0720);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::initTasks: Creating TE0720 PST failed!" << std::endl;
}
taskVec.push_back(pollingSequenceTaskTE0720);
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;
}
taskVec.push_back(gomSpacePstTask);
#else /* BOARD_TE7020 == 0 */
FixedTimeslotTaskIF * pollingSequenceTaskTE0720 = factory.createFixedTimeslotTask(
"PST_TASK_TE0720", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE * 8, 3.0,
missedDeadlineFunc);
result = pst::pollingSequenceTE0720(pollingSequenceTaskTE0720);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::initTasks: Creating TE0720 PST failed!" << std::endl;
}
taskVec.push_back(pollingSequenceTaskTE0720);
#endif /* BOARD_TE7020 == 1 */
}
void initmission::createPusTasks(TaskFactory& factory,
TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
/* PUS Services */
PeriodicTaskIF* pusVerification = factory.createPeriodicTask(
"PUS_VERIF", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_VERIF", objects::PUS_SERVICE_1_VERIFICATION);
}
taskVec.push_back(pusVerification);
void initmission::createPusTasks(TaskFactory &factory,
TaskDeadlineMissedFunction missedDeadlineFunc, std::vector<PeriodicTaskIF*> &taskVec) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
/* PUS Services */
PeriodicTaskIF* pusVerification = factory.createPeriodicTask(
"PUS_VERIF", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_VERIF", objects::PUS_SERVICE_1_VERIFICATION);
}
taskVec.push_back(pusVerification);
PeriodicTaskIF* pusEvents = factory.createPeriodicTask(
"PUS_EVENTS", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
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);
}
taskVec.push_back(pusEvents);
PeriodicTaskIF* pusEvents = factory.createPeriodicTask(
"PUS_EVENTS", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
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);
}
taskVec.push_back(pusEvents);
PeriodicTaskIF* pusHighPrio = factory.createPeriodicTask(
"PUS_HIGH_PRIO", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
}
result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_9", objects::PUS_SERVICE_9_TIME_MGMT);
}
taskVec.push_back(pusHighPrio);
PeriodicTaskIF* pusHighPrio = factory.createPeriodicTask(
"PUS_HIGH_PRIO", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
}
result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_9", objects::PUS_SERVICE_9_TIME_MGMT);
}
taskVec.push_back(pusHighPrio);
PeriodicTaskIF* pusMedPrio = factory.createPeriodicTask(
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_8", objects::PUS_SERVICE_8_FUNCTION_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_3_HOUSEKEEPING);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_200", objects::PUS_SERVICE_200_MODE_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_20_PARAMETERS);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_20", objects::PUS_SERVICE_20_PARAMETERS);
}
taskVec.push_back(pusMedPrio);
PeriodicTaskIF* pusMedPrio = factory.createPeriodicTask(
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_8", objects::PUS_SERVICE_8_FUNCTION_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_3_HOUSEKEEPING);
if(result!=HasReturnvaluesIF::RETURN_OK){
sif::error << "Object add component failed" << std::endl;
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_200", objects::PUS_SERVICE_200_MODE_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_20_PARAMETERS);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_20", objects::PUS_SERVICE_20_PARAMETERS);
}
taskVec.push_back(pusMedPrio);
PeriodicTaskIF* pusLowPrio = factory.createPeriodicTask(
"PUS_LOW_PRIO", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.6, missedDeadlineFunc);
result = pusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
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);
}
taskVec.push_back(pusLowPrio);
PeriodicTaskIF* pusLowPrio = factory.createPeriodicTask(
"PUS_LOW_PRIO", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.6, missedDeadlineFunc);
result = pusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
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);
}
taskVec.push_back(pusLowPrio);
}
void initmission::createTestTasks(TaskFactory& factory,
TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec) {
#if OBSW_ADD_TEST_TASK == 1 && OBSW_ADD_TEST_CODE == 1
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
static_cast<void>(result); // supress warning in case it is not used
PeriodicTaskIF* testTask = factory.createPeriodicTask(
"TEST_TASK", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1, missedDeadlineFunc);
result = testTask->addComponent(objects::TEST_TASK);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("TEST_TASK", objects::TEST_TASK);
}
void initmission::createTestTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec) {
#if OBSW_ADD_TEST_TASK == 1 || OBSW_ADD_SPI_TEST_CODE == 1 || (BOARD_TE0720 == 1 && OBSW_TEST_LIBGPIOD == 1)
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
#endif
PeriodicTaskIF* testTask = factory.createPeriodicTask(
"TEST_TASK", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1, missedDeadlineFunc);
#if OBSW_ADD_TEST_TASK == 1
result = testTask->addComponent(objects::TEST_TASK);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("TEST_TASK", objects::TEST_TASK);
}
#endif /* OBSW_ADD_TEST_TASK == 1 */
#if OBSW_ADD_SPI_TEST_CODE == 1
result = testTask->addComponent(objects::SPI_TEST);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("SPI_TEST", objects::SPI_TEST);
}
result = testTask->addComponent(objects::SPI_TEST);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("SPI_TEST", objects::SPI_TEST);
}
#endif
#if OBSW_ADD_I2C_TEST_CODE == 1
result = testTask->addComponent(objects::I2C_TEST);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("I2C_TEST", objects::I2C_TEST);
}
#endif
#if OBSW_ADD_UART_TEST_CODE == 1
result = testTask->addComponent(objects::UART_TEST);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("UART_TEST", objects::UART_TEST);
}
#endif
#if BOARD_TE0720 == 1 && OBSW_TEST_LIBGPIOD == 1
result = testTask->addComponent(objects::LIBGPIOD_TEST);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("GPIOD_TEST", objects::LIBGPIOD_TEST);
}
result = testTask->addComponent(objects::LIBGPIOD_TEST);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("GPIOD_TEST", objects::LIBGPIOD_TEST);
}
#endif /* BOARD_TE0720 == 1 && OBSW_TEST_LIBGPIOD == 1 */
taskVec.push_back(testTask);
#endif // OBSW_ADD_TEST_TASK == 1 && OBSW_ADD_TEST_CODE == 1
taskVec.push_back(testTask);
}

View File

@ -1,9 +1,8 @@
#ifndef BSP_Q7S_INITMISSION_H_
#define BSP_Q7S_INITMISSION_H_
#include <vector>
#include "fsfw/tasks/Typedef.h"
#include <vector>
class PeriodicTaskIF;
class TaskFactory;
@ -13,11 +12,11 @@ void initMission();
void initTasks();
void createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec);
std::vector<PeriodicTaskIF*>& taskVec);
void createPusTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec);
std::vector<PeriodicTaskIF*>& taskVec);
void createTestTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec);
}; // namespace initmission
std::vector<PeriodicTaskIF*>& taskVec);
};
#endif /* BSP_Q7S_INITMISSION_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,6 @@
class LinuxLibgpioIF;
class UartComIF;
class SpiComIF;
class I2cComIF;
namespace ObjectFactory {
@ -12,11 +11,9 @@ void setStatics();
void produce(void* args);
void createCommunicationInterfaces(LinuxLibgpioIF** gpioComIF, UartComIF** uartComIF,
SpiComIF** spiComIF, I2cComIF** i2cComIF);
void createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF* spiComIF);
SpiComIF** spiComIF);
void createTmpComponents();
void createPcduComponents(LinuxLibgpioIF* gpioComIF);
void createPcduComponents();
void createRadSensorComponent(LinuxLibgpioIF* gpioComIF);
void createSunSensorComponents(LinuxLibgpioIF* gpioComIF, SpiComIF* spiComIF);
void createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComIF* uartComIF);
@ -25,9 +22,8 @@ void createSolarArrayDeploymentComponents();
void createSyrlinksComponents();
void createRtdComponents(LinuxLibgpioIF* gpioComIF);
void createReactionWheelComponents(LinuxLibgpioIF* gpioComIF);
void createCcsdsComponents(LinuxLibgpioIF* gpioComIF);
void createTestComponents(LinuxLibgpioIF* gpioComIF);
}; // namespace ObjectFactory
};
#endif /* BSP_Q7S_OBJECTFACTORY_H_ */

View File

@ -1,5 +1,8 @@
#include "ParameterHandler.h"
ParameterHandler::ParameterHandler(std::string mountPrefix) : mountPrefix(mountPrefix) {}
ParameterHandler::ParameterHandler(std::string mountPrefix): mountPrefix(mountPrefix) {
}
void ParameterHandler::setMountPrefix(std::string prefix) { mountPrefix = prefix; }
void ParameterHandler::setMountPrefix(std::string prefix) {
mountPrefix = prefix;
}

View File

@ -4,17 +4,19 @@
#include <nlohmann/json.hpp>
#include <string>
class ParameterHandler {
public:
ParameterHandler(std::string mountPrefix);
public:
ParameterHandler(std::string mountPrefix);
void setMountPrefix(std::string prefix);
void setMountPrefix(std::string prefix);
void setUpDummyParameter();
private:
std::string mountPrefix;
DummyParameter dummyParam;
void setUpDummyParameter();
private:
std::string mountPrefix;
DummyParameter dummyParam;
};
#endif /* BSP_Q7S_CORE_PARAMETERHANDLER_H_ */

View File

@ -1,44 +1,43 @@
#include "obsw.h"
#include <filesystem>
#include <iostream>
#include "InitMission.h"
#include "OBSWConfig.h"
#include "OBSWVersion.h"
#include "fsfw/FSFWVersion.h"
#include "fsfw/tasks/TaskFactory.h"
#include "OBSWConfig.h"
#include "InitMission.h"
#include "watchdogConf.h"
#include "fsfw/tasks/TaskFactory.h"
#include "fsfw/FSFWVersion.h"
#include <iostream>
#include <filesystem>
static int OBSW_ALREADY_RUNNING = -2;
int obsw::obsw() {
std::cout << "-- EIVE OBSW --" << std::endl;
std::cout << "-- EIVE OBSW --" << std::endl;
#if BOARD_TE0720 == 0
std::cout << "-- Compiled for Linux (Xiphos Q7S) --" << std::endl;
std::cout << "-- Compiled for Linux (Xiphos Q7S) --" << std::endl;
#else
std::cout << "-- Compiled for Linux (TE0720) --" << std::endl;
std::cout << "-- Compiled for Linux (TE0720) --" << std::endl;
#endif
std::cout << "-- OBSW v" << SW_VERSION << "." << SW_SUBVERSION << "." << SW_REVISION << ", FSFW v"
<< FSFW_VERSION << "." << FSFW_SUBVERSION << "." << FSFW_REVISION << "--" << std::endl;
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
std::cout << "-- OBSW v" << SW_VERSION << "." << SW_SUBVERSION <<
"." << SW_REVISION << ", FSFW v" << FSFW_VERSION << "." << FSFW_SUBVERSION << "." <<
FSFW_REVISION << "--" << std::endl;
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
#if Q7S_CHECK_FOR_ALREADY_RUNNING_IMG == 1
// Check special file here. This file is created or deleted by the eive-watchdog application
// or systemd service!
if (std::filesystem::exists(watchdog::RUNNING_FILE_NAME)) {
sif::warning << "File " << watchdog::RUNNING_FILE_NAME
<< " exists so the software might "
"already be running. Check if obsw systemd service has been stopped."
<< std::endl;
return OBSW_ALREADY_RUNNING;
}
// Check special file here. This file is created or deleted by the eive-watchdog application
// or systemd service!
if(std::filesystem::exists(watchdog::RUNNING_FILE_NAME)) {
sif::warning << "File " << watchdog::RUNNING_FILE_NAME << " exists so the software might "
"already be running. Aborting.." << std::endl;
return OBSW_ALREADY_RUNNING;
}
#endif
initmission::initMission();
initmission::initMission();
for (;;) {
/* Suspend main thread by sleeping it. */
TaskFactory::delayTask(5000);
}
return 0;
for(;;) {
/* Suspend main thread by sleeping it. */
TaskFactory::delayTask(5000);
}
return 0;
}

View File

@ -1,4 +1,4 @@
target_sources(${OBSW_NAME} PRIVATE
target_sources(${TARGET_NAME} PRIVATE
PlocSupervisorHandler.cpp
PlocUpdater.cpp
PlocMemoryDumper.cpp

View File

@ -1,194 +1,206 @@
#include <fsfw/src/fsfw/serialize/SerializeAdapter.h>
#include "fsfw/ipc/QueueFactory.h"
#include "PlocMemoryDumper.h"
#include <fsfw/src/fsfw/serialize/SerializeAdapter.h>
#include <filesystem>
#include <fstream>
#include <filesystem>
#include <string>
#include "fsfw/ipc/QueueFactory.h"
PlocMemoryDumper::PlocMemoryDumper(object_id_t objectId)
: SystemObject(objectId), commandActionHelper(this), actionHelper(this, nullptr) {
auto mqArgs = MqArgs(this->getObjectId());
commandQueue = QueueFactory::instance()->createMessageQueue(
QUEUE_SIZE, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
PlocMemoryDumper::PlocMemoryDumper(object_id_t objectId) :
SystemObject(objectId), commandActionHelper(this), actionHelper(this, nullptr) {
commandQueue = QueueFactory::instance()->createMessageQueue(QUEUE_SIZE);
}
PlocMemoryDumper::~PlocMemoryDumper() {}
PlocMemoryDumper::~PlocMemoryDumper() {
}
ReturnValue_t PlocMemoryDumper::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = commandActionHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = actionHelper.initialize(commandQueue);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return HasReturnvaluesIF::RETURN_OK;
ReturnValue_t result = SystemObject::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = commandActionHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = actionHelper.initialize(commandQueue);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t PlocMemoryDumper::performOperation(uint8_t operationCode) {
readCommandQueue();
doStateMachine();
return HasReturnvaluesIF::RETURN_OK;
readCommandQueue();
doStateMachine();
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t PlocMemoryDumper::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) {
if (state != State::IDLE) {
return IS_BUSY;
}
ReturnValue_t PlocMemoryDumper::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
switch (actionId) {
if (state != State::IDLE) {
return IS_BUSY;
}
switch (actionId) {
case DUMP_MRAM: {
size_t deserializeSize = sizeof(mram.startAddress) + sizeof(mram.endAddress);
SerializeAdapter::deSerialize(&mram.startAddress, &data, &deserializeSize,
SerializeIF::Endianness::BIG);
SerializeAdapter::deSerialize(&mram.endAddress, &data, &deserializeSize,
SerializeIF::Endianness::BIG);
if (mram.endAddress > MAX_MRAM_ADDRESS) {
return MRAM_ADDRESS_TOO_HIGH;
}
if (mram.endAddress <= mram.startAddress) {
return MRAM_INVALID_ADDRESS_COMBINATION;
}
state = State::COMMAND_FIRST_MRAM_DUMP;
break;
size_t deserializeSize = sizeof(mram.startAddress) + sizeof(mram.endAddress);
SerializeAdapter::deSerialize(&mram.startAddress, &data, &deserializeSize,
SerializeIF::Endianness::BIG);
SerializeAdapter::deSerialize(&mram.endAddress, &data, &deserializeSize,
SerializeIF::Endianness::BIG);
if (mram.endAddress > MAX_MRAM_ADDRESS) {
return MRAM_ADDRESS_TOO_HIGH;
}
if (mram.endAddress <= mram.startAddress) {
return MRAM_INVALID_ADDRESS_COMBINATION;
}
state = State::COMMAND_FIRST_MRAM_DUMP;
break;
}
default: {
sif::warning << "PlocMemoryDumper::executeAction: Received command with invalid action id"
<< std::endl;
return INVALID_ACTION_ID;
sif::warning << "PlocMemoryDumper::executeAction: Received command with invalid action id"
<< std::endl;
return INVALID_ACTION_ID;
}
}
}
return EXECUTION_FINISHED;
return EXECUTION_FINISHED;
}
MessageQueueId_t PlocMemoryDumper::getCommandQueue() const { return commandQueue->getId(); }
MessageQueueId_t PlocMemoryDumper::getCommandQueue() const {
return commandQueue->getId();
}
MessageQueueIF* PlocMemoryDumper::getCommandQueuePtr() { return commandQueue; }
MessageQueueIF* PlocMemoryDumper::getCommandQueuePtr() {
return commandQueue;
}
void PlocMemoryDumper::readCommandQueue() {
CommandMessage message;
ReturnValue_t result;
CommandMessage message;
ReturnValue_t result;
for (result = commandQueue->receiveMessage(&message); result == HasReturnvaluesIF::RETURN_OK;
result = commandQueue->receiveMessage(&message)) {
if (result != RETURN_OK) {
continue;
}
result = actionHelper.handleActionMessage(&message);
if (result == HasReturnvaluesIF::RETURN_OK) {
continue;
}
for (result = commandQueue->receiveMessage(&message); result == HasReturnvaluesIF::RETURN_OK;
result = commandQueue->receiveMessage(&message)) {
if (result != RETURN_OK) {
continue;
}
result = actionHelper.handleActionMessage(&message);
if (result == HasReturnvaluesIF::RETURN_OK) {
continue;
}
result = commandActionHelper.handleReply(&message);
if (result == HasReturnvaluesIF::RETURN_OK) {
continue;
}
result = commandActionHelper.handleReply(&message);
if (result == HasReturnvaluesIF::RETURN_OK) {
continue;
}
sif::debug << "PlocMemoryDumper::readCommandQueue: Received message with invalid format"
<< std::endl;
}
sif::debug << "PlocMemoryDumper::readCommandQueue: Received message with invalid format"
<< std::endl;
}
}
void PlocMemoryDumper::doStateMachine() {
switch (state) {
switch (state) {
case State::IDLE:
break;
break;
case State::COMMAND_FIRST_MRAM_DUMP:
commandNextMramDump(PLOC_SPV::FIRST_MRAM_DUMP);
break;
commandNextMramDump(PLOC_SPV::FIRST_MRAM_DUMP);
break;
case State::COMMAND_CONSECUTIVE_MRAM_DUMP:
commandNextMramDump(PLOC_SPV::CONSECUTIVE_MRAM_DUMP);
break;
commandNextMramDump(PLOC_SPV::CONSECUTIVE_MRAM_DUMP);
break;
case State::EXECUTING_MRAM_DUMP:
break;
break;
default:
sif::debug << "PlocMemoryDumper::doStateMachine: Invalid state" << std::endl;
break;
}
sif::debug << "PlocMemoryDumper::doStateMachine: Invalid state" << std::endl;
break;
}
}
void PlocMemoryDumper::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) {}
void PlocMemoryDumper::stepSuccessfulReceived(ActionId_t actionId,
uint8_t step) {
}
void PlocMemoryDumper::stepFailedReceived(ActionId_t actionId, uint8_t step,
ReturnValue_t returnCode) {}
void PlocMemoryDumper::dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) {}
void PlocMemoryDumper::completionSuccessfulReceived(ActionId_t actionId) {
switch (pendingCommand) {
case (PLOC_SPV::FIRST_MRAM_DUMP):
case (PLOC_SPV::CONSECUTIVE_MRAM_DUMP):
if (mram.endAddress == mram.startAddress) {
triggerEvent(MRAM_DUMP_FINISHED);
state = State::IDLE;
} else {
state = State::COMMAND_CONSECUTIVE_MRAM_DUMP;
}
break;
default:
sif::debug << "PlocMemoryDumper::completionSuccessfulReceived: Invalid pending command"
<< std::endl;
state = State::IDLE;
break;
}
ReturnValue_t returnCode) {
}
void PlocMemoryDumper::completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) {
switch (pendingCommand) {
void PlocMemoryDumper::dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) {
}
void PlocMemoryDumper::completionSuccessfulReceived(ActionId_t actionId) {
switch (pendingCommand) {
case (PLOC_SPV::FIRST_MRAM_DUMP):
case (PLOC_SPV::CONSECUTIVE_MRAM_DUMP):
triggerEvent(MRAM_DUMP_FAILED, mram.lastStartAddress);
break;
if (mram.endAddress == mram.startAddress) {
triggerEvent(MRAM_DUMP_FINISHED);
state = State::IDLE;
}
else {
state = State::COMMAND_CONSECUTIVE_MRAM_DUMP;
}
break;
default:
sif::debug << "PlocMemoryDumper::completionFailedReceived: Invalid pending command "
<< std::endl;
break;
}
state = State::IDLE;
sif::debug << "PlocMemoryDumper::completionSuccessfulReceived: Invalid pending command"
<< std::endl;
state = State::IDLE;
break;
}
}
void PlocMemoryDumper::completionFailedReceived(ActionId_t actionId,
ReturnValue_t returnCode) {
switch(pendingCommand) {
case(PLOC_SPV::FIRST_MRAM_DUMP):
case(PLOC_SPV::CONSECUTIVE_MRAM_DUMP):
triggerEvent(MRAM_DUMP_FAILED, mram.lastStartAddress);
break;
default:
sif::debug << "PlocMemoryDumper::completionFailedReceived: Invalid pending command "
<< std::endl;
break;
}
state = State::IDLE;
}
void PlocMemoryDumper::commandNextMramDump(ActionId_t dumpCommand) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = RETURN_OK;
uint32_t tempStartAddress = 0;
uint32_t tempEndAddress = 0;
uint32_t tempStartAddress = 0;
uint32_t tempEndAddress = 0;
if (mram.endAddress - mram.startAddress > MAX_MRAM_DUMP_SIZE) {
tempStartAddress = mram.startAddress;
tempEndAddress = mram.startAddress + MAX_MRAM_DUMP_SIZE;
mram.startAddress += MAX_MRAM_DUMP_SIZE;
mram.lastStartAddress = tempStartAddress;
} else {
tempStartAddress = mram.startAddress;
tempEndAddress = mram.endAddress;
mram.startAddress = mram.endAddress;
}
if (mram.endAddress - mram.startAddress > MAX_MRAM_DUMP_SIZE) {
tempStartAddress = mram.startAddress;
tempEndAddress = mram.startAddress + MAX_MRAM_DUMP_SIZE;
mram.startAddress += MAX_MRAM_DUMP_SIZE;
mram.lastStartAddress = tempStartAddress;
}
else {
tempStartAddress = mram.startAddress;
tempEndAddress = mram.endAddress;
mram.startAddress = mram.endAddress;
}
MemoryParams params(tempStartAddress, tempEndAddress);
MemoryParams params(tempStartAddress, tempEndAddress);
result =
commandActionHelper.commandAction(objects::PLOC_SUPERVISOR_HANDLER, dumpCommand, &params);
if (result != RETURN_OK) {
sif::warning << "PlocMemoryDumper::commandNextMramDump: Failed to send mram dump command "
<< "with start address " << tempStartAddress << " and end address "
<< tempEndAddress << std::endl;
triggerEvent(SEND_MRAM_DUMP_FAILED, result, tempStartAddress);
state = State::IDLE;
pendingCommand = NONE;
result = commandActionHelper.commandAction(objects::PLOC_SUPERVISOR_HANDLER,
dumpCommand, &params);
if (result != RETURN_OK) {
sif::warning << "PlocMemoryDumper::commandNextMramDump: Failed to send mram dump command "
<< "with start address " << tempStartAddress << " and end address "
<< tempEndAddress << std::endl;
triggerEvent(SEND_MRAM_DUMP_FAILED, result, tempStartAddress);
state = State::IDLE;
pendingCommand = NONE;
return;
}
state = State::EXECUTING_MRAM_DUMP;
pendingCommand = dumpCommand;
return;
}
state = State::EXECUTING_MRAM_DUMP;
pendingCommand = dumpCommand;
return;
}

View File

@ -3,18 +3,18 @@
#include <bsp_q7s/devices/devicedefinitions/PlocMemDumpDefinitions.h>
#include <bsp_q7s/devices/devicedefinitions/PlocSupervisorDefinitions.h>
#include "OBSWConfig.h"
#include "bsp_q7s/memory/SdCardManager.h"
#include "fsfw/action/ActionHelper.h"
#include "fsfw/action/CommandActionHelper.h"
#include "fsfw/action/CommandsActionsIF.h"
#include "fsfw/action/ActionHelper.h"
#include "fsfw/action/HasActionsIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/action/CommandsActionsIF.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tmtcpacket/SpacePacket.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "bsp_q7s/memory/SdCardManager.h"
#include "linux/fsfwconfig/objects/systemObjectList.h"
#include "fsfw/tmtcpacket/SpacePacket.h"
/**
* @brief Because the buffer of the linux tty driver is limited to 2 x 65535 bytes, this class is
@ -25,90 +25,91 @@
* @author J. Meier
*/
class PlocMemoryDumper : public SystemObject,
public HasActionsIF,
public ExecutableObjectIF,
public HasReturnvaluesIF,
public CommandsActionsIF {
public:
static const ActionId_t NONE = 0;
static const ActionId_t DUMP_MRAM = 1;
public HasActionsIF,
public ExecutableObjectIF,
public HasReturnvaluesIF,
public CommandsActionsIF {
public:
PlocMemoryDumper(object_id_t objectId);
virtual ~PlocMemoryDumper();
static const ActionId_t NONE = 0;
static const ActionId_t DUMP_MRAM = 1;
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size);
MessageQueueId_t getCommandQueue() const;
ReturnValue_t initialize() override;
MessageQueueIF* getCommandQueuePtr() override;
void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) override;
void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) override;
void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) override;
void completionSuccessfulReceived(ActionId_t actionId) override;
void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) override;
PlocMemoryDumper(object_id_t objectId);
virtual ~PlocMemoryDumper();
private:
static const uint32_t QUEUE_SIZE = 10;
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size);
MessageQueueId_t getCommandQueue() const;
ReturnValue_t initialize() override;
MessageQueueIF* getCommandQueuePtr() override;
void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) override;
void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) override;
void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) override;
void completionSuccessfulReceived(ActionId_t actionId) override;
void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) override;
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_MEMORY_DUMPER;
private:
//! [EXPORT] : [COMMENT] The capacity of the MRAM amounts to 512 kB. Thus the maximum address must
//! not be higher than 0x7d000.
static const ReturnValue_t MRAM_ADDRESS_TOO_HIGH = MAKE_RETURN_CODE(0xA0);
//! [EXPORT] : [COMMENT] The specified end address is lower than the start address
static const ReturnValue_t MRAM_INVALID_ADDRESS_COMBINATION = MAKE_RETURN_CODE(0xA1);
static const uint32_t QUEUE_SIZE = 10;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_MEMORY_DUMPER;
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_MEMORY_DUMPER;
//! [EXPORT] : [COMMENT] Failed to send mram dump command to supervisor handler
//! P1: Return value of commandAction function
//! P2: Start address of MRAM to dump with this command
static const Event SEND_MRAM_DUMP_FAILED = MAKE_EVENT(0, severity::LOW);
//! [EXPORT] : [COMMENT] Received completion failure report form PLOC supervisor handler
//! P1: MRAM start address of failing dump command
static const Event MRAM_DUMP_FAILED = MAKE_EVENT(1, severity::LOW);
//! [EXPORT] : [COMMENT] MRAM dump finished successfully
static const Event MRAM_DUMP_FINISHED = MAKE_EVENT(2, severity::LOW);
//! [EXPORT] : [COMMENT] The capacity of the MRAM amounts to 512 kB. Thus the maximum address must not be higher than 0x7d000.
static const ReturnValue_t MRAM_ADDRESS_TOO_HIGH = MAKE_RETURN_CODE(0xA0);
//! [EXPORT] : [COMMENT] The specified end address is lower than the start address
static const ReturnValue_t MRAM_INVALID_ADDRESS_COMBINATION = MAKE_RETURN_CODE(0xA1);
// Maximum size of mram dump which can be retrieved with one command
static const uint32_t MAX_MRAM_DUMP_SIZE = 100000;
static const uint32_t MAX_MRAM_ADDRESS = 0x7d000;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_MEMORY_DUMPER;
MessageQueueIF* commandQueue = nullptr;
//! [EXPORT] : [COMMENT] Failed to send mram dump command to supervisor handler
//! P1: Return value of commandAction function
//! P2: Start address of MRAM to dump with this command
static const Event SEND_MRAM_DUMP_FAILED = MAKE_EVENT(0, severity::LOW);
//! [EXPORT] : [COMMENT] Received completion failure report form PLOC supervisor handler
//! P1: MRAM start address of failing dump command
static const Event MRAM_DUMP_FAILED = MAKE_EVENT(1, severity::LOW);
//! [EXPORT] : [COMMENT] MRAM dump finished successfully
static const Event MRAM_DUMP_FINISHED = MAKE_EVENT(2, severity::LOW);
CommandActionHelper commandActionHelper;
// Maximum size of mram dump which can be retrieved with one command
static const uint32_t MAX_MRAM_DUMP_SIZE = 100000;
static const uint32_t MAX_MRAM_ADDRESS = 0x7d000;
ActionHelper actionHelper;
MessageQueueIF* commandQueue = nullptr;
enum class State : uint8_t {
IDLE,
COMMAND_FIRST_MRAM_DUMP,
COMMAND_CONSECUTIVE_MRAM_DUMP,
EXECUTING_MRAM_DUMP
};
CommandActionHelper commandActionHelper;
State state = State::IDLE;
ActionHelper actionHelper;
ActionId_t pendingCommand = NONE;
enum class State: uint8_t {
IDLE,
COMMAND_FIRST_MRAM_DUMP,
COMMAND_CONSECUTIVE_MRAM_DUMP,
EXECUTING_MRAM_DUMP
};
typedef struct MemoryInfo {
// Stores the start address of the next memory range to dump
uint32_t startAddress;
uint32_t endAddress;
// Stores the start address of the last sent dump command
uint32_t lastStartAddress;
} MemoryInfo_t;
State state = State::IDLE;
MemoryInfo_t mram = {0, 0, 0};
ActionId_t pendingCommand = NONE;
void readCommandQueue();
void doStateMachine();
typedef struct MemoryInfo {
// Stores the start address of the next memory range to dump
uint32_t startAddress;
uint32_t endAddress;
// Stores the start address of the last sent dump command
uint32_t lastStartAddress;
} MemoryInfo_t;
/**
* @brief Sends the next mram dump command to the PLOC supervisor handler.
*/
void commandNextMramDump(ActionId_t dumpCommand);
MemoryInfo_t mram = {0, 0, 0};
void readCommandQueue();
void doStateMachine();
/**
* @brief Sends the next mram dump command to the PLOC supervisor handler.
*/
void commandNextMramDump(ActionId_t dumpCommand);
};
#endif /* MISSION_DEVICES_PLOCMEMORYDUMPER_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,12 @@
#ifndef MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_
#define MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_
#include "devicedefinitions/PlocSupervisorDefinitions.h"
#include <bsp_q7s/memory/SdCardManager.h>
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <fsfw_hal/linux/uart/UartComIF.h>
#include "devicedefinitions/PlocSupervisorDefinitions.h"
/**
* @brief This is the device handler for the supervisor of the PLOC which is programmed by
* Thales.
@ -19,327 +19,324 @@
* Arbeitsdaten/08_Used%20Components/PLOC&fileid=940960
* @author J. Meier
*/
class PlocSupervisorHandler : public DeviceHandlerBase {
public:
PlocSupervisorHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF* comCookie);
virtual ~PlocSupervisorHandler();
class PlocSupervisorHandler: public DeviceHandlerBase {
public:
virtual ReturnValue_t initialize() override;
PlocSupervisorHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF * comCookie);
virtual ~PlocSupervisorHandler();
protected:
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t* id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t* id) override;
void fillCommandAndReplyMap() override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t* commandData,
size_t commandDataLen) override;
ReturnValue_t scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId,
size_t* foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) override;
void setNormalDatapoolEntriesInvalid() override;
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator command,
uint8_t expectedReplies = 1, bool useAlternateId = false,
DeviceCommandId_t alternateReplyID = 0) override;
size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override;
virtual ReturnValue_t initialize() override;
private:
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_SUPERVISOR_HANDLER;
protected:
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) override;
void fillCommandAndReplyMap() override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t * commandData,size_t commandDataLen) override;
ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize,
DeviceCommandId_t *foundId, size_t *foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) override;
void setNormalDatapoolEntriesInvalid() override;
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator command,
uint8_t expectedReplies = 1, bool useAlternateId = false,
DeviceCommandId_t alternateReplyID = 0) override;
size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override;
//! [EXPORT] : [COMMENT] Space Packet received from PLOC supervisor has invalid CRC
static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA0);
//! [EXPORT] : [COMMENT] Received ACK failure reply from PLOC supervisor
static const ReturnValue_t RECEIVED_ACK_FAILURE = MAKE_RETURN_CODE(0xA1);
//! [EXPORT] : [COMMENT] Received execution failure reply from PLOC supervisor
static const ReturnValue_t RECEIVED_EXE_FAILURE = MAKE_RETURN_CODE(0xA2);
//! [EXPORT] : [COMMENT] Received space packet with invalid APID from PLOC supervisor
static const ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(0xA3);
//! [EXPORT] : [COMMENT] Failed to read current system time
static const ReturnValue_t GET_TIME_FAILURE = MAKE_RETURN_CODE(0xA4);
//! [EXPORT] : [COMMENT] Invalid communication interface specified
static const ReturnValue_t INVALID_UART_COM_IF = MAKE_RETURN_CODE(0xA5);
//! [EXPORT] : [COMMENT] Received command with invalid watchdog parameter. Valid watchdogs are 0
//! for PS, 1 for PL and 2 for INT
static const ReturnValue_t INVALID_WATCHDOG = MAKE_RETURN_CODE(0xA6);
//! [EXPORT] : [COMMENT] Received watchdog timeout config command with invalid timeout. Valid
//! timeouts must be in the range between 1000 and 360000 ms.
static const ReturnValue_t INVALID_WATCHDOG_TIMEOUT = MAKE_RETURN_CODE(0xA7);
//! [EXPORT] : [COMMENT] Received latchup config command with invalid latchup ID
static const ReturnValue_t INVALID_LATCHUP_ID = MAKE_RETURN_CODE(0xA8);
//! [EXPORT] : [COMMENT] Received set adc sweep period command with invalid sweep period. Must be
//! larger than 21.
static const ReturnValue_t SWEEP_PERIOD_TOO_SMALL = MAKE_RETURN_CODE(0xA9);
//! [EXPORT] : [COMMENT] Receive auto EM test command with invalid test param. Valid params are 1
//! and 2.
static const ReturnValue_t INVALID_TEST_PARAM = MAKE_RETURN_CODE(0xAA);
//! [EXPORT] : [COMMENT] Returned when scanning for MRAM dump packets failed.
static const ReturnValue_t MRAM_PACKET_PARSING_FAILURE = MAKE_RETURN_CODE(0xAB);
//! [EXPORT] : [COMMENT] Returned when the start and stop addresses of the MRAM dump or MRAM wipe
//! commands are invalid (e.g. start address bigger than stop address)
static const ReturnValue_t INVALID_MRAM_ADDRESSES = MAKE_RETURN_CODE(0xAC);
//! [EXPORT] : [COMMENT] Expect reception of an MRAM dump packet but received space packet with
//! other apid.
static const ReturnValue_t NO_MRAM_PACKET = MAKE_RETURN_CODE(0xAD);
//! [EXPORT] : [COMMENT] Path to PLOC directory on SD card does not exist
static const ReturnValue_t PATH_DOES_NOT_EXIST = MAKE_RETURN_CODE(0xAE);
//! [EXPORT] : [COMMENT] MRAM dump file does not exists. The file should actually already have
//! been created with the reception of the first dump packet.
static const ReturnValue_t MRAM_FILE_NOT_EXISTS = MAKE_RETURN_CODE(0xAF);
private:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_SUPERVISOR_HANDLER;
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_SUPERVISOR_HANDLER;
//! [EXPORT] : [COMMENT] PLOC supervisor crc failure in telemetry packet
static const Event SUPV_MEMORY_READ_RPT_CRC_FAILURE = MAKE_EVENT(1, severity::LOW);
//! [EXPORT] : [COMMENT] PLOC supervisor received acknowledgment failure report
static const Event SUPV_ACK_FAILURE = MAKE_EVENT(2, severity::LOW);
//! [EXPORT] : [COMMENT] PLOC received execution failure report
static const Event SUPV_EXE_FAILURE = MAKE_EVENT(3, severity::LOW);
//! [EXPORT] : [COMMENT] PLOC supervisor reply has invalid crc
static const Event SUPV_CRC_FAILURE_EVENT = MAKE_EVENT(4, severity::LOW);
//! [EXPORT] : [COMMENT] Space Packet received from PLOC supervisor has invalid CRC
static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA0);
//! [EXPORT] : [COMMENT] Received ACK failure reply from PLOC supervisor
static const ReturnValue_t RECEIVED_ACK_FAILURE = MAKE_RETURN_CODE(0xA1);
//! [EXPORT] : [COMMENT] Received execution failure reply from PLOC supervisor
static const ReturnValue_t RECEIVED_EXE_FAILURE = MAKE_RETURN_CODE(0xA2);
//! [EXPORT] : [COMMENT] Received space packet with invalid APID from PLOC supervisor
static const ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(0xA3);
//! [EXPORT] : [COMMENT] Failed to read current system time
static const ReturnValue_t GET_TIME_FAILURE = MAKE_RETURN_CODE(0xA4);
//! [EXPORT] : [COMMENT] Invalid communication interface specified
static const ReturnValue_t INVALID_UART_COM_IF = MAKE_RETURN_CODE(0xA5);
//! [EXPORT] : [COMMENT] Received command with invalid watchdog parameter. Valid watchdogs are 0 for PS, 1 for PL and 2 for INT
static const ReturnValue_t INVALID_WATCHDOG = MAKE_RETURN_CODE(0xA6);
//! [EXPORT] : [COMMENT] Received watchdog timeout config command with invalid timeout. Valid timeouts must be in the range between 1000 and 360000 ms.
static const ReturnValue_t INVALID_WATCHDOG_TIMEOUT = MAKE_RETURN_CODE(0xA7);
//! [EXPORT] : [COMMENT] Received latchup config command with invalid latchup ID
static const ReturnValue_t INVALID_LATCHUP_ID = MAKE_RETURN_CODE(0xA8);
//! [EXPORT] : [COMMENT] Received set adc sweep period command with invalid sweep period. Must be larger than 21.
static const ReturnValue_t SWEEP_PERIOD_TOO_SMALL = MAKE_RETURN_CODE(0xA9);
//! [EXPORT] : [COMMENT] Receive auto EM test command with invalid test param. Valid params are 1 and 2.
static const ReturnValue_t INVALID_TEST_PARAM = MAKE_RETURN_CODE(0xAA);
//! [EXPORT] : [COMMENT] Returned when scanning for MRAM dump packets failed.
static const ReturnValue_t MRAM_PACKET_PARSING_FAILURE = MAKE_RETURN_CODE(0xAB);
//! [EXPORT] : [COMMENT] Returned when the start and stop addresses of the MRAM dump or MRAM wipe commands are invalid (e.g. start address bigger than stop address)
static const ReturnValue_t INVALID_MRAM_ADDRESSES = MAKE_RETURN_CODE(0xAC);
//! [EXPORT] : [COMMENT] Expect reception of an MRAM dump packet but received space packet with other apid.
static const ReturnValue_t NO_MRAM_PACKET = MAKE_RETURN_CODE(0xAD);
//! [EXPORT] : [COMMENT] Path to PLOC directory on SD card does not exist
static const ReturnValue_t PATH_DOES_NOT_EXIST = MAKE_RETURN_CODE(0xAE);
//! [EXPORT] : [COMMENT] MRAM dump file does not exists. The file should actually already have been created with the reception of the first dump packet.
static const ReturnValue_t MRAM_FILE_NOT_EXISTS = MAKE_RETURN_CODE(0xAF);
static const uint16_t APID_MASK = 0x7FF;
static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_SUPERVISOR_HANDLER;
uint8_t commandBuffer[PLOC_SPV::MAX_COMMAND_SIZE];
//! [EXPORT] : [COMMENT] PLOC supervisor crc failure in telemetry packet
static const Event SUPV_MEMORY_READ_RPT_CRC_FAILURE = MAKE_EVENT(1, severity::LOW);
//! [EXPORT] : [COMMENT] PLOC supervisor received acknowledgment failure report
static const Event SUPV_ACK_FAILURE = MAKE_EVENT(2, severity::LOW);
//! [EXPORT] : [COMMENT] PLOC received execution failure report
static const Event SUPV_EXE_FAILURE = MAKE_EVENT(3, severity::LOW);
//! [EXPORT] : [COMMENT] PLOC supervisor reply has invalid crc
static const Event SUPV_CRC_FAILURE_EVENT = MAKE_EVENT(4, severity::LOW);
/**
* This variable is used to store the id of the next reply to receive. This is necessary
* because the PLOC sends as reply to each command at least one acknowledgment and execution
* report.
*/
DeviceCommandId_t nextReplyId = PLOC_SPV::NONE;
static const uint16_t APID_MASK = 0x7FF;
static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF;
UartComIF* uartComIf = nullptr;
uint8_t commandBuffer[PLOC_SPV::MAX_COMMAND_SIZE];
PLOC_SPV::HkSet hkset;
PLOC_SPV::BootStatusReport bootStatusReport;
PLOC_SPV::LatchupStatusReport latchupStatusReport;
/**
* This variable is used to store the id of the next reply to receive. This is necessary
* because the PLOC sends as reply to each command at least one acknowledgment and execution
* report.
*/
DeviceCommandId_t nextReplyId = PLOC_SPV::NONE;
/** Number of expected replies following the MRAM dump command */
uint32_t expectedMramDumpPackets = 0;
uint32_t receivedMramDumpPackets = 0;
/** Set to true as soon as a complete space packet is present in the spacePacketBuffer */
bool packetInBuffer = false;
/** Points to the next free position in the space packet buffer */
uint16_t bufferTop = 0;
UartComIF* uartComIf = nullptr;
/** This buffer is used to concatenate space packets received in two different read steps */
uint8_t spacePacketBuffer[PLOC_SPV::MAX_PACKET_SIZE];
PLOC_SPV::HkSet hkset;
PLOC_SPV::BootStatusReport bootStatusReport;
PLOC_SPV::LatchupStatusReport latchupStatusReport;
/** Number of expected replies following the MRAM dump command */
uint32_t expectedMramDumpPackets = 0;
uint32_t receivedMramDumpPackets = 0;
/** Set to true as soon as a complete space packet is present in the spacePacketBuffer */
bool packetInBuffer = false;
/** Points to the next free position in the space packet buffer */
uint16_t bufferTop = 0;
/** This buffer is used to concatenate space packets received in two different read steps */
uint8_t spacePacketBuffer[PLOC_SPV::MAX_PACKET_SIZE];
#if BOARD_TE0720 == 0
SdCardManager* sdcMan = nullptr;
SdCardManager* sdcMan = nullptr;
#endif /* BOARD_TE0720 == 0 */
/** Path to PLOC specific files on SD card */
std::string plocFilePath = "ploc";
std::string activeMramFile;
/** Path to PLOC specific files on SD card */
std::string plocFilePath = "ploc";
std::string activeMramFile;
/** Setting this variable to true will enable direct downlink of MRAM packets */
bool downlinkMramDump = false;
/** Setting this variable to true will enable direct downlink of MRAM packets */
bool downlinkMramDump = false;
/**
* @brief This function checks the crc of the received PLOC reply.
*
* @param start Pointer to the first byte of the reply.
* @param foundLen Pointer to the length of the whole packet.
*
* @return RETURN_OK if CRC is ok, otherwise CRC_FAILURE.
*/
ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen);
/**
* @brief This function checks the crc of the received PLOC reply.
*
* @param start Pointer to the first byte of the reply.
* @param foundLen Pointer to the length of the whole packet.
*
* @return RETURN_OK if CRC is ok, otherwise CRC_FAILURE.
*/
ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen);
/**
* @brief This function handles the acknowledgment report.
*
* @param data Pointer to the data holding the acknowledgment report.
*
* @return RETURN_OK if successful, otherwise an error code.
*/
ReturnValue_t handleAckReport(const uint8_t* data);
/**
* @brief This function handles the acknowledgment report.
*
* @param data Pointer to the data holding the acknowledgment report.
*
* @return RETURN_OK if successful, otherwise an error code.
*/
ReturnValue_t handleAckReport(const uint8_t* data);
/**
* @brief This function handles the data of a execution report.
*
* @param data Pointer to the received data packet.
*
* @return RETURN_OK if successful, otherwise an error code.
*/
ReturnValue_t handleExecutionReport(const uint8_t* data);
/**
* @brief This function handles the data of a execution report.
*
* @param data Pointer to the received data packet.
*
* @return RETURN_OK if successful, otherwise an error code.
*/
ReturnValue_t handleExecutionReport(const uint8_t* data);
/**
* @brief This function handles the housekeeping report. This means verifying the CRC of the
* reply and filling the appropriate dataset.
*
* @param data Pointer to the data buffer holding the housekeeping read report.
*
* @return RETURN_OK if successful, otherwise an error code.
*/
ReturnValue_t handleHkReport(const uint8_t* data);
/**
* @brief This function handles the housekeeping report. This means verifying the CRC of the
* reply and filling the appropriate dataset.
*
* @param data Pointer to the data buffer holding the housekeeping read report.
*
* @return RETURN_OK if successful, otherwise an error code.
*/
ReturnValue_t handleHkReport(const uint8_t* data);
/**
* @brief This function calls the function to check the CRC of the received boot status report
* and fills the associated dataset with the boot status information.
*/
ReturnValue_t handleBootStatusReport(const uint8_t* data);
/**
* @brief This function calls the function to check the CRC of the received boot status report
* and fills the associated dataset with the boot status information.
*/
ReturnValue_t handleBootStatusReport(const uint8_t* data);
ReturnValue_t handleLatchupStatusReport(const uint8_t* data);
ReturnValue_t handleLatchupStatusReport(const uint8_t* data);
/**
* @brief Depending on the current active command, this function sets the reply id of the
* next reply after a successful acknowledgment report has been received. This is
* required by the function getNextReplyLength() to identify the length of the next
* reply to read.
*/
void setNextReplyId();
/**
* @brief Depending on the current active command, this function sets the reply id of the
* next reply after a successful acknowledgment report has been received. This is
* required by the function getNextReplyLength() to identify the length of the next
* reply to read.
*/
void setNextReplyId();
/**
* @brief This function handles action message replies in case the telemetry has been
* requested by another object.
*
* @param data Pointer to the telemetry data.
* @param dataSize Size of telemetry in bytes.
* @param replyId Id of the reply. This will be added to the ActionMessage.
*/
void handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId);
/**
* @brief This function handles action message replies in case the telemetry has been
* requested by another object.
*
* @param data Pointer to the telemetry data.
* @param dataSize Size of telemetry in bytes.
* @param replyId Id of the reply. This will be added to the ActionMessage.
*/
void handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId);
/**
* @brief This function prepares a space packet which does not transport any data in the
* packet data field apart from the crc.
*/
void prepareEmptyCmd(uint16_t apid);
/**
* @brief This function prepares a space packet which does not transport any data in the
* packet data field apart from the crc.
*/
void prepareEmptyCmd(uint16_t apid);
/**
* @brief This function initializes the space packet to select the boot image of the MPSoC.
*/
void prepareSelBootImageCmd(const uint8_t* commandData);
/**
* @brief This function initializes the space packet to select the boot image of the MPSoC.
*/
void prepareSelBootImageCmd(const uint8_t * commandData);
void prepareDisableHk();
void prepareDisableHk();
/**
* @brief This function fills the commandBuffer with the data to update the time of the
* PLOC supervisor.
*/
ReturnValue_t prepareSetTimeRefCmd();
/**
* @brief This function fills the commandBuffer with the data to update the time of the
* PLOC supervisor.
*/
ReturnValue_t prepareSetTimeRefCmd();
/**
* @brief This function fills the commandBuffer with the data to change the boot timeout
* value in the PLOC supervisor.
*/
void prepareSetBootTimeoutCmd(const uint8_t* commandData);
/**
* @brief This function fills the commandBuffer with the data to change the boot timeout
* value in the PLOC supervisor.
*/
void prepareSetBootTimeoutCmd(const uint8_t * commandData);
void prepareRestartTriesCmd(const uint8_t* commandData);
void prepareRestartTriesCmd(const uint8_t * commandData);
/**
* @brief This function fills the command buffer with the packet to enable or disable the
* watchdogs on the PLOC.
*/
void prepareWatchdogsEnableCmd(const uint8_t* commandData);
/**
* @brief This function fills the command buffer with the packet to enable or disable the
* watchdogs on the PLOC.
*/
void prepareWatchdogsEnableCmd(const uint8_t * commandData);
/**
* @brief This function fills the command buffer with the packet to set the watchdog timer
* of one of the three watchdogs (PS, PL, INT).
*/
ReturnValue_t prepareWatchdogsConfigTimeoutCmd(const uint8_t* commandData);
/**
* @brief This function fills the command buffer with the packet to set the watchdog timer
* of one of the three watchdogs (PS, PL, INT).
*/
ReturnValue_t prepareWatchdogsConfigTimeoutCmd(const uint8_t * commandData);
ReturnValue_t prepareLatchupConfigCmd(const uint8_t* commandData,
DeviceCommandId_t deviceCommand);
ReturnValue_t prepareAutoCalibrateAlertCmd(const uint8_t* commandData);
ReturnValue_t prepareSetAlertLimitCmd(const uint8_t* commandData);
ReturnValue_t prepareSetAlertIrqFilterCmd(const uint8_t* commandData);
ReturnValue_t prepareSetAdcSweetPeriodCmd(const uint8_t* commandData);
void prepareSetAdcEnabledChannelsCmd(const uint8_t* commandData);
void prepareSetAdcWindowAndStrideCmd(const uint8_t* commandData);
void prepareSetAdcThresholdCmd(const uint8_t* commandData);
void prepareEnableNvmsCmd(const uint8_t* commandData);
void prepareSelectNvmCmd(const uint8_t* commandData);
ReturnValue_t prepareRunAutoEmTest(const uint8_t* commandData);
ReturnValue_t prepareWipeMramCmd(const uint8_t* commandData);
ReturnValue_t prepareDumpMramCmd(const uint8_t* commandData);
void preparePrintCpuStatsCmd(const uint8_t* commandData);
void prepareSetDbgVerbosityCmd(const uint8_t* commandData);
void prepareSetGpioCmd(const uint8_t* commandData);
void prepareReadGpioCmd(const uint8_t* commandData);
ReturnValue_t prepareLatchupConfigCmd(const uint8_t* commandData,
DeviceCommandId_t deviceCommand);
ReturnValue_t prepareAutoCalibrateAlertCmd(const uint8_t* commandData);
ReturnValue_t prepareSetAlertLimitCmd(const uint8_t* commandData);
ReturnValue_t prepareSetAlertIrqFilterCmd(const uint8_t* commandData);
ReturnValue_t prepareSetAdcSweetPeriodCmd(const uint8_t* commandData);
void prepareSetAdcEnabledChannelsCmd(const uint8_t* commandData);
void prepareSetAdcWindowAndStrideCmd(const uint8_t* commandData);
void prepareSetAdcThresholdCmd(const uint8_t* commandData);
void prepareEnableNvmsCmd(const uint8_t* commandData);
void prepareSelectNvmCmd(const uint8_t* commandData);
ReturnValue_t prepareRunAutoEmTest(const uint8_t* commandData);
ReturnValue_t prepareWipeMramCmd(const uint8_t* commandData);
ReturnValue_t prepareDumpMramCmd(const uint8_t* commandData);
void preparePrintCpuStatsCmd(const uint8_t* commandData);
void prepareSetDbgVerbosityCmd(const uint8_t* commandData);
void prepareSetGpioCmd(const uint8_t* commandData);
void prepareReadGpioCmd(const uint8_t* commandData);
/**
* @brief Copies the content of a space packet to the command buffer.
*/
void packetToOutBuffer(uint8_t* packetData, size_t fullSize);
/**
* @brief In case an acknowledgment failure reply has been received this function disables
* all previously enabled commands and resets the exepected replies variable of an
* active command.
*/
void disableAllReplies();
/**
* @brief Copies the content of a space packet to the command buffer.
*/
void packetToOutBuffer(uint8_t* packetData, size_t fullSize);
/**
* @brief This function sends a failure report if the active action was commanded by an other
* object.
*
* @param replyId The id of the reply which signals a failure.
* @param status A status byte which gives information about the failure type.
*/
void sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status);
/**
* @brief In case an acknowledgment failure reply has been received this function disables
* all previously enabled commands and resets the exepected replies variable of an
* active command.
*/
void disableAllReplies();
/**
* @brief This function disables the execution report reply. Within this function also the
* the variable expectedReplies of an active command will be set to 0.
*/
void disableExeReportReply();
/**
* @brief This function sends a failure report if the active action was commanded by an other
* object.
*
* @param replyId The id of the reply which signals a failure.
* @param status A status byte which gives information about the failure type.
*/
void sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status);
/**
* @brief Function is called in scanForReply and fills the spacePacketBuffer with the read
* data until a full packet has been received.
*/
ReturnValue_t parseMramPackets(const uint8_t* packet, size_t remainingSize, size_t* foundlen);
/**
* @brief This function disables the execution report reply. Within this function also the
* the variable expectedReplies of an active command will be set to 0.
*/
void disableExeReportReply();
/**
* @brief This function generates the Service 8 packets for the MRAM dump data.
*/
ReturnValue_t handleMramDumpPacket(DeviceCommandId_t id);
/**
* @brief Function is called in scanForReply and fills the spacePacketBuffer with the read
* data until a full packet has been received.
*/
ReturnValue_t parseMramPackets(const uint8_t *packet, size_t remainingSize, size_t* foundlen);
/**
* @brief With this function the number of expected replies following an MRAM dump command
* will be increased. This is necessary to release the command in case not all replies
* have been received.
*/
void increaseExpectedMramReplies(DeviceCommandId_t id);
/**
* @brief This function generates the Service 8 packets for the MRAM dump data.
*/
ReturnValue_t handleMramDumpPacket(DeviceCommandId_t id);
/**
* @brief Function checks if the packet written to the space packet buffer is really a
* MRAM dump packet.
*/
ReturnValue_t checkMramPacketApid();
/**
* @brief With this function the number of expected replies following an MRAM dump command
* will be increased. This is necessary to release the command in case not all replies
* have been received.
*/
void increaseExpectedMramReplies(DeviceCommandId_t id);
/**
* @brief Writes the data of the MRAM dump to a file. The file will be created when receiving
* the first packet.
*/
ReturnValue_t handleMramDumpFile(DeviceCommandId_t id);
/**
* @brief Function checks if the packet written to the space packet buffer is really a
* MRAM dump packet.
*/
ReturnValue_t checkMramPacketApid();
/**
* @brief Extracts the length field of a spacePacket referenced by the spacePacket pointer.
*
* @param spacePacket Pointer to the buffer holding the space packet.
*
* @return The value stored in the length field of the data field.
*/
uint16_t readSpacePacketLength(uint8_t* spacePacket);
/**
* @brief Writes the data of the MRAM dump to a file. The file will be created when receiving
* the first packet.
*/
ReturnValue_t handleMramDumpFile(DeviceCommandId_t id);
/**
* @brief Extracts the sequence flags from a space packet referenced by the spacePacket
* pointer.
*
* @param spacePacket Pointer to the buffer holding the space packet.
*
* @return uint8_t where the two least significant bits hold the sequence flags.
*/
uint8_t readSequenceFlags(uint8_t* spacePacket);
/**
* @brief Extracts the length field of a spacePacket referenced by the spacePacket pointer.
*
* @param spacePacket Pointer to the buffer holding the space packet.
*
* @return The value stored in the length field of the data field.
*/
uint16_t readSpacePacketLength(uint8_t* spacePacket);
ReturnValue_t createMramDumpFile();
ReturnValue_t getTimeStampString(std::string& timeStamp);
/**
* @brief Extracts the sequence flags from a space packet referenced by the spacePacket
* pointer.
*
* @param spacePacket Pointer to the buffer holding the space packet.
*
* @return uint8_t where the two least significant bits hold the sequence flags.
*/
uint8_t readSequenceFlags(uint8_t* spacePacket);
ReturnValue_t createMramDumpFile();
ReturnValue_t getTimeStampString(std::string& timeStamp);
};
#endif /* MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ */

View File

@ -1,395 +1,436 @@
#include "fsfw/ipc/QueueFactory.h"
#include "PlocUpdater.h"
#include <filesystem>
#include <fstream>
#include <filesystem>
#include <string>
#include "fsfw/ipc/QueueFactory.h"
PlocUpdater::PlocUpdater(object_id_t objectId)
: SystemObject(objectId), commandActionHelper(this), actionHelper(this, nullptr) {
auto mqArgs = MqArgs(this->getObjectId());
commandQueue = QueueFactory::instance()->createMessageQueue(
QUEUE_SIZE, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
PlocUpdater::PlocUpdater(object_id_t objectId) :
SystemObject(objectId), commandActionHelper(this), actionHelper(this, nullptr) {
commandQueue = QueueFactory::instance()->createMessageQueue(QUEUE_SIZE);
}
PlocUpdater::~PlocUpdater() {}
PlocUpdater::~PlocUpdater() {
}
ReturnValue_t PlocUpdater::initialize() {
#if BOARD_TE0720 == 0
sdcMan = SdCardManager::instance();
sdcMan = SdCardManager::instance();
#endif
ReturnValue_t result = SystemObject::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = commandActionHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = actionHelper.initialize(commandQueue);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
ReturnValue_t result = SystemObject::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = commandActionHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = actionHelper.initialize(commandQueue);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return HasReturnvaluesIF::RETURN_OK;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t PlocUpdater::performOperation(uint8_t operationCode) {
readCommandQueue();
doStateMachine();
return HasReturnvaluesIF::RETURN_OK;
readCommandQueue();
doStateMachine();
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t PlocUpdater::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) {
ReturnValue_t result = RETURN_FAILED;
ReturnValue_t PlocUpdater::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
ReturnValue_t result = RETURN_FAILED;
if (state != State::IDLE) {
return IS_BUSY;
}
if (state != State::IDLE) {
return IS_BUSY;
}
if (size > MAX_PLOC_UPDATE_PATH) {
return NAME_TOO_LONG;
}
if (size > MAX_PLOC_UPDATE_PATH) {
return NAME_TOO_LONG;
}
switch (actionId) {
switch (actionId) {
case UPDATE_A_UBOOT:
image = Image::A;
partition = Partition::UBOOT;
break;
image = Image::A;
partition = Partition::UBOOT;
break;
case UPDATE_A_BITSTREAM:
image = Image::A;
partition = Partition::BITSTREAM;
break;
image = Image::A;
partition = Partition::BITSTREAM;
break;
case UPDATE_A_LINUX:
image = Image::A;
partition = Partition::LINUX_OS;
break;
image = Image::A;
partition = Partition::LINUX_OS;
break;
case UPDATE_A_APP_SW:
image = Image::A;
partition = Partition::APP_SW;
break;
image = Image::A;
partition = Partition::APP_SW;
break;
case UPDATE_B_UBOOT:
image = Image::B;
partition = Partition::UBOOT;
break;
image = Image::B;
partition = Partition::UBOOT;
break;
case UPDATE_B_BITSTREAM:
image = Image::B;
partition = Partition::BITSTREAM;
break;
image = Image::B;
partition = Partition::BITSTREAM;
break;
case UPDATE_B_LINUX:
image = Image::B;
partition = Partition::LINUX_OS;
break;
image = Image::B;
partition = Partition::LINUX_OS;
break;
case UPDATE_B_APP_SW:
image = Image::B;
partition = Partition::APP_SW;
break;
image = Image::B;
partition = Partition::APP_SW;
break;
default:
return INVALID_ACTION_ID;
}
return INVALID_ACTION_ID;
}
result = getImageLocation(data, size);
result = getImageLocation(data, size);
if (result != RETURN_OK) {
return result;
}
if (result != RETURN_OK) {
return result;
}
state = State::UPDATE_AVAILABLE;
state = State::UPDATE_AVAILABLE;
return EXECUTION_FINISHED;
return EXECUTION_FINISHED;
}
MessageQueueId_t PlocUpdater::getCommandQueue() const { return commandQueue->getId(); }
MessageQueueId_t PlocUpdater::getCommandQueue() const {
return commandQueue->getId();
}
MessageQueueIF* PlocUpdater::getCommandQueuePtr() { return commandQueue; }
MessageQueueIF* PlocUpdater::getCommandQueuePtr() {
return commandQueue;
}
void PlocUpdater::readCommandQueue() {
CommandMessage message;
ReturnValue_t result;
CommandMessage message;
ReturnValue_t result;
for (result = commandQueue->receiveMessage(&message); result == HasReturnvaluesIF::RETURN_OK;
result = commandQueue->receiveMessage(&message)) {
if (result != RETURN_OK) {
continue;
}
result = actionHelper.handleActionMessage(&message);
if (result == HasReturnvaluesIF::RETURN_OK) {
continue;
}
for (result = commandQueue->receiveMessage(&message); result == HasReturnvaluesIF::RETURN_OK;
result = commandQueue->receiveMessage(&message)) {
if (result != RETURN_OK) {
continue;
}
result = actionHelper.handleActionMessage(&message);
if (result == HasReturnvaluesIF::RETURN_OK) {
continue;
}
result = commandActionHelper.handleReply(&message);
if (result == HasReturnvaluesIF::RETURN_OK) {
continue;
}
result = commandActionHelper.handleReply(&message);
if (result == HasReturnvaluesIF::RETURN_OK) {
continue;
}
sif::debug << "PlocUpdater::readCommandQueue: Received message with invalid format"
<< std::endl;
}
sif::debug << "PlocUpdater::readCommandQueue: Received message with invalid format"
<< std::endl;
}
}
void PlocUpdater::doStateMachine() {
switch (state) {
switch (state) {
case State::IDLE:
break;
break;
case State::UPDATE_AVAILABLE:
commandUpdateAvailable();
break;
commandUpdateAvailable();
break;
case State::UPDATE_TRANSFER:
commandUpdatePacket();
break;
commandUpdatePacket();
break;
case State::UPDATE_VERIFY:
commandUpdateVerify();
break;
commandUpdateVerify();
break;
case State::COMMAND_EXECUTING:
break;
break;
default:
sif::debug << "PlocUpdater::doStateMachine: Invalid state" << std::endl;
break;
}
sif::debug << "PlocUpdater::doStateMachine: Invalid state" << std::endl;
break;
}
}
ReturnValue_t PlocUpdater::checkNameLength(size_t size) {
if (size > MAX_PLOC_UPDATE_PATH) {
return NAME_TOO_LONG;
}
return RETURN_OK;
if (size > MAX_PLOC_UPDATE_PATH) {
return NAME_TOO_LONG;
}
return RETURN_OK;
}
ReturnValue_t PlocUpdater::getImageLocation(const uint8_t* data, size_t size) {
ReturnValue_t result = checkNameLength(size);
if (result != RETURN_OK) {
return result;
}
ReturnValue_t result = checkNameLength(size);
if (result != RETURN_OK) {
return result;
}
#if BOARD_TE0720 == 0
// Check if file is stored on SD card and if associated SD card is mounted
if (std::string(reinterpret_cast<const char*>(data), SD_PREFIX_LENGTH) ==
std::string(SdCardManager::SD_0_MOUNT_POINT)) {
if (!sdcMan->isSdCardMounted(sd::SLOT_0)) {
sif::warning << "PlocUpdater::getImageLocation: SD card 0 not mounted" << std::endl;
return SD_NOT_MOUNTED;
// Check if file is stored on SD card and if associated SD card is mounted
if (std::string(reinterpret_cast<const char*>(data), SD_PREFIX_LENGTH) == std::string(SdCardManager::SD_0_MOUNT_POINT)) {
if (!isSdCardMounted(sd::SLOT_0)) {
sif::warning << "PlocUpdater::prepareNvm0AUpdate: SD card 0 not mounted" << std::endl;
return SD_NOT_MOUNTED;
}
}
} else if (std::string(reinterpret_cast<const char*>(data), SD_PREFIX_LENGTH) ==
std::string(SdCardManager::SD_1_MOUNT_POINT)) {
if (!sdcMan->isSdCardMounted(sd::SLOT_0)) {
sif::warning << "PlocUpdater::getImageLocation: SD card 1 not mounted" << std::endl;
return SD_NOT_MOUNTED;
else if (std::string(reinterpret_cast<const char*>(data), SD_PREFIX_LENGTH) == std::string(SdCardManager::SD_1_MOUNT_POINT)) {
if (!isSdCardMounted(sd::SLOT_0)) {
sif::warning << "PlocUpdater::prepareNvm0AUpdate: SD card 1 not mounted" << std::endl;
return SD_NOT_MOUNTED;
}
}
else {
//update image not stored on SD card
}
} else {
// update image not stored on SD card
}
#endif /* BOARD_TE0720 == 0 */
updateFile = std::string(reinterpret_cast<const char*>(data), size);
updateFile = std::string(reinterpret_cast<const char*>(data), size);
// Check if file exists
if (not std::filesystem::exists(updateFile)) {
return FILE_NOT_EXISTS;
}
return RETURN_OK;
// Check if file exists
if(not std::filesystem::exists(updateFile)) {
return FILE_NOT_EXISTS;
}
return RETURN_OK;
}
void PlocUpdater::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) {}
#if BOARD_TE0720 == 0
bool PlocUpdater::isSdCardMounted(sd::SdCard sdCard) {
SdCardManager::SdStatePair active;
ReturnValue_t result = sdcMan->getSdCardActiveStatus(active);
if (result != RETURN_OK) {
sif::debug << "PlocUpdater::isSdCardMounted: Failed to get SD card active state";
return false;
}
if (sdCard == sd::SLOT_0) {
if (active.first == sd::MOUNTED) {
return true;
}
else {
return false;
}
}
else if (sdCard == sd::SLOT_1) {
if (active.second == sd::MOUNTED) {
return true;
}
else {
return false;
}
}
else {
sif::debug << "PlocUpdater::isSdCardMounted: Unknown SD card specified" << std::endl;
}
return false;
}
#endif /* #if BOARD_TE0720 == 0 */
void PlocUpdater::stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) {}
void PlocUpdater::stepSuccessfulReceived(ActionId_t actionId,
uint8_t step) {
}
void PlocUpdater::dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) {}
void PlocUpdater::stepFailedReceived(ActionId_t actionId, uint8_t step,
ReturnValue_t returnCode) {
}
void PlocUpdater::dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) {
}
void PlocUpdater::completionSuccessfulReceived(ActionId_t actionId) {
switch (pendingCommand) {
switch (pendingCommand) {
case (PLOC_SPV::UPDATE_AVAILABLE):
state = State::UPDATE_TRANSFER;
break;
case (PLOC_SPV::UPDATE_IMAGE_DATA):
if (remainingPackets == 0) {
packetsSent = 0; // Reset packets sent variable for next update sequence
state = State::UPDATE_VERIFY;
} else {
state = State::UPDATE_TRANSFER;
}
break;
break;
case (PLOC_SPV::UPDATE_IMAGE_DATA):
if (remainingPackets == 0) {
packetsSent = 0; // Reset packets sent variable for next update sequence
state = State::UPDATE_VERIFY;
}
else {
state = State::UPDATE_TRANSFER;
}
break;
case (PLOC_SPV::UPDATE_VERIFY):
triggerEvent(UPDATE_FINISHED);
state = State::IDLE;
pendingCommand = PLOC_SPV::NONE;
break;
triggerEvent(UPDATE_FINISHED);
state = State::IDLE;
pendingCommand = PLOC_SPV::NONE;
break;
default:
sif::debug << "PlocUpdater::completionSuccessfulReceived: Invalid pending command"
<< std::endl;
state = State::IDLE;
break;
}
sif::debug << "PlocUpdater::completionSuccessfulReceived: Invalid pending command"
<< std::endl;
state = State::IDLE;
break;
}
}
void PlocUpdater::completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) {
switch (pendingCommand) {
case (PLOC_SPV::UPDATE_AVAILABLE): {
triggerEvent(UPDATE_AVAILABLE_FAILED);
break;
void PlocUpdater::completionFailedReceived(ActionId_t actionId,
ReturnValue_t returnCode) {
switch(pendingCommand) {
case(PLOC_SPV::UPDATE_AVAILABLE): {
triggerEvent(UPDATE_AVAILABLE_FAILED);
break;
}
case (PLOC_SPV::UPDATE_IMAGE_DATA): {
triggerEvent(UPDATE_TRANSFER_FAILED, packetsSent);
break;
case(PLOC_SPV::UPDATE_IMAGE_DATA): {
triggerEvent(UPDATE_TRANSFER_FAILED, packetsSent);
break;
}
case (PLOC_SPV::UPDATE_VERIFY): {
triggerEvent(UPDATE_VERIFY_FAILED);
break;
case(PLOC_SPV::UPDATE_VERIFY): {
triggerEvent(UPDATE_VERIFY_FAILED);
break;
}
default:
sif::debug << "PlocUpdater::completionFailedReceived: Invalid pending command " << std::endl;
break;
}
state = State::IDLE;
sif::debug << "PlocUpdater::completionFailedReceived: Invalid pending command "
<< std::endl;
break;
}
state = State::IDLE;
}
void PlocUpdater::commandUpdateAvailable() {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = RETURN_OK;
if (not std::filesystem::exists(updateFile)) {
triggerEvent(UPDATE_FILE_NOT_EXISTS, static_cast<uint8_t>(state));
state = State::IDLE;
if (not std::filesystem::exists(updateFile)) {
triggerEvent(UPDATE_FILE_NOT_EXISTS, static_cast<uint8_t>(state));
state = State::IDLE;
return;
}
std::ifstream file(updateFile, std::ifstream::binary);
file.seekg(0, file.end);
imageSize = static_cast<size_t>(file.tellg());
file.close();
numOfUpdatePackets = imageSize / MAX_SP_DATA ;
if (imageSize % MAX_SP_DATA) {
numOfUpdatePackets++;
}
remainingPackets = numOfUpdatePackets;
packetsSent = 0;
calcImageCrc();
PLOC_SPV::UpdateInfo packet(PLOC_SPV::APID_UPDATE_AVAILABLE, static_cast<uint8_t>(image),
static_cast<uint8_t>(partition), imageSize, imageCrc, numOfUpdatePackets);
result = commandActionHelper.commandAction(objects::PLOC_SUPERVISOR_HANDLER,
PLOC_SPV::UPDATE_AVAILABLE, packet.getWholeData(), packet.getFullSize());
if (result != RETURN_OK) {
sif::warning << "PlocUpdater::commandUpdateAvailable: Failed to send update available"
<< " packet to supervisor handler" << std::endl;
triggerEvent(ACTION_COMMANDING_FAILED, result, PLOC_SPV::UPDATE_AVAILABLE);
state = State::IDLE;
pendingCommand = PLOC_SPV::NONE;
return;
}
pendingCommand = PLOC_SPV::UPDATE_AVAILABLE;
state = State::COMMAND_EXECUTING;
return;
}
std::ifstream file(updateFile, std::ifstream::binary);
file.seekg(0, file.end);
imageSize = static_cast<size_t>(file.tellg());
file.close();
numOfUpdatePackets = imageSize / MAX_SP_DATA;
if (imageSize % MAX_SP_DATA) {
numOfUpdatePackets++;
}
remainingPackets = numOfUpdatePackets;
packetsSent = 0;
calcImageCrc();
PLOC_SPV::UpdateInfo packet(PLOC_SPV::APID_UPDATE_AVAILABLE, static_cast<uint8_t>(image),
static_cast<uint8_t>(partition), imageSize, imageCrc,
numOfUpdatePackets);
result = commandActionHelper.commandAction(objects::PLOC_SUPERVISOR_HANDLER,
PLOC_SPV::UPDATE_AVAILABLE, packet.getWholeData(),
packet.getFullSize());
if (result != RETURN_OK) {
sif::warning << "PlocUpdater::commandUpdateAvailable: Failed to send update available"
<< " packet to supervisor handler" << std::endl;
triggerEvent(ACTION_COMMANDING_FAILED, result, PLOC_SPV::UPDATE_AVAILABLE);
state = State::IDLE;
pendingCommand = PLOC_SPV::NONE;
return;
}
pendingCommand = PLOC_SPV::UPDATE_AVAILABLE;
state = State::COMMAND_EXECUTING;
return;
}
void PlocUpdater::commandUpdatePacket() {
ReturnValue_t result = RETURN_OK;
uint16_t payloadLength = 0;
ReturnValue_t result = RETURN_OK;
uint16_t payloadLength = 0;
if (not std::filesystem::exists(updateFile)) {
triggerEvent(UPDATE_FILE_NOT_EXISTS, static_cast<uint8_t>(state), packetsSent);
state = State::IDLE;
return;
}
if (not std::filesystem::exists(updateFile)) {
triggerEvent(UPDATE_FILE_NOT_EXISTS, static_cast<uint8_t>(state), packetsSent);
state = State::IDLE;
return;
}
std::ifstream file(updateFile, std::ifstream::binary);
file.seekg(packetsSent * MAX_SP_DATA, file.beg);
std::ifstream file(updateFile, std::ifstream::binary);
file.seekg(packetsSent * MAX_SP_DATA, file.beg);
if (remainingPackets == 1) {
payloadLength = imageSize - static_cast<uint16_t>(file.tellg());
} else {
payloadLength = MAX_SP_DATA;
}
if (remainingPackets == 1) {
payloadLength = imageSize - static_cast<uint16_t>(file.tellg());
}
else {
payloadLength = MAX_SP_DATA;
}
PLOC_SPV::UpdatePacket packet(payloadLength);
file.read(reinterpret_cast<char*>(packet.getDataFieldPointer()), payloadLength);
file.close();
// sequence count of first packet is 1
packet.setPacketSequenceCount((packetsSent + 1) & PLOC_SPV::SEQUENCE_COUNT_MASK);
if (numOfUpdatePackets > 1) {
adjustSequenceFlags(packet);
}
packet.makeCrc();
PLOC_SPV::UpdatePacket packet(payloadLength);
file.read(reinterpret_cast<char*>(packet.getDataFieldPointer()), payloadLength);
file.close();
// sequence count of first packet is 1
packet.setPacketSequenceCount((packetsSent + 1) & PLOC_SPV::SEQUENCE_COUNT_MASK);
if (numOfUpdatePackets > 1) {
adjustSequenceFlags(packet);
}
packet.makeCrc();
result = commandActionHelper.commandAction(objects::PLOC_SUPERVISOR_HANDLER,
PLOC_SPV::UPDATE_IMAGE_DATA, packet.getWholeData(),
packet.getFullSize());
result = commandActionHelper.commandAction(objects::PLOC_SUPERVISOR_HANDLER,
PLOC_SPV::UPDATE_IMAGE_DATA, packet.getWholeData(), packet.getFullSize());
if (result != RETURN_OK) {
sif::warning << "PlocUpdater::commandUpdateAvailable: Failed to send update"
<< " packet to supervisor handler" << std::endl;
triggerEvent(ACTION_COMMANDING_FAILED, result, PLOC_SPV::UPDATE_IMAGE_DATA);
state = State::IDLE;
pendingCommand = PLOC_SPV::NONE;
return;
}
if (result != RETURN_OK) {
sif::warning << "PlocUpdater::commandUpdateAvailable: Failed to send update"
<< " packet to supervisor handler" << std::endl;
triggerEvent(ACTION_COMMANDING_FAILED, result, PLOC_SPV::UPDATE_IMAGE_DATA);
state = State::IDLE;
pendingCommand = PLOC_SPV::NONE;
return;
}
remainingPackets--;
packetsSent++;
remainingPackets--;
packetsSent++;
pendingCommand = PLOC_SPV::UPDATE_IMAGE_DATA;
state = State::COMMAND_EXECUTING;
pendingCommand = PLOC_SPV::UPDATE_IMAGE_DATA;
state = State::COMMAND_EXECUTING;
}
void PlocUpdater::commandUpdateVerify() {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = RETURN_OK;
PLOC_SPV::UpdateInfo packet(PLOC_SPV::APID_UPDATE_VERIFY, static_cast<uint8_t>(image),
static_cast<uint8_t>(partition), imageSize, imageCrc,
numOfUpdatePackets);
PLOC_SPV::UpdateInfo packet(PLOC_SPV::APID_UPDATE_VERIFY, static_cast<uint8_t>(image),
static_cast<uint8_t>(partition), imageSize, imageCrc, numOfUpdatePackets);
result =
commandActionHelper.commandAction(objects::PLOC_SUPERVISOR_HANDLER, PLOC_SPV::UPDATE_VERIFY,
packet.getWholeData(), packet.getFullSize());
if (result != RETURN_OK) {
sif::warning << "PlocUpdater::commandUpdateAvailable: Failed to send update available"
<< " packet to supervisor handler" << std::endl;
triggerEvent(ACTION_COMMANDING_FAILED, result, PLOC_SPV::UPDATE_VERIFY);
state = State::IDLE;
pendingCommand = PLOC_SPV::NONE;
result = commandActionHelper.commandAction(objects::PLOC_SUPERVISOR_HANDLER,
PLOC_SPV::UPDATE_VERIFY, packet.getWholeData(), packet.getFullSize());
if (result != RETURN_OK) {
sif::warning << "PlocUpdater::commandUpdateAvailable: Failed to send update available"
<< " packet to supervisor handler" << std::endl;
triggerEvent(ACTION_COMMANDING_FAILED, result, PLOC_SPV::UPDATE_VERIFY);
state = State::IDLE;
pendingCommand = PLOC_SPV::NONE;
return;
}
state = State::COMMAND_EXECUTING;
pendingCommand = PLOC_SPV::UPDATE_VERIFY;
return;
}
state = State::COMMAND_EXECUTING;
pendingCommand = PLOC_SPV::UPDATE_VERIFY;
return;
}
void PlocUpdater::calcImageCrc() {
std::ifstream file(updateFile, std::ifstream::binary);
file.seekg(0, file.end);
uint32_t count;
uint32_t bit;
uint32_t remainder = INITIAL_REMAINDER_32;
char input;
for (count = 0; count < imageSize; count++) {
file.seekg(count, file.beg);
file.read(&input, 1);
remainder ^= (input << 16);
for (bit = 8; bit > 0; --bit) {
if (remainder & TOPBIT_32) {
remainder = (remainder << 1) ^ POLYNOMIAL_32;
} else {
remainder = (remainder << 1);
}
std::ifstream file(updateFile, std::ifstream::binary);
file.seekg(0, file.end);
uint32_t count;
uint32_t bit;
uint32_t remainder = INITIAL_REMAINDER_32;
char input;
for (count = 0; count < imageSize; count++) {
file.seekg(count, file.beg);
file.read(&input, 1);
remainder ^= (input << 16);
for (bit = 8; bit > 0; --bit) {
if (remainder & TOPBIT_32) {
remainder = (remainder << 1) ^ POLYNOMIAL_32;
} else {
remainder = (remainder << 1);
}
}
}
}
file.close();
imageCrc = (remainder ^ FINAL_XOR_VALUE_32);
file.close();
imageCrc = (remainder ^ FINAL_XOR_VALUE_32);
}
void PlocUpdater::adjustSequenceFlags(PLOC_SPV::UpdatePacket& packet) {
if (packetsSent == 0) {
packet.setSequenceFlags(static_cast<uint8_t>(PLOC_SPV::SequenceFlags::FIRST_PKT));
} else if (remainingPackets == 1) {
packet.setSequenceFlags(static_cast<uint8_t>(PLOC_SPV::SequenceFlags::LAST_PKT));
} else {
packet.setSequenceFlags(static_cast<uint8_t>(PLOC_SPV::SequenceFlags::CONTINUED_PKT));
}
if (packetsSent == 0) {
packet.setSequenceFlags(static_cast<uint8_t>(PLOC_SPV::SequenceFlags::FIRST_PKT));
}
else if (remainingPackets == 1) {
packet.setSequenceFlags(static_cast<uint8_t>(PLOC_SPV::SequenceFlags::LAST_PKT));
}
else {
packet.setSequenceFlags(static_cast<uint8_t>(PLOC_SPV::SequenceFlags::CONTINUED_PKT));
}
}

View File

@ -2,170 +2,188 @@
#define MISSION_DEVICES_PLOCUPDATER_H_
#include "OBSWConfig.h"
#include "bsp_q7s/memory/SdCardManager.h"
#include "devicedefinitions/PlocSupervisorDefinitions.h"
#include "fsfw/action/ActionHelper.h"
#include "fsfw/action/CommandActionHelper.h"
#include "fsfw/action/CommandsActionsIF.h"
#include "fsfw/action/ActionHelper.h"
#include "fsfw/action/HasActionsIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/action/CommandsActionsIF.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tmtcpacket/SpacePacket.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "bsp_q7s/memory/SdCardManager.h"
#include "linux/fsfwconfig/objects/systemObjectList.h"
#include "fsfw/tmtcpacket/SpacePacket.h"
/**
* @brief An object of this class can be used to perform the software updates of the PLOC. The
* software update will be read from one of the SD cards, split into multiple space
* packets and sent to the PlocSupervisorHandler.
*
* @details The MPSoC has two boot memories (NVM0 and NVM1) where each stores two images (Partition
* A and Partition B)
* @details The MPSoC has two boot memories (NVM0 and NVM1) where each stores two images (Partition A
* and Partition B)
*
* @author J. Meier
*/
class PlocUpdater : public SystemObject,
public HasActionsIF,
public ExecutableObjectIF,
public HasReturnvaluesIF,
public CommandsActionsIF {
public:
static const ActionId_t UPDATE_A_UBOOT = 0;
static const ActionId_t UPDATE_A_BITSTREAM = 1;
static const ActionId_t UPDATE_A_LINUX = 2;
static const ActionId_t UPDATE_A_APP_SW = 3;
static const ActionId_t UPDATE_B_UBOOT = 4;
static const ActionId_t UPDATE_B_BITSTREAM = 5;
static const ActionId_t UPDATE_B_LINUX = 6;
static const ActionId_t UPDATE_B_APP_SW = 7;
public HasActionsIF,
public ExecutableObjectIF,
public HasReturnvaluesIF,
public CommandsActionsIF {
public:
PlocUpdater(object_id_t objectId);
virtual ~PlocUpdater();
static const ActionId_t UPDATE_A_UBOOT = 0;
static const ActionId_t UPDATE_A_BITSTREAM = 1;
static const ActionId_t UPDATE_A_LINUX = 2;
static const ActionId_t UPDATE_A_APP_SW = 3;
static const ActionId_t UPDATE_B_UBOOT = 4;
static const ActionId_t UPDATE_B_BITSTREAM = 5;
static const ActionId_t UPDATE_B_LINUX = 6;
static const ActionId_t UPDATE_B_APP_SW = 7;
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size);
MessageQueueId_t getCommandQueue() const;
ReturnValue_t initialize() override;
MessageQueueIF* getCommandQueuePtr() override;
void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) override;
void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) override;
void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) override;
void completionSuccessfulReceived(ActionId_t actionId) override;
void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) override;
PlocUpdater(object_id_t objectId);
virtual ~PlocUpdater();
private:
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_UPDATER;
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size);
MessageQueueId_t getCommandQueue() const;
ReturnValue_t initialize() override;
MessageQueueIF* getCommandQueuePtr() override;
void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) override;
void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) override;
void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) override;
void completionSuccessfulReceived(ActionId_t actionId) override;
void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) override;
//! [EXPORT] : [COMMENT] Updater is already performing an update
static const ReturnValue_t UPDATER_BUSY = MAKE_RETURN_CODE(0xA0);
//! [EXPORT] : [COMMENT] Received update command with invalid path string (too long).
static const ReturnValue_t NAME_TOO_LONG = MAKE_RETURN_CODE(0xA1);
//! [EXPORT] : [COMMENT] Received command to initiate update but SD card with update image not
//! mounted.
static const ReturnValue_t SD_NOT_MOUNTED = MAKE_RETURN_CODE(0xA2);
//! [EXPORT] : [COMMENT] Update file received with update command does not exist.
static const ReturnValue_t FILE_NOT_EXISTS = MAKE_RETURN_CODE(0xA3);
private:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_UPDATER;
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_UPDATER;
//! [EXPORT] : [COMMENT] Try to read update file but the file does not exist.
//! P1: Indicates in which state the file read fails
//! P2: During the update transfer the second parameter gives information about the number of
//! already sent packets
static const Event UPDATE_FILE_NOT_EXISTS = MAKE_EVENT(0, severity::LOW);
//! [EXPORT] : [COMMENT] Failed to send command to supervisor handler
//! P1: Return value of CommandActionHelper::commandAction
//! P2: Action ID of command to send
static const Event ACTION_COMMANDING_FAILED = MAKE_EVENT(1, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor handler replied action message indicating a command execution
//! failure of the update available command
static const Event UPDATE_AVAILABLE_FAILED = MAKE_EVENT(2, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor handler failed to transfer an update space packet.
//! P1: Parameter holds the number of update packets already sent (inclusive the failed packet)
static const Event UPDATE_TRANSFER_FAILED = MAKE_EVENT(3, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor failed to execute the update verify command.
static const Event UPDATE_VERIFY_FAILED = MAKE_EVENT(4, severity::LOW);
//! [EXPORT] : [COMMENT] MPSoC update successful completed
static const Event UPDATE_FINISHED = MAKE_EVENT(5, severity::INFO);
//! [EXPORT] : [COMMENT] Updater is already performing an update
static const ReturnValue_t UPDATER_BUSY = MAKE_RETURN_CODE(0xA0);
//! [EXPORT] : [COMMENT] Received update command with invalid path string (too long).
static const ReturnValue_t NAME_TOO_LONG = MAKE_RETURN_CODE(0xA1);
//! [EXPORT] : [COMMENT] Received command to initiate update but SD card with update image not mounted.
static const ReturnValue_t SD_NOT_MOUNTED = MAKE_RETURN_CODE(0xA2);
//! [EXPORT] : [COMMENT] Update file received with update command does not exist.
static const ReturnValue_t FILE_NOT_EXISTS = MAKE_RETURN_CODE(0xA3);
static const uint32_t QUEUE_SIZE = config::PLOC_UPDATER_QUEUE_SIZE;
static const size_t MAX_PLOC_UPDATE_PATH = 50;
static const size_t SD_PREFIX_LENGTH = 8;
// Maximum size of update payload data per space packet (max size of space packet is 1024 bytes)
static const size_t MAX_SP_DATA = 1016;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_UPDATER;
static const uint32_t TOPBIT_32 = (1 << 31);
static const uint32_t POLYNOMIAL_32 = 0x04C11DB7;
static const uint32_t INITIAL_REMAINDER_32 = 0xFFFFFFFF;
static const uint32_t FINAL_XOR_VALUE_32 = 0xFFFFFFFF;
//! [EXPORT] : [COMMENT] Try to read update file but the file does not exist.
//! P1: Indicates in which state the file read fails
//! P2: During the update transfer the second parameter gives information about the number of already sent packets
static const Event UPDATE_FILE_NOT_EXISTS = MAKE_EVENT(0, severity::LOW);
//! [EXPORT] : [COMMENT] Failed to send command to supervisor handler
//! P1: Return value of CommandActionHelper::commandAction
//! P2: Action ID of command to send
static const Event ACTION_COMMANDING_FAILED = MAKE_EVENT(1, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor handler replied action message indicating a command execution failure of the update available command
static const Event UPDATE_AVAILABLE_FAILED = MAKE_EVENT(2, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor handler failed to transfer an update space packet.
//! P1: Parameter holds the number of update packets already sent (inclusive the failed packet)
static const Event UPDATE_TRANSFER_FAILED = MAKE_EVENT(3, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor failed to execute the update verify command.
static const Event UPDATE_VERIFY_FAILED = MAKE_EVENT(4, severity::LOW);
//! [EXPORT] : [COMMENT] MPSoC update successful completed
static const Event UPDATE_FINISHED = MAKE_EVENT(5, severity::INFO);
MessageQueueIF* commandQueue = nullptr;
static const uint32_t QUEUE_SIZE = config::PLOC_UPDATER_QUEUE_SIZE;
static const size_t MAX_PLOC_UPDATE_PATH = 50;
static const size_t SD_PREFIX_LENGTH = 8;
// Maximum size of update payload data per space packet (max size of space packet is 1024 bytes)
static const size_t MAX_SP_DATA = 1016;
static const uint32_t TOPBIT_32 = (1 << 31);
static const uint32_t POLYNOMIAL_32 = 0x04C11DB7;
static const uint32_t INITIAL_REMAINDER_32 = 0xFFFFFFFF;
static const uint32_t FINAL_XOR_VALUE_32 = 0xFFFFFFFF;
MessageQueueIF* commandQueue = nullptr;
#if BOARD_TE0720 == 0
SdCardManager* sdcMan = nullptr;
SdCardManager* sdcMan = nullptr;
#endif
CommandActionHelper commandActionHelper;
CommandActionHelper commandActionHelper;
ActionHelper actionHelper;
ActionHelper actionHelper;
enum class State : uint8_t {
IDLE,
UPDATE_AVAILABLE,
UPDATE_TRANSFER,
UPDATE_VERIFY,
COMMAND_EXECUTING
};
enum class State: uint8_t {
IDLE,
UPDATE_AVAILABLE,
UPDATE_TRANSFER,
UPDATE_VERIFY,
COMMAND_EXECUTING
};
State state = State::IDLE;
State state = State::IDLE;
ActionId_t pendingCommand = PLOC_SPV::NONE;
ActionId_t pendingCommand = PLOC_SPV::NONE;
enum class Image : uint8_t { NONE, A, B };
enum class Image: uint8_t {
NONE,
A,
B
};
Image image = Image::NONE;
Image image = Image::NONE;
enum class Partition : uint8_t { NONE, UBOOT, BITSTREAM, LINUX_OS, APP_SW };
enum class Partition: uint8_t {
NONE,
UBOOT,
BITSTREAM,
LINUX_OS,
APP_SW
};
Partition partition = Partition::NONE;
Partition partition = Partition::NONE;
uint32_t packetsSent = 0;
uint32_t remainingPackets = 0;
// Number of packets required to transfer the update image
uint32_t numOfUpdatePackets = 0;
uint32_t packetsSent = 0;
uint32_t remainingPackets = 0;
// Number of packets required to transfer the update image
uint32_t numOfUpdatePackets = 0;
std::string updateFile;
uint32_t imageSize = 0;
uint32_t imageCrc = 0;
std::string updateFile;
uint32_t imageSize = 0;
uint32_t imageCrc = 0;
void readCommandQueue();
void doStateMachine();
void readCommandQueue();
void doStateMachine();
/**
* @brief Extracts the path and name of the update image from the service 8 command data.
*/
ReturnValue_t getImageLocation(const uint8_t* data, size_t size);
/**
* @brief Extracts the path and name of the update image from the service 8 command data.
*/
ReturnValue_t getImageLocation(const uint8_t* data, size_t size);
ReturnValue_t checkNameLength(size_t size);
ReturnValue_t checkNameLength(size_t size);
/**
* @brief Prepares and sends update available command to PLOC supervisor handler.
*/
void commandUpdateAvailable();
/**
* @brief Prepares and sends update available command to PLOC supervisor handler.
*/
void commandUpdateAvailable();
/**
* @brief Prepares and sends and update packet to the PLOC supervisor handler.
*/
void commandUpdatePacket();
/**
* @brief Prepares and sends and update packet to the PLOC supervisor handler.
*/
void commandUpdatePacket();
/**
* @brief Prepares and sends the update verification packet to the PLOC supervisor handler.
*/
void commandUpdateVerify();
/**
* @brief Prepares and sends the update verification packet to the PLOC supervisor handler.
*/
void commandUpdateVerify();
void calcImageCrc();
#if BOARD_TE0720 == 0
/**
* @brief Checks whether the SD card to read from is mounted or not.
*/
bool isSdCardMounted(sd::SdCard sdCard);
#endif
void adjustSequenceFlags(PLOC_SPV::UpdatePacket& packet);
void calcImageCrc();
void adjustSequenceFlags(PLOC_SPV::UpdatePacket& packet);
};
#endif /* MISSION_DEVICES_PLOCUPDATER_H_ */

View File

@ -3,26 +3,31 @@
#include <fsfw/src/fsfw/serialize/SerialLinkedListAdapter.h>
class MemoryParams : public SerialLinkedListAdapter<SerializeIF> {
public:
/**
* @brief Constructor
* @param startAddress Start of address range to dump
* @param endAddress End of address range to dump
*/
MemoryParams(uint32_t startAddress, uint32_t endAddress)
: startAddress(startAddress), endAddress(endAddress) {
setLinks();
}
class MemoryParams: public SerialLinkedListAdapter<SerializeIF> {
public:
private:
void setLinks() {
setStart(&startAddress);
startAddress.setNext(&endAddress);
}
/**
* @brief Constructor
* @param startAddress Start of address range to dump
* @param endAddress End of address range to dump
*/
MemoryParams(uint32_t startAddress, uint32_t endAddress) :
startAddress(startAddress), endAddress(endAddress) {
setLinks();
}
private:
void setLinks() {
setStart(&startAddress);
startAddress.setNext(&endAddress);
}
SerializeElement<uint32_t> startAddress;
SerializeElement<uint32_t> endAddress;
SerializeElement<uint32_t> startAddress;
SerializeElement<uint32_t> endAddress;
};
#endif /* BSP_Q7S_DEVICES_DEVICEDEFINITIONS_PLOCMEMDUMPDEFINITIONS_H_ */

Some files were not shown because too many files have changed in this diff Show More