diff --git a/.gitignore b/.gitignore
index f6adc50a..2ccfca61 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,8 +2,21 @@ _obj
_bin
_dep
+Debug
+Debug*
+Release
+Release*
+MinSizeRel
+MinSizeRel*
+RelWithDebInfo
+RelWithDebInfo*
+
.settings
.metadata
.project
.cproject
__pycache__
+
+!misc/eclipse/**/.cproject
+!misc/eclipse/**/.project
+/eive_obsw cmake debug/
diff --git a/.gitmodules b/.gitmodules
index 8b5921a8..6f538287 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,12 +1,21 @@
[submodule "etl"]
- path = etl
+ path = thirdparty/etl
url = https://github.com/ETLCPP/etl.git
-[submodule "tmtc"]
- path = tmtc
- url = https://git.ksat-stuttgart.de/Robin.Mueller/tmtc.git
[submodule "arduino"]
path = arduino
url = https://egit.irs.uni-stuttgart.de/eive/eive_arduino_interface.git
[submodule "fsfw"]
path = fsfw
url = https://egit.irs.uni-stuttgart.de/eive/fsfw.git
+[submodule "tmtc"]
+ path = tmtc
+ url = https://egit.irs.uni-stuttgart.de/eive/eive_tmtc.git
+[submodule "thirdparty/lwgps"]
+ path = thirdparty/lwgps
+ url = https://github.com/rmspacefish/lwgps.git
+[submodule "fsfw_hal"]
+ path = fsfw_hal
+ url = https://egit.irs.uni-stuttgart.de/fsfw/fsfw_hal.git
+[submodule "generators/modgen"]
+ path = generators/modgen
+ url = https://git.ksat-stuttgart.de/source/modgen.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 00000000..6e4eb527
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,228 @@
+################################################################################
+# CMake support for the EIVE OBSW
+#
+# Developed in an effort to replace Make with a modern build system.
+#
+# Author: R. Mueller
+################################################################################
+
+################################################################################
+# Pre-Project preparation
+################################################################################
+cmake_minimum_required(VERSION 3.13)
+
+# set(CMAKE_VERBOSE TRUE)
+
+set(CMAKE_SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
+option(ADD_ETL_LIB "Add ETL library" ON)
+if(NOT OS_FSFW)
+ set(OS_FSFW host CACHE STRING "OS for the FSFW.")
+endif()
+
+# Perform steps like loading toolchain files where applicable.
+include(${CMAKE_SCRIPT_PATH}/PreProjectConfig.cmake)
+pre_project_config()
+
+# Project Name
+project(eive_obsw ASM C CXX)
+
+################################################################################
+# Pre-Sources preparation
+################################################################################
+
+# Specify the C++ standard
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+# Set names and variables
+set(TARGET_NAME ${CMAKE_PROJECT_NAME})
+set(LIB_FSFW_NAME fsfw)
+set(LIB_ETL_NAME etl)
+set(LIB_CSP_NAME libcsp)
+set(LIB_FSFW_HAL_NAME fsfw_hal)
+set(LIB_LWGPS_NAME lwgps)
+set(THIRD_PARTY_FOLDER thirdparty)
+
+# Set path names
+set(FSFW_PATH fsfw)
+set(MISSION_PATH mission)
+set(TEST_PATH test/testtasks)
+set(LINUX_PATH linux)
+set(COMMON_PATH common)
+
+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(FSFW_WARNING_SHADOW_LOCAL_GCC OFF)
+set(ADD_LINUX_FILES TRUE)
+
+# Analyse different OS and architecture/target options, determine BSP_PATH,
+# display information about compiler etc.
+include (${CMAKE_SCRIPT_PATH}/HardwareOsPreConfig.cmake)
+pre_source_hw_os_config()
+
+if(TGT_BSP)
+ if(${TGT_BSP} MATCHES "arm/q7s" OR ${TGT_BSP} MATCHES "arm/raspberrypi")
+ set(ROOT_CONFIG_FOLDER TRUE)
+ set(FSFW_CONFIG_PATH "fsfwconfig")
+ set(ADD_LINUX_FILES TRUE)
+ set(ADD_CSP_LIB TRUE)
+ set(FSFW_HAL_ADD_LINUX ON)
+ endif()
+
+ if(${TGT_BSP} MATCHES "arm/raspberrypi")
+ add_definitions(-DRASPBERRY_PI)
+ set(FSFW_HAL_ADD_RASPBERRY_PI ON)
+ endif()
+
+ if(${TGT_BSP} MATCHES "arm/q7s")
+ add_definitions(-DXIPHOS_Q7S)
+ endif()
+else()
+ # Required by FSFW library
+ set(FSFW_CONFIG_PATH "${BSP_PATH}/fsfwconfig")
+endif()
+# Set for lwgps library
+set(LWGPS_CONFIG_PATH "${COMMON_PATH}/config")
+
+################################################################################
+# Executable and Sources
+################################################################################
+
+# Add executable
+add_executable(${TARGET_NAME})
+
+# Add subdirectories
+if(ROOT_CONFIG_FOLDER)
+ add_subdirectory(${FSFW_CONFIG_PATH})
+endif()
+
+if(ADD_CSP_LIB)
+ add_subdirectory(${CSP_LIB_PATH})
+endif()
+
+if(ADD_ETL_LIB)
+ add_subdirectory(${ETL_LIB_PATH})
+endif()
+
+if(ADD_LINUX_FILES)
+ add_subdirectory(${LINUX_PATH})
+endif()
+
+add_subdirectory(${LWGPS_LIB_PATH})
+add_subdirectory(${BSP_PATH})
+add_subdirectory(${FSFW_PATH})
+add_subdirectory(${MISSION_PATH})
+add_subdirectory(${TEST_PATH})
+add_subdirectory(${FSFW_HAL_LIB_PATH})
+add_subdirectory(${COMMON_PATH})
+
+################################################################################
+# Post-Sources preparation
+################################################################################
+
+set_property(CACHE OS_FSFW PROPERTY STRINGS host linux)
+
+# Add libraries for all sources.
+target_link_libraries(${TARGET_NAME} PRIVATE
+ ${LIB_FSFW_NAME}
+ ${LIB_OS_NAME}
+ ${LIB_LWGPS_NAME}
+ ${LIB_FSFW_HAL_NAME}
+)
+
+if(ADD_ETL_LIB)
+ target_link_libraries(${TARGET_NAME} PRIVATE
+ ${LIB_ETL_NAME}
+ )
+endif()
+
+if(ADD_CSP_LIB)
+ target_link_libraries(${TARGET_NAME} PRIVATE
+ ${LIB_CSP_NAME}
+ )
+endif()
+
+# Add include paths for all sources.
+target_include_directories(${TARGET_NAME} PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${FSFW_CONFIG_PATH}
+)
+
+
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ set(WARNING_FLAGS
+ -Wall
+ -Wextra
+ -Wimplicit-fallthrough=1
+ -Wno-unused-parameter
+ -Wno-psabi
+ )
+
+ # Remove unused sections.
+ target_compile_options(${TARGET_NAME} PRIVATE
+ "-ffunction-sections"
+ "-fdata-sections"
+ )
+
+ # Removed unused sections.
+ target_link_options(${TARGET_NAME} PRIVATE
+ "-Wl,--gc-sections"
+ )
+
+elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ set(COMPILER_FLAGS "/permissive-")
+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)
+ post_source_hw_os_config()
+endif()
+
+if(NOT CMAKE_SIZE)
+ set(CMAKE_SIZE size)
+ if(WIN32)
+ set(FILE_SUFFIX ".exe")
+ endif()
+endif()
+
+if(TGT_BSP)
+ set(TARGET_STRING "Target BSP: ${TGT_BSP}")
+else()
+ set(TARGET_STRING "Target BSP: Hosted")
+endif()
+
+string(CONCAT POST_BUILD_COMMENT
+ "Build directory: ${CMAKE_BINARY_DIR}\n"
+ "Target OSAL: ${OS_FSFW}\n"
+ "Target Build Type: ${CMAKE_BUILD_TYPE}\n"
+ "${TARGET_STRING}"
+)
+
+add_custom_command(
+ TARGET ${TARGET_NAME}
+ POST_BUILD
+ COMMAND ${CMAKE_SIZE} ${TARGET_NAME}${FILE_SUFFIX}
+ COMMENT ${POST_BUILD_COMMENT}
+)
+
+include (${CMAKE_SCRIPT_PATH}/BuildType.cmake)
+set_build_type()
+
+
+
+
+
diff --git a/Makefile b/Makefile
index 04a263ef..b1ccd741 100644
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,7 @@ SHELL = /bin/sh
# Chip & board used for compilation
# (can be overriden by adding CHIP=chip and BOARD=board to the command-line)
-BOARD_FILE_ROOT = bsp_linux
+BOARD_FILE_ROOT = bsp_q7s
BOARD = linux
OS_FSFW = linux
CUSTOM_DEFINES += -D$(OS_FSFW)
@@ -25,6 +25,7 @@ MISSION_PATH = mission
CONFIG_PATH = fsfwconfig
TEST_PATH = test
UNITTEST_PATH = unittest
+LIBCSP_PATH = libcsp
# Board specific paths
BSP_PATH = $(BOARD_FILE_ROOT)
@@ -113,7 +114,7 @@ INCLUDES :=
# Directories where $(directoryname).mk files should be included from
SUBDIRS := $(FRAMEWORK_PATH) $(TEST_PATH) $(BSP_PATH) $(UNITTEST_PATH)\
- $(CONFIG_PATH) $(MISSION_PATH)
+ $(CONFIG_PATH) $(MISSION_PATH) $(LIBCSP_PATH)
# INCLUDES += framework/test/catch2
# ETL library include.
@@ -278,7 +279,7 @@ cleanbin:
-rm -rf $(BUILDPATH)/$(OUTPUT_FOLDER)
# Build target configuration
-release: OPTIMIZATION = -Os $(PROTOTYPE_OPTIMIZATION) $(LINK_TIME_OPTIMIZATION)
+release: OPTIMIZATION = -O2 $(PROTOTYPE_OPTIMIZATION) $(LINK_TIME_OPTIMIZATION)
release: LINK_TIME_OPTIMIZATION = -flto
release: TARGET = Release
release: OPTIMIZATION_MESSAGE = On with Link Time Optimization
diff --git a/Makefile-Hosted b/Makefile-Hosted
index bb56fec5..3a93f625 100644
--- a/Makefile-Hosted
+++ b/Makefile-Hosted
@@ -15,14 +15,14 @@ CUSTOM_DEFINES :=
# Chip & board used for compilation
# (can be overriden by adding CHIP=chip and BOARD=board to the command-line)
-BOARD_FILE_ROOT = hosted
+BOARD_FILE_ROOT = bsp_hosted
BOARD = host
-OS_FSFW = host
-CUSTOM_DEFINES += -D$(OS_FSFW)
+DETECTED_OS :=
# Copied from stackoverflow, can be used to differentiate between Windows
# and Linux
ifeq ($(OS),Windows_NT)
+ DETECTED_OS = WINDOWS
CUSTOM_DEFINES += -DWIN32
ifeq ($(PROCESSOR_ARCHITEW6432),AMD64)
CUSTOM_DEFINES += -DAMD64
@@ -55,6 +55,14 @@ else
endif
endif
+ifeq (${DETECTED_OS}, WINDOWS)
+OS_FSFW = host
+else
+OS_FSFW = linux
+endif
+
+CUSTOM_DEFINES += -D$(OS_FSFW)
+
# General folder paths
FRAMEWORK_PATH = fsfw
MISSION_PATH = mission
@@ -179,10 +187,10 @@ $(foreach S,$(SUBDIRS),$(eval $(INCLUDE_FILE)))
# VPATH += mission/pus/
-ifeq ($(DETECTED_OS), LINUX)
-CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TcUnixUdpPollingTask.cpp
-CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TmTcUnixUdpBridge.cpp
-endif
+#ifeq ($(DETECTED_OS), LINUX)
+#CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TcUnixUdpPollingTask.cpp
+#CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TmTcUnixUdpBridge.cpp
+#endif
# All C Sources included by .mk files are assigned here
# Add the objects to sources so dependency handling works
@@ -227,7 +235,6 @@ DEAD_CODE_REMOVAL = -Wl,--gc-sections
# Link time is larger and size of object files can not be retrieved
# but resulting binary is smaller. Could be used in mission/deployment build
# Requires -ffunction-section in linker call
-LINK_TIME_OPTIMIZATION = -flto
OPTIMIZATION += $(PROTOTYPE_OPTIMIZATION)
endif
@@ -261,12 +268,12 @@ ASFLAGS = -Wall -g $(OPTIMIZATION) $(I_INCLUDES) -D__ASSEMBLY__
# LINK_INCLUDES specify the path to used libraries and the linker script
# LINK_LIBRARIES link HCC and HAL library and enable float support
LDFLAGS := -g3 -pthread $(DEAD_CODE_REMOVAL) $(OPTIMIZATION)
-
-LINK_INCLUDES :=
-
LINK_LIBRARIES :=
+
ifeq ($(OS),Windows_NT)
LINK_LIBRARIES += -lwsock32 -lws2_32
+else
+LINK_LIBRARIES += -lrt
endif
# Gnu Coverage Tools Flags
@@ -309,7 +316,10 @@ all: executable
# Build target configuration
release: OPTIMIZATION = -Os $(PROTOTYPE_OPTIMIZATION) $(LINK_TIME_OPTIMIZATION)
+# Problematic on MinGW
+ifneq ($(OS),Windows_NT)
release: LINK_TIME_OPTIMIZATION = -flto
+endif
release: TARGET = Release
release: OPTIMIZATION_MESSAGE = On with Link Time Optimization
release: DEBUG_LEVEL = -g0
diff --git a/README.md b/README.md
index 71f7860e..38df4443 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
Target systems:
-* OBC
+* OBC with Linux OS
* Xiphos Q7S
* Based on Zynq-7020 SoC (xc7z020clg484-2)
* Dual-core ARM Cortex-A9
@@ -12,56 +12,157 @@ Target systems:
* Artix-7 FPGA (85K pogrammable logic cells)
* Datasheet at https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Arbeitsdaten/08_Used%20Components/Q7S&fileid=340648
* Also a lot of informatin about the Q7S can be found on the xiphos trac platform: https://trac.xiphos.com/trac/eive-q7/wiki/Q7RevB
-* Linux OS
- * Built with Yocto 2.5
+ * Linux OS built with Yocto 2.5
* Linux Kernel https://github.com/XiphosSystemsCorp/linux-xlnx.git
* Host System
* Generic software components which are not dependant on hardware can also
- be run. All host code is contained in the hosted folder
+ be run on a host system. All host code is contained in the `bsp_hosted` folder
* Tested for Linux (Ubuntu 20.04) and Windows 10
+* Raspberry Pi
+ * EIVE OBC can be built for Raspberry Pi as well (either directly on Raspberry Pi or by installing a cross compiler)
+The steps in the primary README are related to the main OBC target Q7S.
+The CMake build system can be used to generate build systems as well (see helper scripts in `cmake/scripts`:
+
+- Linux (Raspberry Pi): See special section below.
+- Linux Host: Uses the `bsp_hosted` BSP folder and the CMake Unix Makefiles generator.
+- Windows Host: Uses the `bsp_hosted` BSP folder, the CMake MinGW Makefiles generator and MSYS2.
## Setting up development environment
+
+### Installing Vivado the the Xilinx development tools
+
+It's also possible to perform debugging with a normal Eclipse installation by installing
+the TCF plugin. Still, it is necessary to install Vivado to get the toolchain for generating
+C++ applications. Alternatively you can download the toolchain
+[from the cloud](https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Arbeitsdaten/08_Used%20Components/Q7S/Toolchain&fileid=422486).
+
* Install Vivado 2018.2 and Xilinx SDK from https://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/vivado-design-tools/archive.html.
- Install the Vivado Design Suite - HLx Editions - 2018.2 Full Product Installation instead of the updates. It is recommended to use the installer
+ Install the Vivado Design Suite - HLx Editions - 2018.2 Full Product Installation instead of the updates. It is recommended to use the installer.
+
* Install settings. In the Devices selection, it is sufficient to pick SoC → Zynq-7000:
-
+
+
+
+
+
+
+
* For supported OS refer to https://www.xilinx.com/support/documentation/sw_manuals/xilinx2018_2/ug973-vivado-release-notes-install-license.pdf
-* Add path of linux cross-compiler to environment variables SDK\2018.2\gnu\aarch32\nt\gcc-arm-linux-gnueabi\bin
-* Install make (only on windows, SDK on Linux can use the make installed with the SDK)
+* Add path of linux cross-compiler to permanent environment variables (`.profile` file in Linux):
+ `\SDK\2018.2\gnu\aarch32\nt\gcc-arm-linux-gnueabi\bin`
+ or set up path each time before debugging.
-### Installing make on Windows
-1. Install NodeJS LTS
-2. Install xpm
-
-```sh
-npm install --global xpm
-```
+### Installing CMake and MSYS2 on Windows
-3. Install Windows build tools (after installation also linux commands like mkdir can be used from windows)
+1. Install [MSYS2](https://www.msys2.org/) and [CMake](https://cmake.org/download/) first.
-```sh
-xpm install --global @xpack-dev-tools/windows-build-tools@latest
-```
+2. Open the MinGW64 console. It is recommended to set up aliases in `.bashrc` to navigate to the
+ software repository quickly
+
+3. Run the following commands in MinGW64
-## Building the software
+ ```sh
+ pacman -Syuuu
+ ```
+
+ It is recommended to install the full base development toolchain
+
+ ```sh
+ pacman -S base-devel
+ ```
+
+ It is also possible to only install required packages
+
+ ```sh
+ pacman -S mingw-w64-x86_64-cmake mingw-w64-x86_64-make mingw-w64-x86_64-gcc mingw-w64-x86_64-gdb python3
+ ```
+
+### Installing CMake on Linux
+
+1. Run the following command
+
+ ```sh
+ sudo apt-get install cmake
+ ````
+
+## Getting the Q7S system root
+
+It is necessary to copy the Q7S system root to your local development machine for libraries
+like `libgpio`. You can find the system root [here](https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Arbeitsdaten/08_Used%20Components/Q7S/Toolchain&fileid=422486). Download it and unzip it somewhere in the Xilinx installation folder.
+
+Then, create a new environmental variables `Q7S_SYSROOT` and set it to the local system root path.
+
+## Building the software with CMake
+
+When using Windows, run theses steps in MSYS2.
1. Clone the repository with
-```sh
-git clone https://egit.irs.uni-stuttgart.de/eive/eive_obsw.git
-```
+
+ ```sh
+ git clone https://egit.irs.uni-stuttgart.de/eive/eive_obsw.git
+ ```
2. Update all the submodules
-```sh
-git submodule init
-git submodule sync
-git submodule update
-```
-3. Open Xilinx SDK 2018.2
-4. Import project
+ ```sh
+ git submodule init
+ git submodule sync
+ git submodule update
+ ```
+
+3. Ensure that the cross-compiler is working with `arm-linux-gnueabihf-gcc --version`.
+ It is recommended to run the shell script `win_path_helper_xilinx_tools.sh` in `cmake/scripts/Q7S`
+ or to set up the [PATH and the CROSS_COMPILE variable permanently](https://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path)
+ in the `.profile` file.
+
+4. Run the CMake configuration to create the build system in a `Debug` folder.
+ Navigate into the `eive_obsw` folder first.
+
+ ```sh
+ cd cmake/scripts/Q7S
+ ./create_cmake_debug.sh
+ cd ../../..
+ ```
+
+ This will invoke a Python script which in turn invokes CMake with the correct
+ arguments to configure CMake for Q7S cross-compilation.
+
+5. Build the software with
+ ```sh
+ cd Debug
+ cmake --build . -j
+ ```
+
+## Setting up default Eclipse for Q7S projects - TCF agent
+
+The [TCF agent](https://wiki.eclipse.org/TCF) can be used to perform remote debugging on the Q7S.
+
+1. Install the TCF agent plugin in Eclipse from the [releases](https://www.eclipse.org/tcf/downloads.php). Go to Help → Install New Software and use the download page, for example https://download.eclipse.org/tools/tcf/releases/1.6/1.6.2/ to search for the plugin and install it.
+
+2. Go to Window → Perspective → Open Perspective and open the **Target Explorer Perspective**.
+ Here, the Q7S should show up if the local port forwarding was set up as explained previously. Please note that you have to connect to `localhost` and port `1534` with port forwaring set up.
+
+3. A launch configuration was provided, but it might be necessary to adapt it for your own needs. Alternatively:
+
+ - Create a new **TCF Remote Application** by pressing the cogs button at the top or going to Run → Debug Configurations → Remote Application and creating a new one there.
+
+ - Set up the correct image in the main tab (it might be necessary to send the image to the Q7S manually once) and file transfer properties
+
+ - It is also recommended to link the correct Eclipse project.
+
+After that, comfortable remote debugging should be possible with the Debug button.
+
+A build configuration and a shell helper script has been provided to set up the path variables and
+build the Q7S binary on Windows, but a launch configuration needs to be newly created because the
+IP address and path settings differ from machine to machine.
+
+## Building in Xilinx SDK 2018.2
+
+1. Open Xilinx SDK 2018.2
+2. Import project
* File → Import → C/C++ → Existing Code as Makefile Project
-5. Set build command. Replace \ with either debug or release.
+3. Set build command. Replace \ with either debug or release.
* When on Linux right click project → Properties → C/C++ Build → Set build command to `make -j`
* -j causes the compiler to use all available cores
* The target is used to either compile the debug or the optimized release build.
@@ -70,153 +171,189 @@ git submodule update
* Target name: all
* Uncheck "Same as the target name"
* Uncheck "Use builder settings"
- * As build command type: `make -j WINDOWS=1`
-6. Run build command by double clicking the created target or by right clicking
+ * As build command type: `cmake --build .`
+ * In the Behaviour tab, you can enable build acceleration
+4. Run build command by double clicking the created target or by right clicking
the project folder and selecting Build Project.
-## Debugging the software (when workstation is directly conncected to Q7S)
-1. Assign static IP address to Q7S
- * Open serial console of Q7S (Accessible via the micro-USB of the PIM, see also Q7S user maunal chapter 10.3)
- * Baudrate 115200
- * Login to Q7S:
- * user: root
- * pw: root
- * Set IP address and netmask with
-
- ```sh
+## TCF-Agent
+
+1. On reboot, some steps have to be taken on the Q7S. Set static IP address and netmask
+
+ ```sh
ifconfig eth0 192.168.133.10
ifconfig eth0 netmask 255.255.255.0
```
-2. Connect Q7S to workstation via ethernet
-3. Make sure the netmask of the ehternet interface of the workstation matches the netmask of the Q7S
- * When IP address is set to 192.168.133.10 and the netmask is 255.255.255.0, an example IP address for the workstation
- is 192.168.133.2
-4. Run tcf-agent on Q7S
- * Tcf-agent is not yet integrated in the rootfs of the Q7S. Therefore build tcf-agent manually
-
- ```sh
- git clone git://git.eclipse.org/gitroot/tcf/org.eclipse.tcf.agent.git
- cd org.eclipse.tcf.agent/agent
- make CC=arm-linux-gnueabihf-gcc LD=arm-linux-gnueabihf-ld MACHINE=arm NO_SSL=1 NO_UUID=1
- ```
+2. `tcfagent` application should run automatically but this can be checked with
+ ```sh
+ systemctl status tcfagent
+ ```
- * Transfer executable agent from org.eclipse.tcf.agent/agent/obj/GNU/Linux/arm/Debug to /tmp of Q7S
-
- ```sh
- cd obj/GNU/Linux/arm/Debug
- scp agent root@192.168.133.10:/tmp
- ```
-
- * On Q7S
- ```sh
- cd /tmp
- chmod +x agent
- ```
-
- * Run agent
- ```sh
- ./agent
- ```
-
-5. In Xilinx SDK 2018.2 right click on project → Debug As → Debug Configurations
-6. Right click Xilinx C/C++ applicaton (System Debugger) → New →
-7. Set Debug Type to Linux Application Debug and Connectin to Linux Agent
-8. Click New
-9. Give connection a name
-10. Set Host to static IP address of Q7S. e.g. 192.168.133.10
-11. Test connection (This ensures the TCF Agent is running on the Q7S)
-12. Select Application tab
- * Project Name: eive_obsw
- * Local File Path: Path to eiveobsw-linux.elf (in _bin\linux\devel)
- * Remote File Path: /tmp/eive_obsw.elf
+3. If the agent is not running, check whether `agent` is located inside `usr/bin`.
+ You can run it manually there. To perform auto-start on boot, have a look at the start-up
+ application section.
## Debugging the software via Flatsat PC
+
Open SSH connection to flatsat PC:
-````
+
+```sh
+ssh eive@flatsat.eive.absatvirt.lw
+```
+
+or
+
+```sh
ssh eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5
-````
-To access the console of the Q7S run the following:
+```
+
+or
+
+```sh
+ssh eive@192.168.199.227
+```
+
+If the static IP address of the Q7S has already been set,
+you can access it with ssh
+
+```sh
+ssh root@192.168.133.10
+```
+
+If this has not been done yet, you can access the serial
+console of the Q7S like this to set it
+
```sh
picocom -b 115200 /dev/ttyUSB0
```
+
+If the serial port is blocked for some reason, you can kill
+the process using it with `q7s_kill`.
+
+You can use `AltGr` + `X` to exit the picocom session.
+
To debug an application, first make sure a static IP address is assigned to the Q7S. Run ifconfig on the Q7S serial console.
-````
+
+```sh
ifconfig
-````
+```
+
Set IP address and netmask with
-````
+
+```sh
ifconfig eth0 192.168.133.10
ifconfig eth0 netmask 255.255.255.0
-````
-To launch application from Xilinx SDK setup port fowarding on the localhost.
-````
-ssh -L 1534:192.168.133.10:1534 eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5
-````
+```
+
+To launch application from Xilinx SDK setup port fowarding on the development machine
+(not on the flatsat!)
+
+```sh
+ssh -L 1534:192.168.133.10:1534 eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 -t bash
+```
+
This forwards any requests to localhost:1534 to the port 1534 of the Q7S with the IP address 192.168.133.10.
+This needs to be done every time, so it is recommended to create an alias to do this quickly.
-Note: When now setting up a debug session in the Xilinx SDK, the host must be set to localhost instead of the IP address
- of the Q7S.
+Note: When now setting up a debug session in the Xilinx SDK, the host must be set to localhost instead of the IP address of the Q7S.
+## Transfering files via SCP
+
+To transfer files from the local machine to the Q7S, use port forwarding
+
+```sh
+ssh -L 1535:192.168.133.10:22 eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5
+```
+
+Then you can copy an `example` file like this
+
+```sh
+scp -P 1535 example root@localhost:/tmp
+```
+
+Copying a file from Q7S to flatsat PC
+````
+scp -P 22 root@192.168.133.10:/tmp/kernel-config /tmp
+````
+
+From a windows machine files can be copied with putty tools
+````
+pscp -scp -P 22 eive@192.168.199.227:/example-file
+````
+
+## Launching an application at start-up
-## Launching an application after boot
Load the root partiton from the flash memory (there are to nor-flash memories and each flash holds two xdi images).
-Note: It is not possible to modify the current loaded root partition.
+Note: It is not possible to modify the currently loaded root partition, e.g. creating directories. To do this,
+the parition needs to be mounted.
+
1. Disable write protection of the desired root partition
-````
-writeprotect 0 0 0 # unlocks nominal image on nor-flash 0
-````
+
+ ```sh
+ writeprotect 0 0 0 # unlocks nominal image on nor-flash 0
+ ```
+
2. Mount the root partition
-````
-xsc_mount_copy 0 0 # Mounts the nominal image from nor-flash 0
-````
-3. Copy the executable to /bin/usr
+
+ ```sh
+ xsc_mount_copy 0 0 # Mounts the nominal image from nor-flash 0
+ ```
+ The mounted partition will be located inside the `/tmp` folder
+
+3. Copy the executable to `/usr/bin`
+
4. Make sure the permissions to execute the application are set
-````
-chmod +x application
-````
+ ```sh
+ chmod +x application
+ ```
+
5. Create systemd service in /lib/systemd/system. The following shows an example service.
-````
-cat > example.service
-[Unit]
-Description=Example Service
-StartLimitIntervalSec=0
+ ```sh
+ cat > example.service
+ [Unit]
+ Description=Example Service
+ StartLimitIntervalSec=0
-[Service]
-Type=simple
-Restart=always
-RestartSec=1
-User=root
-ExecStart=/usr/bin/application
+ [Service]
+ Type=simple
+ Restart=always
+ RestartSec=1
+ User=root
+ ExecStart=/usr/bin/application
-[Install]
-WantedBy=multi-user.target
-````
+ [Install]
+ WantedBy=multi-user.target
+ ```
6. Enable the service. This is normally done with systemctl enable. However, this is not possible when the service is
created for a mounted root partition. Therefore create a symlink as follows.
-````
-ln -s '/tmp/the-mounted-xdi-image/lib/systemd/system/example.service' '/tmp/the-mounted-xdi-image/etc/systemd/system/multi-user.target.wants/example.service'
-````
+ ```sh
+ ln -s '/tmp/the-mounted-xdi-image/lib/systemd/system/example.service' '/tmp/the-mounted-xdi-image/etc/systemd/system/multi-user.target.wants/example.service'
+ ```
+
7. The modified root partition is written back when the partion is locked again.
-````
-writeprotect 0 0 1
-````
+ ```sh
+ writeprotect 0 0 1
+ ```
8. Now verify the application start by booting from the modified image
-````
-xsc_boot_copy 0 0
-````
+ ```sh
+ xsc_boot_copy 0 0
+ ````
+
9. After booting verify if the service is running
-````
-systemctl status example
-````
+ ```sh
+ systemctl status example
+ ```
More detailed information about the used q7s commands can be found in the Q7S user manual.
### Bringing up CAN
-````
-ip link set can0 down
-ip link set can0 type can loopback off
-ip link set can0 up type can bitrate 1000000
-````
+
+ ```sh
+ ip link set can0 down
+ ip link set can0 type can loopback off
+ ip link set can0 up type can bitrate 1000000
+ ```
+
Following command sends 8 bytes to device with id 99 (for petalinux)
````
cansend can0 -i99 99 88 77 11 33 11 22 99
@@ -293,17 +430,6 @@ a permanent solution). If running the script before executing the binary does
not help or an warning is issue that the soft real time value is invalid,
the hard real-time limit of the system might not be high enough (see step 1).
-## Building and running the software on a host system
-
-The host build can be built with following command
-
-```sh
-make -f Makefile-Hosted all -j
-```
-
-If compiling on Windows, it is recommended to supply `WINDOWS=1` .
-A release build can be built by using the `mission` target.
-
## Flight Software Framework (FSFW)
An EIVE fork of the FSFW is submodules into this repository.
@@ -323,3 +449,134 @@ git merge upstream/master
Alternatively, changes from other upstreams (forks) and branches can be merged like that in
the same way.
+
+## PCDU
+
+Connect to serial console of P60 Dock
+````
+picocom -b 500000 /dev/ttyUSBx
+````
+General information
+````
+cmp ident
+````
+List parameter table:
+x values: 1,2 or 4
+````
+param list x
+````
+Table 4 lists HK parameters
+Changing parameters
+First switch to table where parameter shall be changed (here table id is 1)
+````
+p60-dock # param mem 1
+p60-dock # param set out_en[0] 1
+p60-dock # param get out_en[0]
+GET out_en[0] = 1
+````
+
+## Debugging the software (when workstation is directly conncected to Q7S)
+
+1. Assign static IP address to Q7S
+ * Open serial console of Q7S (Accessible via the micro-USB of the PIM, see also Q7S user maunal chapter 10.3)
+ * Baudrate 115200
+ * Login to Q7S:
+ * user: root
+ * pw: root
+
+2. Connect Q7S to workstation via ethernet
+3. Make sure the netmask of the ehternet interface of the workstation matches the netmask of the Q7S
+ * When IP address is set to 192.168.133.10 and the netmask is 255.255.255.0, an example IP address for the workstation
+ is 192.168.133.2
+
+4. Run tcf-agent on Q7S
+
+ * Tcf-agent is not yet integrated in the rootfs of the Q7S. Therefore build tcf-agent manually
+
+ ```sh
+ git clone git://git.eclipse.org/gitroot/tcf/org.eclipse.tcf.agent.git
+ cd org.eclipse.tcf.agent/agent
+ make CC=arm-linux-gnueabihf-gcc LD=arm-linux-gnueabihf-ld MACHINE=arm NO_SSL=1 NO_UUID=1
+ ```
+
+ * Transfer executable agent from org.eclipse.tcf.agent/agent/obj/GNU/Linux/arm/Debug to /tmp of Q7S
+
+ ```sh
+ cd obj/GNU/Linux/arm/Debug
+ scp agent root@192.168.133.10:/tmp
+ ```
+
+ * On Q7S
+ ```sh
+ cd /tmp
+ chmod +x agent
+ ```
+
+ * Run agent
+ ```sh
+ ./agent
+ ```
+
+5. In Xilinx SDK 2018.2 right click on project → Debug As → Debug Configurations
+6. Right click Xilinx C/C++ applicaton (System Debugger) → New →
+7. Set Debug Type to Linux Application Debug and Connectin to Linux Agent
+8. Click New
+9. Give connection a name
+10. Set Host to static IP address of Q7S. e.g. 192.168.133.10
+11. Test connection (This ensures the TCF Agent is running on the Q7S)
+12. Select Application tab
+ * Project Name: eive_obsw
+ * Local File Path: Path to eiveobsw-linux.elf (in _bin\linux\devel)
+ * Remote File Path: /tmp/eive_obsw.elf
+
+## Libgpiod
+
+Detect all gpio device files:
+````
+gpiodetect
+````
+Get info about a specific gpio group:
+````
+gpioinfo
+````
+The following sets the gpio 18 from gpio group gpiochip7 to high level.
+````
+gpioset gpiochip7 18=1
+````
+Setting the gpio to low.
+````
+gpioset gpiochip7 18=0
+````
+Show options for setting gpios.
+````
+gpioset -h
+````
+To get the state of a gpio:
+````
+gpioget
+````
+Example to get state:
+gpioget gpiochip7 14
+
+## Running the EIVE OBSW on a Raspberry Pi
+
+Special section for running the EIVE OBSW on the Raspberry Pi.
+The Raspberry Pi build uses the `bsp_rpi` BSP folder, and a very similar cross-compiler.
+
+For running the software on a Raspberry Pi, it is recommended to follow the steps specified in
+[the fsfw example](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_example/src/branch/mueller/master/doc/README-rpi.md#top)
+and using the TCF agent to have a similar set-up process also required for the Q7S.
+You should run the following command first on your Raspberry Pi
+
+```sh
+sudo apt-get install gpiod libgpiod-dev
+```
+
+to install the required GPIO libraries before cloning the system root folder.
+
+## Special notes on Eclipse
+
+When using Eclipse, there are two special build variables in the project properties
+→ C/C++ Build → Build Variables called `Q7S_SYSROOT` or `RPI_SYSROOT`. You can set
+the sysroot path in those variables to get any additional includes like `gpiod.h` in the
+Eclipse indexer.
\ No newline at end of file
diff --git a/bsp_hosted/CMakeLists.txt b/bsp_hosted/CMakeLists.txt
new file mode 100644
index 00000000..7171d9d7
--- /dev/null
+++ b/bsp_hosted/CMakeLists.txt
@@ -0,0 +1,10 @@
+target_sources(${TARGET_NAME} PUBLIC
+ InitMission.cpp
+ main.cpp
+ ObjectFactory.cpp
+)
+
+add_subdirectory(fsfwconfig)
+add_subdirectory(boardconfig)
+
+
diff --git a/bsp_hosted/InitMission.cpp b/bsp_hosted/InitMission.cpp
new file mode 100644
index 00000000..06bc5646
--- /dev/null
+++ b/bsp_hosted/InitMission.cpp
@@ -0,0 +1,159 @@
+#include "InitMission.h"
+#include "ObjectFactory.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+#ifdef LINUX
+ServiceInterfaceStream sif::debug("DEBUG");
+ServiceInterfaceStream sif::info("INFO");
+ServiceInterfaceStream sif::warning("WARNING");
+ServiceInterfaceStream sif::error("ERROR", false, false, true);
+#else
+ServiceInterfaceStream sif::debug("DEBUG", true);
+ServiceInterfaceStream sif::info("INFO", true);
+ServiceInterfaceStream sif::warning("WARNING", true);
+ServiceInterfaceStream sif::error("ERROR", true, false, true);
+#endif
+
+ObjectManagerIF *objectManager = nullptr;
+
+void initmission::initMission() {
+ sif::info << "Building global objects.." << std::endl;
+ /* Instantiate global object manager and also create all objects */
+ objectManager = new ObjectManager(ObjectFactory::produce);
+ sif::info << "Initializing all objects.." << std::endl;
+ objectManager->initialize();
+
+ /* This function creates and starts all tasks */
+ initTasks();
+}
+
+void initmission::initTasks() {
+ TaskFactory* factory = TaskFactory::instance();
+ 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);
+ 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* udpBridgeTask = factory->createPeriodicTask(
+ "UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
+ result = udpBridgeTask->addComponent(objects::UDP_BRIDGE);
+ if(result != HasReturnvaluesIF::RETURN_OK) {
+ sif::error << "Add component UDP Unix Bridge failed" << std::endl;
+ }
+ PeriodicTaskIF* udpPollingTask = factory->createPeriodicTask(
+ "UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
+ result = udpPollingTask->addComponent(objects::UDP_POLLING_TASK);
+ 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;
+ }
+
+ 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* 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* 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);
+ }
+#endif /* OBSW_ADD_TEST_CODE == 1 */
+
+ sif::info << "Starting tasks.." << std::endl;
+ tmTcDistributor->startTask();
+ udpBridgeTask->startTask();
+ udpPollingTask->startTask();
+
+ pusVerification->startTask();
+ pusEvents->startTask();
+ pusHighPrio->startTask();
+ pusMedPrio->startTask();
+ pusLowPrio->startTask();
+
+#if OBSW_ADD_TEST_CODE == 1
+ testTask->startTask();
+#endif /* OBSW_ADD_TEST_CODE == 1 */
+
+ sif::info << "Tasks started.." << std::endl;
+}
diff --git a/hosted/InitMission.h b/bsp_hosted/InitMission.h
similarity index 85%
rename from hosted/InitMission.h
rename to bsp_hosted/InitMission.h
index 5ecf9e41..01c72008 100644
--- a/hosted/InitMission.h
+++ b/bsp_hosted/InitMission.h
@@ -1,7 +1,7 @@
#ifndef BSP_LINUX_INITMISSION_H_
#define BSP_LINUX_INITMISSION_H_
-namespace InitMission {
+namespace initmission {
void initMission();
void initTasks();
};
diff --git a/bsp_linux/ObjectFactory.cpp b/bsp_hosted/ObjectFactory.cpp
similarity index 70%
rename from bsp_linux/ObjectFactory.cpp
rename to bsp_hosted/ObjectFactory.cpp
index a0f82887..f3d7591d 100644
--- a/bsp_linux/ObjectFactory.cpp
+++ b/bsp_hosted/ObjectFactory.cpp
@@ -1,20 +1,27 @@
#include "ObjectFactory.h"
-#include
#include
+#include
#include
#include
#include
#include
-#include
-#include
-#include
#include
#include
-void Factory::setStaticFrameworkObjectIds() {
+#include
+#include
+
+#include
+
+
+#if OBSW_ADD_TEST_CODE == 1
+#include
+#endif
+
+void Factory::setStaticFrameworkObjectIds(){
PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR;
PusServiceBase::packetDestination = objects::TM_FUNNEL;
@@ -29,14 +36,13 @@ void Factory::setStaticFrameworkObjectIds() {
TmPacketStored::timeStamperId = objects::TIME_STAMPER;
}
-
-
void ObjectFactory::produce(){
Factory::setStaticFrameworkObjectIds();
ObjectFactory::produceGenericObjects();
- new TmTcUnixUdpBridge(objects::UDP_BRIDGE,
- objects::CCSDS_PACKET_DISTRIBUTOR,
- objects::TM_STORE, objects::TC_STORE);
- new TcUnixUdpPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
+ new UdpTmTcBridge(objects::UDP_BRIDGE,
+ objects::CCSDS_PACKET_DISTRIBUTOR,
+ objects::TM_STORE, objects::TC_STORE);
+ new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
+
}
diff --git a/bsp_linux/ObjectFactory.h b/bsp_hosted/ObjectFactory.h
similarity index 100%
rename from bsp_linux/ObjectFactory.h
rename to bsp_hosted/ObjectFactory.h
diff --git a/bsp_hosted/boardconfig/CMakeLists.txt b/bsp_hosted/boardconfig/CMakeLists.txt
new file mode 100644
index 00000000..c32b326d
--- /dev/null
+++ b/bsp_hosted/boardconfig/CMakeLists.txt
@@ -0,0 +1,10 @@
+target_sources(${TARGET_NAME} PRIVATE
+ print.c
+)
+
+target_include_directories(${TARGET_NAME} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+
+
diff --git a/bsp_linux/boardconfig/etl_profile.h b/bsp_hosted/boardconfig/etl_profile.h
similarity index 100%
rename from bsp_linux/boardconfig/etl_profile.h
rename to bsp_hosted/boardconfig/etl_profile.h
diff --git a/bsp_linux/boardconfig/gcov.h b/bsp_hosted/boardconfig/gcov.h
similarity index 100%
rename from bsp_linux/boardconfig/gcov.h
rename to bsp_hosted/boardconfig/gcov.h
diff --git a/hosted/boardconfig/print.c b/bsp_hosted/boardconfig/print.c
similarity index 99%
rename from hosted/boardconfig/print.c
rename to bsp_hosted/boardconfig/print.c
index f409ee1b..f35f9447 100644
--- a/hosted/boardconfig/print.c
+++ b/bsp_hosted/boardconfig/print.c
@@ -1,4 +1,5 @@
#include "print.h"
+
#include
void printChar(const char* character, bool errStream) {
diff --git a/bsp_hosted/boardconfig/print.h b/bsp_hosted/boardconfig/print.h
new file mode 100644
index 00000000..84798490
--- /dev/null
+++ b/bsp_hosted/boardconfig/print.h
@@ -0,0 +1,8 @@
+#ifndef BSP_HOSTED_BOARDCONFIG_PRINT_H_
+#define BSP_HOSTED_BOARDCONFIG_PRINT_H_
+
+#include
+
+void printChar(const char* character, bool errStream);
+
+#endif /* BSP_HOSTED_BOARDCONFIG_PRINT_H_ */
diff --git a/hosted/hosted.mk b/bsp_hosted/bsp_hosted.mk
similarity index 76%
rename from hosted/hosted.mk
rename to bsp_hosted/bsp_hosted.mk
index 8bd29bc1..9595ffbf 100644
--- a/hosted/hosted.mk
+++ b/bsp_hosted/bsp_hosted.mk
@@ -7,4 +7,5 @@ CSRC += $(wildcard $(CURRENTPATH)/boardconfig/*.c)
CXXSRC += $(wildcard $(CURRENTPATH)/comIF/*.cpp)
CSRC += $(wildcard $(CURRENTPATH)/comIF/*.c)
-INCLUDES += $(CURRENTPATH)/boardconfig
\ No newline at end of file
+INCLUDES += $(CURRENTPATH)/boardconfig
+INCLUDES += $(CURRENTPATH)/fsfwconfig
\ No newline at end of file
diff --git a/hosted/comIF/ArduinoComIF.cpp b/bsp_hosted/comIF/ArduinoComIF.cpp
similarity index 97%
rename from hosted/comIF/ArduinoComIF.cpp
rename to bsp_hosted/comIF/ArduinoComIF.cpp
index 11555f55..2db293e6 100644
--- a/hosted/comIF/ArduinoComIF.cpp
+++ b/bsp_hosted/comIF/ArduinoComIF.cpp
@@ -8,6 +8,8 @@
// This only works on Linux
#ifdef LINUX
#include
+#include
+#include
#elif WIN32
#include
#include
@@ -255,7 +257,7 @@ ReturnValue_t ArduinoComIF::sendMessage(uint8_t command,
encodedLen = sizeof(sendBuffer) - remainingLen;
#ifdef LINUX
- ssize_t writtenlen = write(serialPort, sendBuffer, encodedLen);
+ ssize_t writtenlen = ::write(serialPort, sendBuffer, encodedLen);
if (writtenlen < 0) {
//we could try to find out what happened...
return RETURN_FAILED;
@@ -286,7 +288,7 @@ void ArduinoComIF::handleSerialPortRx() {
rxBuffer.writeData(dataFromSerial, bytesRead);
- uint8_t dataReceivedSoFar[rxBuffer.maxSize()];
+ uint8_t dataReceivedSoFar[rxBuffer.getMaxSize()];
uint32_t dataLenReceivedSoFar = 0;
@@ -296,11 +298,11 @@ void ArduinoComIF::handleSerialPortRx() {
//look for STX
size_t firstSTXinRawData = 0;
while ((firstSTXinRawData < dataLenReceivedSoFar)
- && (dataReceivedSoFar[firstSTXinRawData] != DleEncoder::STX)) {
+ && (dataReceivedSoFar[firstSTXinRawData] != DleEncoder::STX_CHAR)) {
firstSTXinRawData++;
}
- if (dataReceivedSoFar[firstSTXinRawData] != DleEncoder::STX) {
+ if (dataReceivedSoFar[firstSTXinRawData] != DleEncoder::STX_CHAR) {
//there is no STX in our data, throw it away...
rxBuffer.deleteData(dataLenReceivedSoFar);
return;
diff --git a/hosted/comIF/ArduinoComIF.h b/bsp_hosted/comIF/ArduinoComIF.h
similarity index 100%
rename from hosted/comIF/ArduinoComIF.h
rename to bsp_hosted/comIF/ArduinoComIF.h
diff --git a/hosted/comIF/ArduinoCookie.cpp b/bsp_hosted/comIF/ArduinoCookie.cpp
similarity index 83%
rename from hosted/comIF/ArduinoCookie.cpp
rename to bsp_hosted/comIF/ArduinoCookie.cpp
index 7d9a9f3c..bc698720 100644
--- a/hosted/comIF/ArduinoCookie.cpp
+++ b/bsp_hosted/comIF/ArduinoCookie.cpp
@@ -1,4 +1,4 @@
-#include "ArduinoCookie.h"
+#include
ArduinoCookie::ArduinoCookie(Protocol_t protocol, uint8_t address,
const size_t maxReplySize) :
diff --git a/hosted/comIF/ArduinoCookie.h b/bsp_hosted/comIF/ArduinoCookie.h
similarity index 100%
rename from hosted/comIF/ArduinoCookie.h
rename to bsp_hosted/comIF/ArduinoCookie.h
diff --git a/bsp_hosted/comIF/CMakeLists.txt b/bsp_hosted/comIF/CMakeLists.txt
new file mode 100644
index 00000000..eb416f75
--- /dev/null
+++ b/bsp_hosted/comIF/CMakeLists.txt
@@ -0,0 +1,8 @@
+target_sources(${TARGET_NAME} PUBLIC
+ ArduinoComIF.cpp
+ ArduinoCookie.cpp
+)
+
+
+
+
diff --git a/bsp_hosted/fsfwconfig/CMakeLists.txt b/bsp_hosted/fsfwconfig/CMakeLists.txt
new file mode 100644
index 00000000..a906098f
--- /dev/null
+++ b/bsp_hosted/fsfwconfig/CMakeLists.txt
@@ -0,0 +1,10 @@
+target_sources(${TARGET_NAME} PRIVATE
+ ipc/MissionMessageTypes.cpp
+)
+
+target_include_directories(${TARGET_NAME} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+
+
diff --git a/hosted/fsfwconfig/FSFWConfig.h b/bsp_hosted/fsfwconfig/FSFWConfig.h
similarity index 54%
rename from hosted/fsfwconfig/FSFWConfig.h
rename to bsp_hosted/fsfwconfig/FSFWConfig.h
index ea86152c..e3def8fe 100644
--- a/hosted/fsfwconfig/FSFWConfig.h
+++ b/bsp_hosted/fsfwconfig/FSFWConfig.h
@@ -1,25 +1,27 @@
#ifndef CONFIG_FSFWCONFIG_H_
#define CONFIG_FSFWCONFIG_H_
-#include
#include
+#include
-//! Used to determine whether C++ ostreams are used
-//! Those can lead to code bloat.
-#define FSFW_CPP_OSTREAM_ENABLED 1
+//! Used to determine whether C++ ostreams are used which can increase
+//! the binary size significantly. If this is disabled,
+//! the C stdio functions can be used alternatively
+#define FSFW_CPP_OSTREAM_ENABLED 1
-//! Reduced printout to further decrese code size
-//! Be careful, this also turns off most diagnostic prinouts!
-#define FSFW_REDUCED_PRINTOUT 0
+//! More FSFW related printouts depending on level. Useful for development.
+#define FSFW_VERBOSE_LEVEL 1
-//! Can be used to enable debugging printouts for developing the FSFW
-#define FSFW_DEBUGGING 0
+//! Can be used to completely disable printouts, even the C stdio ones.
+#if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_VERBOSE_LEVEL == 0
+ #define FSFW_DISABLE_PRINTOUT 0
+#endif
-//! Defines the FIFO depth of each commanding service base which
-//! also determines how many commands a CSB service can handle in one cycle
-//! simulataneously. This will increase the required RAM for
-//! each CSB service !
-#define FSFW_CSB_FIFO_DEPTH 6
+//! Can be used to disable the ANSI color sequences for C stdio.
+#define FSFW_COLORED_OUTPUT 1
+
+//! Can be used to disable the ANSI color sequences for C stdio.
+#define FSFW_COLORED_OUTPUT 1
//! If FSFW_OBJ_EVENT_TRANSLATION is set to one,
//! additional output which requires the translation files translateObjects
@@ -27,18 +29,19 @@
#define FSFW_OBJ_EVENT_TRANSLATION 0
#if FSFW_OBJ_EVENT_TRANSLATION == 1
-#define FSFW_DEBUG_OUTPUT 1
//! Specify whether info events are printed too.
#define FSFW_DEBUG_INFO 1
-#include
-#include
+#include "objects/translateObjects.h"
+#include "events/translateEvents.h"
#else
-#define FSFW_DEBUG_OUTPUT 0
#endif
//! When using the newlib nano library, C99 support for stdio facilities
//! will not be provided. This define should be set to 1 if this is the case.
-#define FSFW_NO_C99_IO 1
+#define FSFW_NO_C99_IO 1
+
+//! Specify whether a special mode store is used for Subsystem components.
+#define FSFW_USE_MODESTORE 0
namespace fsfwconfig {
//! Default timestamp size. The default timestamp will be an eight byte CDC
@@ -49,6 +52,14 @@ static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 8;
static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240;
static constexpr size_t FSFW_EVENTMGMT_EVENTIDMATCHERS = 120;
static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120;
+
+//! Defines the FIFO depth of each commanding service base which
+//! also determines how many commands a CSB service can handle in one cycle
+//! simulataneously. This will increase the required RAM for
+//! each CSB service !
+static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 6;
+
+static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 124;
}
#endif /* CONFIG_FSFWCONFIG_H_ */
diff --git a/bsp_hosted/fsfwconfig/OBSWConfig.h b/bsp_hosted/fsfwconfig/OBSWConfig.h
new file mode 100644
index 00000000..5996e3a2
--- /dev/null
+++ b/bsp_hosted/fsfwconfig/OBSWConfig.h
@@ -0,0 +1,32 @@
+/**
+ * @brief This file can be used to add preprocessor define for conditional
+ * code inclusion exclusion or various other project constants and
+ * properties in one place.
+ */
+#ifndef CONFIG_OBSWCONFIG_H_
+#define CONFIG_OBSWCONFIG_H_
+
+#include "commonConfig.h"
+
+#define OBSW_ADD_TEST_CODE 1
+
+/* These defines should be disabled for mission code but are useful for
+debugging. */
+#define OBSW_VEBOSE_LEVEL 1
+
+#ifdef __cplusplus
+
+#include "objects/systemObjectList.h"
+#include "events/subsystemIdRanges.h"
+#include "returnvalues/classIds.h"
+
+namespace config {
+#endif
+
+/* Add mission configuration flags here */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_OBSWCONFIG_H_ */
diff --git a/hosted/fsfwconfig/OBSWVersion.h b/bsp_hosted/fsfwconfig/OBSWVersion.h
similarity index 79%
rename from hosted/fsfwconfig/OBSWVersion.h
rename to bsp_hosted/fsfwconfig/OBSWVersion.h
index e1afa204..980b6965 100644
--- a/hosted/fsfwconfig/OBSWVersion.h
+++ b/bsp_hosted/fsfwconfig/OBSWVersion.h
@@ -3,8 +3,8 @@
const char* const SW_NAME = "eive";
-#define SW_VERSION 0
-#define SW_SUBVERSION 2
+#define SW_VERSION 1
+#define SW_SUBVERSION 0
#define SW_SUBSUBVERSION 0
diff --git a/bsp_hosted/fsfwconfig/devices/gpioIds.h b/bsp_hosted/fsfwconfig/devices/gpioIds.h
new file mode 100644
index 00000000..df49c0b7
--- /dev/null
+++ b/bsp_hosted/fsfwconfig/devices/gpioIds.h
@@ -0,0 +1,59 @@
+#ifndef FSFWCONFIG_DEVICES_GPIOIDS_H_
+#define FSFWCONFIG_DEVICES_GPIOIDS_H_
+
+#include
+
+namespace gpioIds {
+ 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,
+
+ TEST_ID_0,
+ TEST_ID_1,
+
+ 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
+ };
+}
+
+
+
+
+#endif /* FSFWCONFIG_DEVICES_GPIOIDS_H_ */
diff --git a/bsp_hosted/fsfwconfig/devices/powerSwitcherList.h b/bsp_hosted/fsfwconfig/devices/powerSwitcherList.h
new file mode 100644
index 00000000..09bdf568
--- /dev/null
+++ b/bsp_hosted/fsfwconfig/devices/powerSwitcherList.h
@@ -0,0 +1,58 @@
+#ifndef FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_
+#define FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_
+
+#include
+
+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_BORAD_SIDE_A,
+ NUMBER_OF_SWITCHES
+ };
+
+ 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;
+#if 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;
+#else
+ 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;
+}
+
+
+#endif /* FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ */
diff --git a/hosted/fsfwconfig/events/subsystemIdRanges.h b/bsp_hosted/fsfwconfig/events/subsystemIdRanges.h
similarity index 90%
rename from hosted/fsfwconfig/events/subsystemIdRanges.h
rename to bsp_hosted/fsfwconfig/events/subsystemIdRanges.h
index 2255b345..51534f60 100644
--- a/hosted/fsfwconfig/events/subsystemIdRanges.h
+++ b/bsp_hosted/fsfwconfig/events/subsystemIdRanges.h
@@ -10,7 +10,7 @@
*/
namespace SUBSYSTEM_ID {
enum: uint8_t {
- SUBSYSTE_ID_START = FW_SUBSYSTEM_ID_RANGE,
+ SUBSYSTEM_ID_START = FW_SUBSYSTEM_ID_RANGE,
PUS_SERVICE_2,
PUS_SERVICE_3,
PUS_SERVICE_5,
@@ -18,6 +18,7 @@ enum: uint8_t {
PUS_SERVICE_8,
PUS_SERVICE_23,
MGM_LIS3MDL,
+ MGM_RM3100,
DUMMY_DEVICE,
};
diff --git a/bsp_hosted/fsfwconfig/fsfwconfig.mk b/bsp_hosted/fsfwconfig/fsfwconfig.mk
new file mode 100644
index 00000000..53cb0fc7
--- /dev/null
+++ b/bsp_hosted/fsfwconfig/fsfwconfig.mk
@@ -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)
\ No newline at end of file
diff --git a/hosted/fsfwconfig/ipc/MissionMessageTypes.cpp b/bsp_hosted/fsfwconfig/ipc/MissionMessageTypes.cpp
similarity index 75%
rename from hosted/fsfwconfig/ipc/MissionMessageTypes.cpp
rename to bsp_hosted/fsfwconfig/ipc/MissionMessageTypes.cpp
index b91abcd3..36ef1b73 100644
--- a/hosted/fsfwconfig/ipc/MissionMessageTypes.cpp
+++ b/bsp_hosted/fsfwconfig/ipc/MissionMessageTypes.cpp
@@ -1,5 +1,5 @@
+#include "MissionMessageTypes.h"
#include
-#include
void messagetypes::clearMissionMessage(CommandMessage* message) {
switch(message->getMessageType()) {
diff --git a/hosted/fsfwconfig/ipc/MissionMessageTypes.h b/bsp_hosted/fsfwconfig/ipc/MissionMessageTypes.h
similarity index 95%
rename from hosted/fsfwconfig/ipc/MissionMessageTypes.h
rename to bsp_hosted/fsfwconfig/ipc/MissionMessageTypes.h
index 832d8e58..7e3c448f 100644
--- a/hosted/fsfwconfig/ipc/MissionMessageTypes.h
+++ b/bsp_hosted/fsfwconfig/ipc/MissionMessageTypes.h
@@ -11,7 +11,7 @@ class CommandMessage;
*
* @param message Generic Command Message
*/
-namespace messagetypes{
+namespace messagetypes {
enum MESSAGE_TYPE {
MISSION_MESSAGE_TYPE_START = FW_MESSAGES_COUNT,
};
diff --git a/bsp_hosted/fsfwconfig/objects/systemObjectList.h b/bsp_hosted/fsfwconfig/objects/systemObjectList.h
new file mode 100644
index 00000000..d7a1abd7
--- /dev/null
+++ b/bsp_hosted/fsfwconfig/objects/systemObjectList.h
@@ -0,0 +1,50 @@
+#ifndef HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_
+#define HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_
+
+#include
+
+// The objects will be instantiated in the ID order
+namespace objects {
+ enum sourceObjects: uint32_t {
+ /* First Byte 0x50-0x52 reserved for PUS Services **/
+ CCSDS_PACKET_DISTRIBUTOR = 0x50000100,
+ PUS_PACKET_DISTRIBUTOR = 0x50000200,
+ UDP_BRIDGE = 0x50000300,
+ UDP_POLLING_TASK = 0x50000400,
+
+ 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,
+
+ /* Test Task */
+
+ TEST_TASK = 0x42694269,
+ DUMMY_INTERFACE = 0xCAFECAFE,
+ DUMMY_HANDLER = 0x4400AFFE,
+
+ /* 0x44 ('D') for device handlers */
+ P60DOCK_HANDLER = 0x44000001,
+ PDU1_HANDLER = 0x44000002,
+ PDU2_HANDLER = 0x44000003,
+ ACU_HANDLER = 0x44000004,
+ TMP1075_HANDLER_1 = 0x44000005,
+ TMP1075_HANDLER_2 = 0x44000006,
+ MGM_0_LIS3_HANDLER = 0x4400007,
+ MGM_1_RM3100_HANDLER = 0x44000008,
+ MGM_2_LIS3_HANDLER = 0x44000009,
+ MGM_3_RM3100_HANDLER = 0x44000010,
+ GYRO_0_ADIS_HANDLER = 0x44000011,
+ GYRO_1_L3G_HANDLER = 0x44000012,
+ GYRO_2_L3G_HANDLER = 0x44000013,
+
+ /* 0x49 ('I') for Communication Interfaces **/
+ ARDUINO_COM_IF = 0x49000001
+ };
+}
+
+#endif /* BSP_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ */
diff --git a/hosted/fsfwconfig/returnvalues/classIds.h b/bsp_hosted/fsfwconfig/returnvalues/classIds.h
similarity index 93%
rename from hosted/fsfwconfig/returnvalues/classIds.h
rename to bsp_hosted/fsfwconfig/returnvalues/classIds.h
index f6427a1f..21371c15 100644
--- a/hosted/fsfwconfig/returnvalues/classIds.h
+++ b/bsp_hosted/fsfwconfig/returnvalues/classIds.h
@@ -11,7 +11,8 @@
namespace CLASS_ID {
enum {
MISSION_CLASS_ID_START = FW_CLASS_ID_COUNT,
- MGM_LIS3MDL
+ MGM_LIS3MDL,
+ MGM_RM3100
};
}
diff --git a/bsp_hosted/fsfwconfig/tmtc/apid.h b/bsp_hosted/fsfwconfig/tmtc/apid.h
new file mode 100644
index 00000000..ee2fc7c4
--- /dev/null
+++ b/bsp_hosted/fsfwconfig/tmtc/apid.h
@@ -0,0 +1,19 @@
+#ifndef FSFWCONFIG_TMTC_APID_H_
+#define FSFWCONFIG_TMTC_APID_H_
+
+#include
+
+/**
+ * Application Process Definition: entity, uniquely identified by an
+ * application process ID (APID), capable of generating telemetry source
+ * packets and receiving telecommand packets
+ *
+ * SOURCE APID: 0x73 / 115 / s
+ * APID is a 11 bit number
+ */
+namespace apid {
+ static const uint16_t EIVE_OBSW = 0x65;
+}
+
+
+#endif /* FSFWCONFIG_TMTC_APID_H_ */
diff --git a/bsp_hosted/fsfwconfig/tmtc/pusIds.h b/bsp_hosted/fsfwconfig/tmtc/pusIds.h
new file mode 100644
index 00000000..a2dd7575
--- /dev/null
+++ b/bsp_hosted/fsfwconfig/tmtc/pusIds.h
@@ -0,0 +1,23 @@
+#ifndef CONFIG_TMTC_PUSIDS_HPP_
+#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,
+};
+};
+
+#endif /* CONFIG_TMTC_PUSIDS_HPP_ */
diff --git a/hosted/main.cpp b/bsp_hosted/main.cpp
similarity index 88%
rename from hosted/main.cpp
rename to bsp_hosted/main.cpp
index e5ca6d02..4fa1eb04 100644
--- a/hosted/main.cpp
+++ b/bsp_hosted/main.cpp
@@ -1,7 +1,7 @@
-#include
-#include
-#include
+#include "InitMission.h"
+#include
+#include
#include
#ifdef WIN32
@@ -24,7 +24,7 @@ int main(void)
<< SW_SUBVERSION << "." << SW_SUBSUBVERSION << " -- " << std::endl;
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
- InitMission::initMission();
+ initmission::initMission();
for(;;) {
// suspend main thread by sleeping it.
diff --git a/bsp_linux/InitMission.cpp b/bsp_linux/InitMission.cpp
deleted file mode 100644
index cf84ab0d..00000000
--- a/bsp_linux/InitMission.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-// This is configured for linux without \cr
-#ifdef LINUX
-ServiceInterfaceStream sif::debug("DEBUG");
-ServiceInterfaceStream sif::info("INFO");
-ServiceInterfaceStream sif::warning("WARNING");
-ServiceInterfaceStream sif::error("ERROR", false, false, true);
-#else
-ServiceInterfaceStream sif::debug("DEBUG", true);
-ServiceInterfaceStream sif::info("INFO", true);
-ServiceInterfaceStream sif::warning("WARNING", true);
-ServiceInterfaceStream sif::error("ERROR", true, false, true);
-#endif
-
-ObjectManagerIF *objectManager = nullptr;
-
-//Initialize Data Pool
-DataPool dataPool(nullptr);
-
-void InitMission::initMission() {
- sif::info << "Building global objects.." << std::endl;
- /* Instantiate global object manager and also create all objects */
- objectManager = new ObjectManager(ObjectFactory::produce);
- sif::info << "Initializing all objects.." << std::endl;
- objectManager->initialize();
-
- /* This function creates and starts all tasks */
- initTasks();
-}
-
-void InitMission::initTasks(){
- /* TMTC Distribution */
- PeriodicTaskIF* TmTcDistributor = TaskFactory::instance()->
- createPeriodicTask("DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE,
- 0.100, nullptr);
- 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* UdpBridgeTask = TaskFactory::instance()->createPeriodicTask(
- "UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE,
- 0.2, nullptr);
- result = UdpBridgeTask->addComponent(objects::UDP_BRIDGE);
- if(result != HasReturnvaluesIF::RETURN_OK) {
- sif::error << "Add component UDP Unix Bridge failed" << std::endl;
- }
- PeriodicTaskIF* UdpPollingTask = TaskFactory::instance()->
- createPeriodicTask("UDP_POLLING", 80,
- PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, nullptr);
- result = UdpPollingTask->addComponent(objects::UDP_POLLING_TASK);
- if(result != HasReturnvaluesIF::RETURN_OK) {
- sif::error << "Add component UDP Polling failed" << std::endl;
- }
-
- /* PUS Services */
- PeriodicTaskIF* PusVerification = TaskFactory::instance()->
- createPeriodicTask("PUS_VERIF_1", 40,
- PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, nullptr);
- result = PusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
- if(result != HasReturnvaluesIF::RETURN_OK){
- sif::error << "Object add component failed" << std::endl;
- }
-
- PeriodicTaskIF* PusEvents = TaskFactory::instance()->
- createPeriodicTask("PUS_VERIF_1", 60,
- PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, nullptr);
- result = PusVerification->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING);
- if(result != HasReturnvaluesIF::RETURN_OK){
- sif::error << "Object add component failed" << std::endl;
- }
-
- PeriodicTaskIF* PusHighPrio = TaskFactory::instance()->
- createPeriodicTask("PUS_HIGH_PRIO", 50,
- PeriodicTaskIF::MINIMUM_STACK_SIZE,
- 0.200, nullptr);
- result = PusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
- if(result!=HasReturnvaluesIF::RETURN_OK){
- sif::error << "Object add component failed" << std::endl;
- }
- result = PusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
- if(result!=HasReturnvaluesIF::RETURN_OK){
- sif::error << "Object add component failed" << std::endl;
- }
-
- PeriodicTaskIF* PusMedPrio = TaskFactory::instance()->
- createPeriodicTask("PUS_HIGH_PRIO", 40,
- PeriodicTaskIF::MINIMUM_STACK_SIZE,
- 0.8, nullptr);
- result = PusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
- 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){
- sif::error << "Object add component failed" << std::endl;
- }
-
- PeriodicTaskIF* PusLowPrio = TaskFactory::instance()->
- createPeriodicTask("PUSB", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE,
- 1.6, nullptr);
- result = PusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
- if(result!=HasReturnvaluesIF::RETURN_OK){
- sif::error << "Object add component failed" << std::endl;
- }
-
-
-#if ADD_TEST_CODE == 1
- FixedTimeslotTaskIF* TestTimeslotTask = TaskFactory::instance()->
- createFixedTimeslotTask("PST_TEST_TASK", 10,
- PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr);
- result = pst::pollingSequenceTestFunction(TestTimeslotTask);
- if(result != HasReturnvaluesIF::RETURN_OK) {
- sif::error << "InitMission::createTasks: Test PST initialization "
- << "failed!" << std::endl;
- }
-#endif
-
- //Main thread sleep
- sif::info << "Starting tasks.." << std::endl;
- TmTcDistributor->startTask();
- UdpBridgeTask->startTask();
- UdpPollingTask->startTask();
-
- PusVerification->startTask();
- PusEvents->startTask();
- PusHighPrio->startTask();
- PusMedPrio->startTask();
- PusLowPrio->startTask();
-#if ADD_TEST_CODE == 1
- TestTimeslotTask->startTask();
-#endif
- sif::info << "Tasks started.." << std::endl;
-}
diff --git a/bsp_linux/bsp_linux.mk b/bsp_linux/bsp_linux.mk
deleted file mode 100644
index f7f9a469..00000000
--- a/bsp_linux/bsp_linux.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-CXXSRC += $(wildcard $(CURRENTPATH)/*.cpp)
-CSRC += $(wildcard $(CURRENTPATH)/*.c)
-
-CSRC += $(wildcard $(CURRENTPATH)/boardconfig/*.c)
\ No newline at end of file
diff --git a/bsp_linux/comIF/ArduinoComIF.cpp b/bsp_linux/comIF/ArduinoComIF.cpp
deleted file mode 100644
index ffc59b47..00000000
--- a/bsp_linux/comIF/ArduinoComIF.cpp
+++ /dev/null
@@ -1,324 +0,0 @@
-#include "ArduinoCookie.h"
-#include "ArduinoComIF.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-ArduinoCommInterface::ArduinoCommInterface(object_id_t setObjectId,
- const char *serialDevice) :
- spiMap(MAX_NUMBER_OF_SPI_DEVICES), rxBuffer(
- MAX_PACKET_SIZE * MAX_NUMBER_OF_SPI_DEVICES*10, true), SystemObject(setObjectId) {
- initialized = false;
- serialPort = ::open("/dev/ttyUSB0", O_RDWR);
-
- if (serialPort < 0) {
- //configuration error
- printf("Error %i from open: %s\n", errno, strerror(errno));
- return;
- }
-
- 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;
- }
-
- 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
-
- if (tcsetattr(serialPort, TCSANOW, &tty) != 0) {
- //printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
- return;
- }
-
- initialized = true;
-
-}
-
-ArduinoCommInterface::~ArduinoCommInterface() {
- ::close(serialPort);
-}
-
-ReturnValue_t ArduinoCommInterface::open(Cookie **cookie, uint32_t address,
- uint32_t maxReplyLen) {
- //This is a hack, will be gone with https://egit.irs.uni-stuttgart.de/fsfw/fsfw/issues/19
- switch ((address >> 8) & 0xff) {
- case 0:
- *cookie = new ArduinoCookie(ArduinoCookie::SPI, address, maxReplyLen);
- spiMap.insert(address, (ArduinoCookie*) *cookie); //Yes, I *do* know that it is an ArduinoSpiCookie, I just new'd it
- break;
- default:
- return HasReturnvaluesIF::RETURN_FAILED;
- }
- return HasReturnvaluesIF::RETURN_OK;
-}
-
-ReturnValue_t ArduinoCommInterface::reOpen(Cookie *cookie, uint32_t address,
- uint32_t maxReplyLen) {
- //too lazy right now will be irrelevant with https://egit.irs.uni-stuttgart.de/fsfw/fsfw/issues/19
- return HasReturnvaluesIF::RETURN_FAILED;
-}
-
-void ArduinoCommInterface::close(Cookie *cookie) {
- //too lazy as well, find the correct Map, delete it there, then the cookie...
-}
-
-ReturnValue_t ArduinoCommInterface::sendMessage(Cookie *cookie, uint8_t *data,
- uint32_t len) {
- ArduinoCookie *arduinoCookie = dynamic_cast(cookie);
- if (arduinoCookie == NULL) {
- return INVALID_COOKIE_TYPE;
- }
-
- return sendMessage(arduinoCookie->command, arduinoCookie->address, data,
- len);
-}
-
-ReturnValue_t ArduinoCommInterface::getSendSuccess(Cookie *cookie) {
- return RETURN_OK;
-}
-
-ReturnValue_t ArduinoCommInterface::requestReceiveMessage(Cookie *cookie) {
- return RETURN_OK;
-}
-
-ReturnValue_t ArduinoCommInterface::readReceivedMessage(Cookie *cookie,
- uint8_t **buffer, uint32_t *size) {
-
- handleSerialPortRx();
-
- ArduinoCookie *arduinoCookie = dynamic_cast(cookie);
- if (arduinoCookie == NULL) {
- return INVALID_COOKIE_TYPE;
- }
-
- *buffer = arduinoCookie->replyBuffer;
- *size = arduinoCookie->receivedDataLen;
- return HasReturnvaluesIF::RETURN_OK;
-}
-
-ReturnValue_t ArduinoCommInterface::setAddress(Cookie *cookie,
- uint32_t address) {
- //not implemented
- return RETURN_FAILED;
-}
-
-uint32_t ArduinoCommInterface::getAddress(Cookie *cookie) {
- //not implemented
- return 0;
-}
-
-ReturnValue_t ArduinoCommInterface::setParameter(Cookie *cookie,
- uint32_t parameter) {
- //not implemented
- return RETURN_FAILED;
-}
-
-uint32_t ArduinoCommInterface::getParameter(Cookie *cookie) {
- //not implemented
- return 0;
-}
-
-ReturnValue_t ArduinoCommInterface::sendMessage(uint8_t command,
- uint8_t address, const uint8_t *data, size_t dataLen) {
- if (dataLen > UINT16_MAX) {
- return TOO_MUCH_DATA;
- }
-
- //being conservative here
- uint8_t sendBuffer[(dataLen + 6) * 2 + 2];
-
- sendBuffer[0] = DleEncoder::STX;
-
- uint8_t *currentPosition = sendBuffer + 1;
- size_t remainingLen = sizeof(sendBuffer) - 1;
- uint32_t encodedLen;
-
- 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
-
- 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
-
- uint8_t temporaryBuffer[2];
-
- //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
-
- //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
-
- 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;
- }
- remainingLen -= 1;
-
- encodedLen = sizeof(sendBuffer) - remainingLen;
-
- 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;
-}
-
-void ArduinoCommInterface::handleSerialPortRx() {
- uint32_t availableSpace = rxBuffer.availableWriteSpace();
-
- uint8_t dataFromSerial[availableSpace];
-
- ssize_t bytesRead = read(serialPort, dataFromSerial,
- sizeof(dataFromSerial));
-
- if (bytesRead < 0) {
- return;
- }
-
- rxBuffer.writeData(dataFromSerial, bytesRead);
-
- uint8_t dataReceivedSoFar[rxBuffer.maxSize()];
-
- uint32_t dataLenReceivedSoFar = 0;
-
- rxBuffer.readData(dataReceivedSoFar, sizeof(dataReceivedSoFar), true,
- &dataLenReceivedSoFar);
-
- //look for STX
- size_t firstSTXinRawData = 0;
- while ((firstSTXinRawData < dataLenReceivedSoFar)
- && (dataReceivedSoFar[firstSTXinRawData] != DleEncoder::STX)) {
- firstSTXinRawData++;
- }
-
- if (dataReceivedSoFar[firstSTXinRawData] != DleEncoder::STX) {
- //there is no STX in our data, throw it away...
- rxBuffer.deleteData(dataLenReceivedSoFar);
- return;
- }
-
- uint8_t packet[MAX_PACKET_SIZE];
- uint32_t packetLen;
-
- uint32_t readSize;
-
- 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);
-
- //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);
-}
-
-void ArduinoCommInterface::handlePacket(uint8_t *packet, size_t packetLen) {
- uint16_t crc = CRC::crc16ccitt(packet, packetLen);
- if (crc != 0) {
- //CRC error
- return;
- }
-
- uint8_t command = packet[0];
- uint8_t address = packet[1];
-
- uint16_t size = (packet[2] << 8) + packet[3];
-
- if (size != packetLen - 6) {
- //Invalid Length
- return;
- }
-
- switch (command) {
- case ArduinoCookie::SPI: {
- ArduinoCookie **itsComplicated;
- ReturnValue_t result = spiMap.find(address, &itsComplicated);
- if (result != RETURN_OK) {
- //we do no know this address
- return;
- }
- ArduinoCookie *theActualCookie = *itsComplicated;
- if (packetLen > theActualCookie->maxReplySize + 6) {
- packetLen = theActualCookie->maxReplySize + 6;
- }
- memcpy(theActualCookie->replyBuffer, packet + 4, packetLen - 6);
- theActualCookie->receivedDataLen = packetLen - 6;
- }
- break;
- default:
- return;
- }
-}
diff --git a/bsp_linux/comIF/ArduinoComIF.h b/bsp_linux/comIF/ArduinoComIF.h
deleted file mode 100644
index 9ab166de..00000000
--- a/bsp_linux/comIF/ArduinoComIF.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//#ifndef MISSION_ARDUINOCOMMINTERFACE_H_
-//#define MISSION_ARDUINOCOMMINTERFACE_H_
-//
-//#include
-//#include
-//#include
-//#include
-//#include
-//#include
-//
-//#include "../../framework/objectmanager/SystemObject.h"
-//#include "ArduinoCookie.h"
-//
-////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;
-//
-// static const uint8_t COMMAND_INVALID = -1;
-// static const uint8_t COMMAND_SPI = 1;
-//
-// ArduinoComIF(object_id_t setObjectId, const char *serialDevice);
-// virtual ~ArduinoComIF();
-//
-// virtual ReturnValue_t open(Cookie **cookie, uint32_t address,
-// uint32_t maxReplyLen);
-//
-// virtual ReturnValue_t reOpen(Cookie *cookie, uint32_t address,
-// uint32_t maxReplyLen);
-//
-// virtual void close(Cookie *cookie);
-//
-// //SHOULDDO can data be const?
-// virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data,
-// uint32_t len);
-//
-// virtual ReturnValue_t getSendSuccess(Cookie *cookie);
-//
-// virtual ReturnValue_t requestReceiveMessage(Cookie *cookie);
-//
-// virtual ReturnValue_t readReceivedMessage(Cookie *cookie, uint8_t **buffer,
-// uint32_t *size);
-//
-// virtual ReturnValue_t setAddress(Cookie *cookie, uint32_t address);
-//
-// virtual uint32_t getAddress(Cookie *cookie);
-//
-// virtual ReturnValue_t setParameter(Cookie *cookie, uint32_t parameter);
-//
-// virtual uint32_t getParameter(Cookie *cookie);
-//private:
-// //remembering if the initialization in the ctor worked
-// //if not, all calls are disabled
-// bool initialized;
-// int serialPort;
-// //used to know where to put the data if a reply is received
-// FixedMap spiMap;
-//
-// SimpleRingBuffer rxBuffer;
-//
-// 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);
-//};
-//
-//#endif /* MISSION_ARDUINOCOMMINTERFACE_H_ */
diff --git a/bsp_linux/comIF/ArduinoCookie.cpp b/bsp_linux/comIF/ArduinoCookie.cpp
deleted file mode 100644
index d7e81192..00000000
--- a/bsp_linux/comIF/ArduinoCookie.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-//#include
-//
-//ArduinoCookie::ArduinoCookie(Protocol_t protocol, uint8_t address,
-// size_t maxReplySize) :
-// command(protocol), address(address), receivedDataLen(0), maxReplySize(
-// maxReplySize) {
-// replyBuffer = new uint8_t[maxReplySize];
-//}
-//
-//ArduinoCookie::~ArduinoCookie() {
-// delete[] replyBuffer;
-//}
diff --git a/bsp_linux/comIF/ArduinoCookie.h b/bsp_linux/comIF/ArduinoCookie.h
deleted file mode 100644
index 64eed4ad..00000000
--- a/bsp_linux/comIF/ArduinoCookie.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//#ifndef MISSION_ARDUINO_ARDUINOCOOKIE_H_
-//#define MISSION_ARDUINO_ARDUINOCOOKIE_H_
-//
-//#include
-//
-//#include
-//#include
-//
-//class ArduinoCookie: public Cookie {
-//public:
-// enum Protocol_t {
-// INVALID = 0, SPI = 1
-// };
-// ArduinoCookie(Protocol_t protocol, uint8_t address, size_t maxReplySize);
-// virtual ~ArduinoCookie();
-//
-// uint8_t command;
-// uint8_t address;
-// uint8_t *replyBuffer;
-// size_t receivedDataLen;
-// size_t maxReplySize;
-//
-//};
-//
-//#endif /* MISSION_ARDUINO_ARDUINOCOOKIE_H_ */
diff --git a/bsp_q7s/CMakeLists.txt b/bsp_q7s/CMakeLists.txt
new file mode 100644
index 00000000..e567628e
--- /dev/null
+++ b/bsp_q7s/CMakeLists.txt
@@ -0,0 +1,14 @@
+target_sources(${TARGET_NAME} PUBLIC
+ InitMission.cpp
+ main.cpp
+ ObjectFactory.cpp
+)
+
+add_subdirectory(boardconfig)
+add_subdirectory(comIF)
+add_subdirectory(devices)
+add_subdirectory(boardtest)
+add_subdirectory(gpio)
+
+
+
diff --git a/bsp_q7s/InitMission.cpp b/bsp_q7s/InitMission.cpp
new file mode 100644
index 00000000..3fe0ba0c
--- /dev/null
+++ b/bsp_q7s/InitMission.cpp
@@ -0,0 +1,205 @@
+#include "InitMission.h"
+#include "ObjectFactory.h"
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* This is configured for linux without CR */
+#ifdef LINUX
+ServiceInterfaceStream sif::debug("DEBUG");
+ServiceInterfaceStream sif::info("INFO");
+ServiceInterfaceStream sif::warning("WARNING");
+ServiceInterfaceStream sif::error("ERROR", false, false, true);
+#else
+ServiceInterfaceStream sif::debug("DEBUG", true);
+ServiceInterfaceStream sif::info("INFO", true);
+ServiceInterfaceStream sif::warning("WARNING", true);
+ServiceInterfaceStream sif::error("ERROR", true, false, true);
+#endif
+
+ObjectManagerIF *objectManager = nullptr;
+
+void initmission::initMission() {
+ sif::info << "Building global objects.." << std::endl;
+ /* Instantiate global object manager and also create all objects */
+ objectManager = new ObjectManager(ObjectFactory::produce);
+ sif::info << "Initializing all objects.." << std::endl;
+ objectManager->initialize();
+
+ /* This function creates and starts all tasks */
+ initTasks();
+}
+
+void initmission::initTasks() {
+ TaskFactory* factory = TaskFactory::instance();
+ 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);
+ ReturnValue_t 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);
+ }
+
+ /* UDP bridge */
+ PeriodicTaskIF* udpBridgeTask = factory->createPeriodicTask(
+ "UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
+ result = udpBridgeTask->addComponent(objects::UDP_BRIDGE);
+ if(result != HasReturnvaluesIF::RETURN_OK) {
+ initmission::printAddObjectError("UDP_BRIDGE", objects::UDP_BRIDGE);
+ }
+ PeriodicTaskIF* udpPollingTask = factory->createPeriodicTask(
+ "UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
+ result = udpPollingTask->addComponent(objects::UDP_POLLING_TASK);
+ if(result != HasReturnvaluesIF::RETURN_OK) {
+ initmission::printAddObjectError("UDP_POLLING", objects::UDP_POLLING_TASK);
+ }
+
+ /* 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);
+ }
+
+ 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("PUS_EVENTS", 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("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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ //TODO: Add handling of missed deadlines
+ /* Polling Sequence Table Default */
+#if Q7S_ADD_SPI_TEST == 0
+ FixedTimeslotTaskIF * pollingSequenceTableTaskDefault = factory->createFixedTimeslotTask(
+ "PST_TASK_DEFAULT", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0,
+ missedDeadlineFunc);
+ result = pst::pollingSequenceInitDefault(pollingSequenceTableTaskDefault);
+ if (result != HasReturnvaluesIF::RETURN_OK) {
+ sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl;
+ }
+#endif
+
+#if TE0720 == 0
+ FixedTimeslotTaskIF* gomSpacePstTask = factory->
+ createFixedTimeslotTask("GS_PST_TASK", 50,
+ PeriodicTaskIF::MINIMUM_STACK_SIZE*8, 3.0, missedDeadlineFunc);
+ result = pst::gomspacePstInit(gomSpacePstTask);
+ if(result != HasReturnvaluesIF::RETURN_OK) {
+ sif::error << "InitMission::initTasks: GomSpace PST initialization failed!" << std::endl;
+ }
+#endif
+
+#if OBSW_ADD_TEST_CODE == 1
+ 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);
+ }
+
+#if Q7S_ADD_SPI_TEST == 1
+ result = testTask->addComponent(objects::SPI_TEST);
+ if(result != HasReturnvaluesIF::RETURN_OK) {
+ initmission::printAddObjectError("SPI_TEST", objects::SPI_TEST);
+ }
+#endif
+#endif /* OBSW_ADD_TEST_CODE == 1 */
+#if TE0720 == 1 && TEST_LIBGPIOD == 1
+ result = testTask->addComponent(objects::LIBGPIOD_TEST);
+ if(result != HasReturnvaluesIF::RETURN_OK) {
+ initmission::printAddObjectError("GPIOD_TEST", objects::LIBGPIOD_TEST);
+ }
+#endif /* TE0720 == 1 && TEST_LIBGPIOD == 1 */
+
+ sif::info << "Starting tasks.." << std::endl;
+ tmTcDistributor->startTask();
+ udpBridgeTask->startTask();
+ udpPollingTask->startTask();
+
+#if TE0720 == 0
+ gomSpacePstTask->startTask();
+#endif
+
+#if Q7S_ADD_SPI_TEST == 0
+ pollingSequenceTableTaskDefault->startTask();
+#endif
+
+ pusVerification->startTask();
+ pusEvents->startTask();
+ pusHighPrio->startTask();
+ pusMedPrio->startTask();
+ pusLowPrio->startTask();
+
+#if OBSW_ADD_TEST_CODE == 1
+ testTask->startTask();
+#endif
+ sif::info << "Tasks started.." << std::endl;
+}
diff --git a/bsp_q7s/InitMission.h b/bsp_q7s/InitMission.h
new file mode 100644
index 00000000..568b26b5
--- /dev/null
+++ b/bsp_q7s/InitMission.h
@@ -0,0 +1,9 @@
+#ifndef BSP_Q7S_INITMISSION_H_
+#define BSP_Q7S_INITMISSION_H_
+
+namespace initmission {
+void initMission();
+void initTasks();
+};
+
+#endif /* BSP_Q7S_INITMISSION_H_ */
diff --git a/bsp_q7s/ObjectFactory.cpp b/bsp_q7s/ObjectFactory.cpp
new file mode 100644
index 00000000..5519b84b
--- /dev/null
+++ b/bsp_q7s/ObjectFactory.cpp
@@ -0,0 +1,439 @@
+#include "ObjectFactory.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+/* UDP server includes */
+#include
+#include
+#include
+
+#if TEST_LIBGPIOD == 1
+#include
+#endif
+
+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::UDP_BRIDGE;
+ // No storage object for now.
+ TmFunnel::storageDestination = objects::NO_OBJECT;
+
+ LocalDataPoolManager::defaultHkDestination = objects::PUS_SERVICE_3_HOUSEKEEPING;
+
+ VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
+ TmPacketBase::timeStamperId = objects::TIME_STAMPER;
+}
+
+
+
+void ObjectFactory::produce(){
+ Factory::setStaticFrameworkObjectIds();
+ ObjectFactory::produceGenericObjects();
+
+#if TE0720 == 1
+ I2cCookie* i2cCookieTmp1075tcs1 = new I2cCookie(addresses::TMP1075_TCS_1,
+ TMP1075::MAX_REPLY_LENGTH, std::string("/dev/i2c-0"));
+ I2cCookie* i2cCookieTmp1075tcs2 = new I2cCookie(addresses::TMP1075_TCS_2,
+ TMP1075::MAX_REPLY_LENGTH, std::string("/dev/i2c-0"));
+#else
+ I2cCookie* i2cCookieTmp1075tcs1 = new I2cCookie(addresses::TMP1075_TCS_1,
+ TMP1075::MAX_REPLY_LENGTH, std::string("/dev/i2c-1"));
+ I2cCookie* i2cCookieTmp1075tcs2 = new I2cCookie(addresses::TMP1075_TCS_2,
+ TMP1075::MAX_REPLY_LENGTH, std::string("/dev/i2c-1"));
+#endif
+ LinuxLibgpioIF* gpioComIF = new LinuxLibgpioIF(objects::GPIO_IF);
+
+ /* Communication interfaces */
+ new CspComIF(objects::CSP_COM_IF);
+ new I2cComIF(objects::I2C_COM_IF);
+ new UartComIF(objects::UART_COM_IF);
+#if Q7S_ADD_SPI_TEST == 0
+ new SpiComIF(objects::SPI_COM_IF, gpioComIF);
+#endif
+
+ /* Temperature sensors */
+ Tmp1075Handler* tmp1075Handler_1 = new Tmp1075Handler(
+ objects::TMP1075_HANDLER_1, objects::I2C_COM_IF,
+ i2cCookieTmp1075tcs1);
+ tmp1075Handler_1->setStartUpImmediately();
+ Tmp1075Handler* tmp1075Handler_2 = new Tmp1075Handler(
+ objects::TMP1075_HANDLER_2, objects::I2C_COM_IF,
+ i2cCookieTmp1075tcs2);
+ tmp1075Handler_2->setStartUpImmediately();
+
+ GpioCookie* heaterGpiosCookie = new GpioCookie;
+
+#if TE0720 == 0
+ CspCookie* p60DockCspCookie = new CspCookie(P60Dock::MAX_REPLY_LENGTH,
+ addresses::P60DOCK);
+ CspCookie* pdu1CspCookie = new CspCookie(PDU::MAX_REPLY_LENGTH,
+ addresses::PDU1);
+ CspCookie* pdu2CspCookie = new CspCookie(PDU::MAX_REPLY_LENGTH,
+ addresses::PDU2);
+ CspCookie* acuCspCookie = new CspCookie(ACU::MAX_REPLY_LENGTH,
+ addresses::ACU);
+ /* Device Handler */
+ P60DockHandler* p60dockhandler = new P60DockHandler(objects::P60DOCK_HANDLER,
+ objects::CSP_COM_IF, p60DockCspCookie);
+ PDU1Handler* pdu1handler = new PDU1Handler(objects::PDU1_HANDLER,
+ objects::CSP_COM_IF, pdu1CspCookie);
+ PDU2Handler* pdu2handler = new PDU2Handler(objects::PDU2_HANDLER,
+ objects::CSP_COM_IF, pdu2CspCookie);
+ ACUHandler* acuhandler = new ACUHandler(objects::ACU_HANDLER,
+ objects::CSP_COM_IF, acuCspCookie);
+ new PCDUHandler(objects::PCDU_HANDLER, 50);
+
+ /**
+ * Setting PCDU devices to mode normal immediately after start up because PCDU is always
+ * running.
+ */
+ /** For now this needs to be commented out because there is no PCDU connected to the OBC */
+// p60dockhandler->setModeNormal();
+// pdu1handler->setModeNormal();
+// pdu2handler->setModeNormal();
+// acuhandler->setModeNormal();
+ (void) p60dockhandler;
+ (void) pdu1handler;
+ (void) pdu2handler;
+ (void) acuhandler;
+
+#if OBSW_ADD_ACS_BOARD == 1
+ GpioCookie* gpioCookieAcsBoard = new GpioCookie();
+ GpiodRegular* gpio = nullptr;
+ gpio = new GpiodRegular(std::string("gpiochip5"), 1, std::string("CS_GYRO_1_ADIS"),
+ gpio::OUT, gpio::HIGH);
+ gpioCookieAcsBoard->addGpio(gpioIds::GYRO_0_ADIS_CS, gpio);
+ gpio = new GpiodRegular(std::string("gpiochip5"), 7, std::string("CS_GYRO_2_L3G"),
+ gpio::OUT, gpio::HIGH);
+ gpioCookieAcsBoard->addGpio(gpioIds::GYRO_1_L3G_CS, gpio);
+ gpio = new GpiodRegular(std::string("gpiochip5"), 3, std::string("CS_GYRO_3_L3G"),
+ gpio::OUT, gpio::HIGH);
+ gpioCookieAcsBoard->addGpio(gpioIds::GYRO_2_L3G_CS, gpio);
+
+ gpio = new GpiodRegular(std::string("gpiochip5"), 5, std::string("CS_MGM_0_LIS3_A"),
+ gpio::OUT, gpio::HIGH);
+ gpioCookieAcsBoard->addGpio(gpioIds::MGM_0_LIS3_CS, gpio);
+
+ gpio = new GpiodRegular(std::string("gpiochip5"), 17, std::string("CS_MGM_1_RM3100_A"),
+ gpio::OUT, gpio::HIGH);
+ gpioCookieAcsBoard->addGpio(gpioIds::MGM_1_RM3100_CS, gpio);
+
+ gpio = new GpiodRegular(std::string("gpiochip6"), 0, std::string("CS_MGM_2_LIS3_B"),
+ gpio::OUT, gpio::HIGH);
+ gpioCookieAcsBoard->addGpio(gpioIds::MGM_2_LIS3_CS, gpio);
+
+ gpio = new GpiodRegular(std::string("gpiochip5"), 10, std::string("CS_MGM_3_RM3100_B"),
+ gpio::OUT, gpio::HIGH);
+ gpioCookieAcsBoard->addGpio(gpioIds::MGM_3_RM3100_CS, gpio);
+
+ gpioComIF->addGpios(gpioCookieAcsBoard);
+
+ std::string spiDev = "/dev/spidev2.0";
+ SpiCookie* 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 MGMHandlerLIS3MDL(objects::MGM_0_LIS3_HANDLER,
+ objects::SPI_COM_IF, spiCookie);
+ 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);
+ auto mgmLis3Handler2 = new MGMHandlerLIS3MDL(objects::MGM_2_LIS3_HANDLER,
+ objects::SPI_COM_IF, spiCookie);
+ mgmLis3Handler2->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 MGMHandlerRM3100(objects::MGM_1_RM3100_HANDLER,
+ objects::SPI_COM_IF, spiCookie);
+ mgmRm3100Handler->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);
+ gyroL3gHandler->setStartUpImmediately();
+#endif
+
+ /* Pin H2-11 on stack connector */
+ GpiodRegular* gpioConfigHeater0 = new GpiodRegular(std::string("gpiochip7"), 6,
+ std::string("Heater0"), gpio::OUT, 0);
+ heaterGpiosCookie->addGpio(gpioIds::HEATER_0, gpioConfigHeater0);
+
+ /* Pin H2-12 on stack connector */
+ GpiodRegular* gpioConfigHeater1 = new GpiodRegular(std::string("gpiochip7"), 12,
+ std::string("Heater1"), gpio::OUT, 0);
+ heaterGpiosCookie->addGpio(gpioIds::HEATER_1, gpioConfigHeater1);
+
+ /* Pin H2-13 on stack connector */
+ GpiodRegular* gpioConfigHeater2 = new GpiodRegular(std::string("gpiochip7"), 7,
+ std::string("Heater2"), gpio::OUT, 0);
+ heaterGpiosCookie->addGpio(gpioIds::HEATER_2, gpioConfigHeater2);
+
+ GpiodRegular* gpioConfigHeater3 = new GpiodRegular(std::string("gpiochip7"), 5,
+ std::string("Heater3"), gpio::OUT, 0);
+ heaterGpiosCookie->addGpio(gpioIds::HEATER_3, gpioConfigHeater3);
+
+ GpiodRegular* gpioConfigHeater4 = new GpiodRegular(std::string("gpiochip7"), 3,
+ std::string("Heater4"), gpio::OUT, 0);
+ heaterGpiosCookie->addGpio(gpioIds::HEATER_4, gpioConfigHeater4);
+
+ GpiodRegular* gpioConfigHeater5 = new GpiodRegular(std::string("gpiochip7"), 0,
+ std::string("Heater5"), gpio::OUT, 0);
+ heaterGpiosCookie->addGpio(gpioIds::HEATER_5, gpioConfigHeater5);
+
+ GpiodRegular* gpioConfigHeater6 = new GpiodRegular(std::string("gpiochip7"), 1,
+ std::string("Heater6"), gpio::OUT, 0);
+ heaterGpiosCookie->addGpio(gpioIds::HEATER_6, gpioConfigHeater6);
+
+ GpiodRegular* gpioConfigHeater7 = new GpiodRegular(std::string("gpiochip7"), 11,
+ std::string("Heater7"), gpio::OUT, 0);
+ heaterGpiosCookie->addGpio(gpioIds::HEATER_7, gpioConfigHeater7);
+
+ new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, heaterGpiosCookie,
+ objects::PCDU_HANDLER, pcduSwitches::TCS_BOARD_8V_HEATER_IN);
+
+ GpioCookie* solarArrayDeplCookie = new GpioCookie;
+
+ GpiodRegular* gpioConfigDeplSA0 = new GpiodRegular(std::string("gpiochip7"), 4,
+ std::string("DeplSA1"), gpio::OUT, 0);
+ solarArrayDeplCookie->addGpio(gpioIds::DEPLSA1, gpioConfigDeplSA0);
+ GpiodRegular* gpioConfigDeplSA1 = new GpiodRegular(std::string("gpiochip7"), 2,
+ std::string("DeplSA2"), gpio::OUT, 0);
+ solarArrayDeplCookie->addGpio(gpioIds::DEPLSA2, gpioConfigDeplSA1);
+
+ //TODO: Find out burn time. For now set to 1000 ms.
+ new SolarArrayDeploymentHandler(objects::SOLAR_ARRAY_DEPL_HANDLER, objects::GPIO_IF,
+ solarArrayDeplCookie, objects::PCDU_HANDLER, pcduSwitches::DEPLOYMENT_MECHANISM,
+ gpioIds::DEPLSA1, gpioIds::DEPLSA2, 1000);
+
+ UartCookie* syrlinksUartCookie = new UartCookie(
+ std::string("/dev/ttyUL0"), 38400, SYRLINKS::MAX_REPLY_SIZE);
+ syrlinksUartCookie->setParityEven();
+
+ SyrlinksHkHandler* syrlinksHkHandler = new SyrlinksHkHandler(objects::SYRLINKS_HK_HANDLER,
+ objects::UART_COM_IF, syrlinksUartCookie);
+ syrlinksHkHandler->setModeNormal();
+
+#if Q7S_ADD_RTD_DEVICES == 1
+ GpioCookie* rtdGpioCookie = new GpioCookie;
+
+ gpioCallbacks::initTcsBoardDecoder(gpioComIF);
+ GpioCallback* gpioRtdIc3 = new GpioCallback(std::string("Chip select RTD IC3"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC3, gpioRtdIc3);
+ GpioCallback* gpioRtdIc4 = new GpioCallback(std::string("Chip select RTD IC4"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC4, gpioRtdIc4);
+ GpioCallback* gpioRtdIc5 = new GpioCallback(std::string("Chip select RTD IC5"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC5, gpioRtdIc5);
+ GpioCallback* gpioRtdIc6 = new GpioCallback(std::string("Chip select RTD IC6"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC6, gpioRtdIc6);
+ GpioCallback* gpioRtdIc7 = new GpioCallback(std::string("Chip select RTD IC7"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC7, gpioRtdIc7);
+ GpioCallback* gpioRtdIc8 = new GpioCallback(std::string("Chip select RTD IC8"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC8, gpioRtdIc8);
+ GpioCallback* gpioRtdIc9 = new GpioCallback(std::string("Chip select RTD IC9"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC9, gpioRtdIc9);
+ GpioCallback* gpioRtdIc10 = new GpioCallback(std::string("Chip select RTD IC10"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC10, gpioRtdIc10);
+ GpioCallback* gpioRtdIc11 = new GpioCallback(std::string("Chip select RTD IC11"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC11, gpioRtdIc11);
+ GpioCallback* gpioRtdIc12 = new GpioCallback(std::string("Chip select RTD IC12"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC12, gpioRtdIc12);
+ GpioCallback* gpioRtdIc13 = new GpioCallback(std::string("Chip select RTD IC13"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC13, gpioRtdIc13);
+ GpioCallback* gpioRtdIc14 = new GpioCallback(std::string("Chip select RTD IC14"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC14, gpioRtdIc14);
+ GpioCallback* gpioRtdIc15 = new GpioCallback(std::string("Chip select RTD IC15"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC15, gpioRtdIc15);
+ GpioCallback* gpioRtdIc16 = new GpioCallback(std::string("Chip select RTD IC16"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC16, gpioRtdIc16);
+ GpioCallback* gpioRtdIc17 = new GpioCallback(std::string("Chip select RTD IC17"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC17, gpioRtdIc17);
+ GpioCallback* gpioRtdIc18 = new GpioCallback(std::string("Chip select RTD IC18"), gpio::OUT, 1,
+ &gpioCallbacks::tcsBoardDecoderCallback, gpioComIF);
+ rtdGpioCookie->addGpio(gpioIds::RTD_IC18, gpioRtdIc18);
+
+ gpioComIF->addGpios(rtdGpioCookie);
+
+ SpiCookie* spiRtdIc3 = new SpiCookie(addresses::RTD_IC3, gpioIds::RTD_IC3,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc4 = new SpiCookie(addresses::RTD_IC4, gpioIds::RTD_IC4,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc5 = new SpiCookie(addresses::RTD_IC5, gpioIds::RTD_IC5,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc6 = new SpiCookie(addresses::RTD_IC6, gpioIds::RTD_IC6,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc7 = new SpiCookie(addresses::RTD_IC7, gpioIds::RTD_IC7,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc8 = new SpiCookie(addresses::RTD_IC8, gpioIds::RTD_IC8,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc9 = new SpiCookie(addresses::RTD_IC9, gpioIds::RTD_IC9,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc10 = new SpiCookie(addresses::RTD_IC10, gpioIds::RTD_IC10,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc11 = new SpiCookie(addresses::RTD_IC11, gpioIds::RTD_IC11,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc12 = new SpiCookie(addresses::RTD_IC12, gpioIds::RTD_IC12,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc13 = new SpiCookie(addresses::RTD_IC13, gpioIds::RTD_IC13,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc14 = new SpiCookie(addresses::RTD_IC14, gpioIds::RTD_IC14,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc15 = new SpiCookie(addresses::RTD_IC15, gpioIds::RTD_IC15,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc16 = new SpiCookie(addresses::RTD_IC16, gpioIds::RTD_IC16,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc17 = new SpiCookie(addresses::RTD_IC17, gpioIds::RTD_IC17,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+ SpiCookie* spiRtdIc18 = new SpiCookie(addresses::RTD_IC18, gpioIds::RTD_IC18,
+ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE,
+ spi::SpiModes::MODE_1, 2000000);
+
+ Max31865PT1000Handler* rtdIc3 = new Max31865PT1000Handler(objects::RTD_IC3, objects::SPI_COM_IF, spiRtdIc3, 0); // 0 is switchId
+ Max31865PT1000Handler* rtdIc4 = new Max31865PT1000Handler(objects::RTD_IC4, objects::SPI_COM_IF, spiRtdIc4, 0);
+ Max31865PT1000Handler* rtdIc5 = new Max31865PT1000Handler(objects::RTD_IC5, objects::SPI_COM_IF, spiRtdIc5, 0);
+ Max31865PT1000Handler* rtdIc6 = new Max31865PT1000Handler(objects::RTD_IC6, objects::SPI_COM_IF, spiRtdIc6, 0);
+ Max31865PT1000Handler* rtdIc7 = new Max31865PT1000Handler(objects::RTD_IC7, objects::SPI_COM_IF, spiRtdIc7, 0);
+ Max31865PT1000Handler* rtdIc8 = new Max31865PT1000Handler(objects::RTD_IC8, objects::SPI_COM_IF, spiRtdIc8, 0);
+ Max31865PT1000Handler* rtdIc9 = new Max31865PT1000Handler(objects::RTD_IC9, objects::SPI_COM_IF, spiRtdIc9, 0);
+ Max31865PT1000Handler* rtdIc10 = new Max31865PT1000Handler(objects::RTD_IC10, objects::SPI_COM_IF, spiRtdIc10, 0);
+ Max31865PT1000Handler* rtdIc11 = new Max31865PT1000Handler(objects::RTD_IC11, objects::SPI_COM_IF, spiRtdIc11, 0);
+ Max31865PT1000Handler* rtdIc12 = new Max31865PT1000Handler(objects::RTD_IC12, objects::SPI_COM_IF, spiRtdIc12, 0);
+ Max31865PT1000Handler* rtdIc13 = new Max31865PT1000Handler(objects::RTD_IC13, objects::SPI_COM_IF, spiRtdIc13, 0);
+ Max31865PT1000Handler* rtdIc14 = new Max31865PT1000Handler(objects::RTD_IC14, objects::SPI_COM_IF, spiRtdIc14, 0);
+ Max31865PT1000Handler* rtdIc15 = new Max31865PT1000Handler(objects::RTD_IC15, objects::SPI_COM_IF, spiRtdIc15, 0);
+ Max31865PT1000Handler* rtdIc16 = new Max31865PT1000Handler(objects::RTD_IC16, objects::SPI_COM_IF, spiRtdIc16, 0);
+ Max31865PT1000Handler* rtdIc17 = new Max31865PT1000Handler(objects::RTD_IC17, objects::SPI_COM_IF, spiRtdIc17, 0);
+ Max31865PT1000Handler* rtdIc18 = new Max31865PT1000Handler(objects::RTD_IC18, objects::SPI_COM_IF, spiRtdIc18, 0);
+// rtdIc10->setStartUpImmediately();
+// rtdIc4->setStartUpImmediately();
+
+ (void) rtdIc3;
+ (void) rtdIc4;
+ (void) rtdIc5;
+ (void) rtdIc6;
+ (void) rtdIc7;
+ (void) rtdIc8;
+ (void) rtdIc9;
+ (void) rtdIc10;
+ (void) rtdIc11;
+ (void) rtdIc12;
+ (void) rtdIc13;
+ (void) rtdIc14;
+ (void) rtdIc15;
+ (void) rtdIc16;
+ (void) rtdIc17;
+ (void) rtdIc18;
+
+#endif /* Q7S_ADD_RTD_DEVICES == 1 */
+
+#endif /* TE0720 == 0 */
+
+ new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR, objects::TM_STORE,
+ objects::TC_STORE);
+ new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
+
+ I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, IMTQ::MAX_REPLY_SIZE,
+ std::string("/dev/i2c-0"));
+ IMTQHandler* imtqHandler = new IMTQHandler(objects::IMTQ_HANDLER, objects::I2C_COM_IF, imtqI2cCookie);
+ imtqHandler->setStartUpImmediately();
+
+#if TE0720 == 1 && TEST_LIBGPIOD == 1
+ /* Configure MIO0 as input */
+ GpiodRegular gpioConfigMio0(std::string("gpiochip0"), 0,
+ std::string("MIO0"), gpio::IN, 0);
+ GpioCookie* gpioCookie = new GpioCookie;
+ gpioCookie->addGpio(gpioIds::TEST_ID_0, gpioConfigMio0);
+ new LibgpiodTest(objects::LIBGPIOD_TEST, objects::GPIO_IF, gpioCookie);
+#elif TE0720 == 1
+ /* Configuration for MIO0 on TE0720-03-1CFA */
+ GpiodRegular gpioConfigForDummyHeater(std::string("gpiochip0"), 0,
+ std::string("Heater0"), gpio::OUT, 0);
+ heaterGpiosCookie->addGpio(gpioIds::HEATER_0, gpioConfigForDummyHeater);
+ new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, heaterGpiosCookie,
+ objects::PCDU_HANDLER, pcduSwitches::TCS_BOARD_8V_HEATER_IN);
+#endif
+
+#if Q7S_ADD_SPI_TEST == 1
+ new SpiTestClass(objects::SPI_TEST, gpioComIF);
+#endif
+}
diff --git a/bsp_q7s/ObjectFactory.h b/bsp_q7s/ObjectFactory.h
new file mode 100644
index 00000000..38ec0e9e
--- /dev/null
+++ b/bsp_q7s/ObjectFactory.h
@@ -0,0 +1,9 @@
+#ifndef BSP_Q7S_OBJECTFACTORY_H_
+#define BSP_Q7S_OBJECTFACTORY_H_
+
+namespace ObjectFactory {
+void setStatics();
+void produce();
+};
+
+#endif /* BSP_Q7S_OBJECTFACTORY_H_ */
diff --git a/bsp_q7s/boardconfig/CMakeLists.txt b/bsp_q7s/boardconfig/CMakeLists.txt
new file mode 100644
index 00000000..c32b326d
--- /dev/null
+++ b/bsp_q7s/boardconfig/CMakeLists.txt
@@ -0,0 +1,10 @@
+target_sources(${TARGET_NAME} PRIVATE
+ print.c
+)
+
+target_include_directories(${TARGET_NAME} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+
+
diff --git a/hosted/boardconfig/etl_profile.h b/bsp_q7s/boardconfig/etl_profile.h
similarity index 100%
rename from hosted/boardconfig/etl_profile.h
rename to bsp_q7s/boardconfig/etl_profile.h
diff --git a/hosted/boardconfig/gcov.h b/bsp_q7s/boardconfig/gcov.h
similarity index 100%
rename from hosted/boardconfig/gcov.h
rename to bsp_q7s/boardconfig/gcov.h
diff --git a/bsp_linux/boardconfig/print.c b/bsp_q7s/boardconfig/print.c
similarity index 81%
rename from bsp_linux/boardconfig/print.c
rename to bsp_q7s/boardconfig/print.c
index f409ee1b..c501e0b7 100644
--- a/bsp_linux/boardconfig/print.c
+++ b/bsp_q7s/boardconfig/print.c
@@ -1,4 +1,4 @@
-#include "print.h"
+#include
#include
void printChar(const char* character, bool errStream) {
diff --git a/bsp_linux/boardconfig/print.h b/bsp_q7s/boardconfig/print.h
similarity index 100%
rename from bsp_linux/boardconfig/print.h
rename to bsp_q7s/boardconfig/print.h
diff --git a/bsp_q7s/boardconfig/q7s_config.h b/bsp_q7s/boardconfig/q7s_config.h
new file mode 100644
index 00000000..782ecf4f
--- /dev/null
+++ b/bsp_q7s/boardconfig/q7s_config.h
@@ -0,0 +1,13 @@
+#ifndef BSP_Q7S_BOARDCONFIG_Q7S_CONFIG_H_
+#define BSP_Q7S_BOARDCONFIG_Q7S_CONFIG_H_
+
+#define Q7S_ADD_RTD_DEVICES 0
+
+/* Only one of those 2 should be enabled! */
+/* Add code for ACS board */
+#define OBSW_ADD_ACS_BOARD 0
+#define Q7S_ADD_SPI_TEST 0
+
+
+
+#endif /* BSP_Q7S_BOARDCONFIG_Q7S_CONFIG_H_ */
diff --git a/bsp_q7s/boardtest/CMakeLists.txt b/bsp_q7s/boardtest/CMakeLists.txt
new file mode 100644
index 00000000..0599b73f
--- /dev/null
+++ b/bsp_q7s/boardtest/CMakeLists.txt
@@ -0,0 +1,6 @@
+target_sources(${TARGET_NAME} PRIVATE
+)
+
+
+
+
diff --git a/bsp_q7s/bsp_q7s.mk b/bsp_q7s/bsp_q7s.mk
new file mode 100644
index 00000000..93bfdc78
--- /dev/null
+++ b/bsp_q7s/bsp_q7s.mk
@@ -0,0 +1,6 @@
+CXXSRC += $(wildcard $(CURRENTPATH)/*.cpp)
+CXXSRC += $(wildcard $(CURRENTPATH)/comIF/cookies/*.cpp)
+CXXSRC += $(wildcard $(CURRENTPATH)/comIF/*.cpp)
+CSRC += $(wildcard $(CURRENTPATH)/*.c)
+
+CSRC += $(wildcard $(CURRENTPATH)/boardconfig/*.c)
\ No newline at end of file
diff --git a/bsp_q7s/comIF/CMakeLists.txt b/bsp_q7s/comIF/CMakeLists.txt
new file mode 100644
index 00000000..0599b73f
--- /dev/null
+++ b/bsp_q7s/comIF/CMakeLists.txt
@@ -0,0 +1,6 @@
+target_sources(${TARGET_NAME} PRIVATE
+)
+
+
+
+
diff --git a/bsp_q7s/devices/CMakeLists.txt b/bsp_q7s/devices/CMakeLists.txt
new file mode 100644
index 00000000..9e6fb793
--- /dev/null
+++ b/bsp_q7s/devices/CMakeLists.txt
@@ -0,0 +1,4 @@
+target_sources(${TARGET_NAME} PRIVATE
+ HeaterHandler.cpp
+ SolarArrayDeploymentHandler.cpp
+)
diff --git a/bsp_q7s/devices/HeaterHandler.cpp b/bsp_q7s/devices/HeaterHandler.cpp
new file mode 100644
index 00000000..21a4a3f4
--- /dev/null
+++ b/bsp_q7s/devices/HeaterHandler.cpp
@@ -0,0 +1,370 @@
+#include "HeaterHandler.h"
+#include
+#include
+#include
+#include
+
+HeaterHandler::HeaterHandler(object_id_t setObjectId_, object_id_t gpioDriverId_,
+ CookieIF * gpioCookie_, object_id_t mainLineSwitcherObjectId_, uint8_t mainLineSwitch_) :
+ SystemObject(setObjectId_), gpioDriverId(gpioDriverId_), gpioCookie(gpioCookie_),
+ mainLineSwitcherObjectId(mainLineSwitcherObjectId_), mainLineSwitch(mainLineSwitch_),
+ actionHelper(this, nullptr) {
+ commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize,
+ MessageQueueMessage::MAX_MESSAGE_SIZE);
+}
+
+HeaterHandler::~HeaterHandler() {
+}
+
+ReturnValue_t HeaterHandler::performOperation(uint8_t operationCode) {
+
+ if (operationCode == DeviceHandlerIF::PERFORM_OPERATION) {
+ readCommandQueue();
+ handleActiveCommands();
+ return RETURN_OK;
+ }
+ return RETURN_OK;
+}
+
+ReturnValue_t HeaterHandler::initialize() {
+ ReturnValue_t result = SystemObject::initialize();
+ if (result != RETURN_OK) {
+ return ObjectManagerIF::CHILD_INIT_FAILED;
+ }
+
+ result = initializeHeaterMap();
+ if (result != RETURN_OK) {
+ return ObjectManagerIF::CHILD_INIT_FAILED;
+ }
+
+ gpioInterface = objectManager->get(gpioDriverId);
+ if (gpioInterface == nullptr) {
+ sif::error << "HeaterHandler::initialize: Invalid Gpio interface." << std::endl;
+ return ObjectManagerIF::CHILD_INIT_FAILED;
+ }
+
+ result = gpioInterface->addGpios(dynamic_cast(gpioCookie));
+ if (result != RETURN_OK) {
+ sif::error << "HeaterHandler::initialize: Failed to initialize Gpio interface" << std::endl;
+ return ObjectManagerIF::CHILD_INIT_FAILED;
+ }
+
+ IPCStore = objectManager->get(objects::IPC_STORE);
+ if (IPCStore == nullptr) {
+ sif::error << "HeaterHandler::initialize: IPC store not set up in factory." << std::endl;
+ return ObjectManagerIF::CHILD_INIT_FAILED;
+ }
+
+ if(mainLineSwitcherObjectId != objects::NO_OBJECT) {
+ mainLineSwitcher = objectManager->get(mainLineSwitcherObjectId);
+ if (mainLineSwitcher == nullptr) {
+ sif::error << "HeaterHandler::initialize: Main line switcher failed to fetch object"
+ << "from object ID." << std::endl;
+ return ObjectManagerIF::CHILD_INIT_FAILED;
+ }
+ }
+
+ result = actionHelper.initialize(commandQueue);
+ if (result != RETURN_OK) {
+ return ObjectManagerIF::CHILD_INIT_FAILED;
+ }
+
+ return RETURN_OK;
+}
+
+ReturnValue_t HeaterHandler::initializeHeaterMap(){
+ HeaterCommandInfo_t heaterCommandInfo;
+ for(switchNr_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) {
+ std::pair status = heaterMap.emplace(switchNr, heaterCommandInfo);
+ if (status.second == false) {
+ sif::error << "HeaterHandler::initializeHeaterMap: Failed to initialize heater map"
+ << std::endl;
+ return RETURN_FAILED;
+ }
+ }
+ return RETURN_OK;
+}
+
+void HeaterHandler::setInitialSwitchStates() {
+ for (switchNr_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) {
+ switchStates[switchNr] = OFF;
+ }
+}
+
+void HeaterHandler::readCommandQueue() {
+ CommandMessage command;
+ ReturnValue_t result = commandQueue->receiveMessage(&command);
+ if (result != RETURN_OK) {
+ return;
+ }
+
+ result = actionHelper.handleActionMessage(&command);
+ if (result == RETURN_OK) {
+ return;
+ }
+}
+
+ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId,
+ MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
+ ReturnValue_t result;
+ if (actionId != SWITCH_HEATER) {
+ result = COMMAND_NOT_SUPPORTED;
+ } else {
+ switchNr_t switchNr = *data;
+ HeaterMapIter heaterMapIter = heaterMap.find(switchNr);
+ if (heaterMapIter != heaterMap.end()) {
+ if (heaterMapIter->second.active) {
+ return COMMAND_ALREADY_WAITING;
+ }
+ heaterMapIter->second.action = *(data + 1);
+ heaterMapIter->second.active = true;
+ heaterMapIter->second.replyQueue = commandedBy;
+ }
+ else {
+ sif::error << "HeaterHandler::executeAction: Invalid switchNr" << std::endl;
+ return INVALID_SWITCH_NR;
+ }
+ result = RETURN_OK;
+ }
+ return result;
+}
+
+
+void HeaterHandler::sendSwitchCommand(uint8_t switchNr,
+ ReturnValue_t onOff) const {
+
+ ReturnValue_t result;
+ store_address_t storeAddress;
+ uint8_t commandData[2];
+
+ switch(onOff) {
+ case PowerSwitchIF::SWITCH_ON:
+ commandData[0] = switchNr;
+ commandData[1] = SET_SWITCH_ON;
+ break;
+ case PowerSwitchIF::SWITCH_OFF:
+ commandData[0] = switchNr;
+ commandData[1] = SET_SWITCH_OFF;
+ break;
+ default:
+ sif::error << "HeaterHandler::sendSwitchCommand: Invalid switch request"
+ << std::endl;
+ break;
+ }
+
+ result = IPCStore->addData(&storeAddress, commandData, sizeof(commandData));
+ if (result == RETURN_OK) {
+ CommandMessage message;
+ ActionMessage::setCommand(&message, SWITCH_HEATER, storeAddress);
+ /* Send heater command to own command queue */
+ result = commandQueue->sendMessage(commandQueue->getId(), &message, 0);
+ if (result != RETURN_OK) {
+ sif::debug << "HeaterHandler::sendSwitchCommand: Failed to send switch"
+ << "message" << std::endl;
+ }
+ }
+}
+
+void HeaterHandler::handleActiveCommands(){
+
+ HeaterMapIter heaterMapIter = heaterMap.begin();
+ for (; heaterMapIter != heaterMap.end(); heaterMapIter++) {
+ if (heaterMapIter->second.active) {
+ switch(heaterMapIter->second.action) {
+ case SET_SWITCH_ON:
+ handleSwitchOnCommand(heaterMapIter);
+ break;
+ case SET_SWITCH_OFF:
+ handleSwitchOffCommand(heaterMapIter);
+ break;
+ default:
+ sif::error << "HeaterHandler::handleActiveCommands: Invalid action commanded"
+ << std::endl;
+ break;
+ }
+ }
+ }
+}
+
+void HeaterHandler::handleSwitchOnCommand(HeaterMapIter heaterMapIter) {
+
+ ReturnValue_t result = RETURN_OK;
+ switchNr_t switchNr;
+
+ /* Check if command waits for main switch being set on and whether the timeout has expired */
+ if (heaterMapIter->second.waitMainSwitchOn
+ && heaterMapIter->second.mainSwitchCountdown.hasTimedOut()) {
+ //TODO - This requires the initiation of an FDIR procedure
+ triggerEvent(MAIN_SWITCH_TIMEOUT);
+ sif::error << "HeaterHandler::handleSwitchOnCommand: Main switch setting on timeout"
+ << std::endl;
+ heaterMapIter->second.active = false;
+ heaterMapIter->second.waitMainSwitchOn = false;
+ if (heaterMapIter->second.replyQueue != commandQueue->getId()) {
+ actionHelper.finish(false, heaterMapIter->second.replyQueue,
+ heaterMapIter->second.action, MAIN_SWITCH_SET_TIMEOUT );
+ }
+ return;
+ }
+
+ switchNr = heaterMapIter->first;
+ /* Check state of main line switch */
+ ReturnValue_t mainSwitchState = mainLineSwitcher->getSwitchState(mainLineSwitch);
+ if (mainSwitchState == PowerSwitchIF::SWITCH_ON) {
+ if (!checkSwitchState(switchNr)) {
+ gpioId_t gpioId = getGpioIdFromSwitchNr(switchNr);
+ result = gpioInterface->pullHigh(gpioId);
+ if (result != RETURN_OK) {
+ sif::error << "HeaterHandler::handleSwitchOnCommand: Failed to pull gpio with id "
+ << gpioId << " high" << std::endl;
+ triggerEvent(GPIO_PULL_HIGH_FAILED, result);
+ }
+ else {
+ switchStates[switchNr] = ON;
+ }
+ }
+ else {
+ triggerEvent(SWITCH_ALREADY_ON, switchNr);
+ }
+ /* There is no need to send action finish replies if the sender was the
+ * HeaterHandler itself. */
+ if (heaterMapIter->second.replyQueue != commandQueue->getId()) {
+ if(result == RETURN_OK) {
+ actionHelper.finish(true, heaterMapIter->second.replyQueue,
+ heaterMapIter->second.action, result);
+ }
+ else {
+ actionHelper.finish(false, heaterMapIter->second.replyQueue,
+ heaterMapIter->second.action, result);
+ }
+
+ }
+ heaterMapIter->second.active = false;
+ heaterMapIter->second.waitMainSwitchOn = false;
+ }
+ else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF
+ && heaterMapIter->second.waitMainSwitchOn) {
+ /* Just waiting for the main switch being set on */
+ return;
+ }
+ else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF) {
+ mainLineSwitcher->sendSwitchCommand(mainLineSwitch,
+ PowerSwitchIF::SWITCH_ON);
+ heaterMapIter->second.mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs());
+ heaterMapIter->second.waitMainSwitchOn = true;
+ }
+ else {
+ sif::debug << "HeaterHandler::handleActiveCommands: Failed to get state of"
+ << " main line switch" << std::endl;
+ if (heaterMapIter->second.replyQueue != commandQueue->getId()) {
+ actionHelper.finish(false, heaterMapIter->second.replyQueue,
+ heaterMapIter->second.action, mainSwitchState);
+ }
+ heaterMapIter->second.active = false;
+ }
+}
+
+void HeaterHandler::handleSwitchOffCommand(HeaterMapIter heaterMapIter) {
+ ReturnValue_t result = RETURN_OK;
+ switchNr_t switchNr = heaterMapIter->first;
+ /* Check whether switch is already off */
+ if (checkSwitchState(switchNr)) {
+ gpioId_t gpioId = getGpioIdFromSwitchNr(switchNr);
+ result = gpioInterface->pullLow(gpioId);
+ if (result != RETURN_OK) {
+ sif::error << "HeaterHandler::handleSwitchOffCommand: Failed to pull gpio with id"
+ << gpioId << " low" << std::endl;
+ triggerEvent(GPIO_PULL_LOW_FAILED, result);
+ }
+ else {
+ switchStates[switchNr] = OFF;
+ /* When all switches are off, also main line switch will be turned off */
+ if (allSwitchesOff()) {
+ mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
+ }
+ }
+ }
+ else {
+ sif::info << "HeaterHandler::handleSwitchOffCommand: Switch already off" << std::endl;
+ triggerEvent(SWITCH_ALREADY_OFF, switchNr);
+ }
+ if (heaterMapIter->second.replyQueue != NO_COMMANDER) {
+ /* Report back switch command reply if necessary */
+ if(result == HasReturnvaluesIF::RETURN_OK) {
+ actionHelper.finish(true, heaterMapIter->second.replyQueue,
+ heaterMapIter->second.action, result);
+ }
+ else {
+ actionHelper.finish(false, heaterMapIter->second.replyQueue,
+ heaterMapIter->second.action, result);
+ }
+ }
+ heaterMapIter->second.active = false;
+}
+
+bool HeaterHandler::checkSwitchState(int switchNr) {
+ return switchStates[switchNr];
+}
+
+bool HeaterHandler::allSwitchesOff() {
+ bool allSwitchesOrd = false;
+ /* Or all switches. As soon one switch is on, allSwitchesOrd will be true */
+ for (switchNr_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) {
+ allSwitchesOrd = allSwitchesOrd || switchStates[switchNr];
+ }
+ return !allSwitchesOrd;
+}
+
+gpioId_t HeaterHandler::getGpioIdFromSwitchNr(int switchNr) {
+ gpioId_t gpioId = 0xFFFF;
+ switch(switchNr) {
+ case heaterSwitches::HEATER_0:
+ gpioId = gpioIds::HEATER_0;
+ break;
+ case heaterSwitches::HEATER_1:
+ gpioId = gpioIds::HEATER_1;
+ break;
+ case heaterSwitches::HEATER_2:
+ gpioId = gpioIds::HEATER_2;
+ break;
+ case heaterSwitches::HEATER_3:
+ gpioId = gpioIds::HEATER_3;
+ break;
+ case heaterSwitches::HEATER_4:
+ gpioId = gpioIds::HEATER_4;
+ break;
+ case heaterSwitches::HEATER_5:
+ gpioId = gpioIds::HEATER_5;
+ break;
+ case heaterSwitches::HEATER_6:
+ gpioId = gpioIds::HEATER_6;
+ break;
+ case heaterSwitches::HEATER_7:
+ gpioId = gpioIds::HEATER_7;
+ break;
+ default:
+ sif::error << "HeaterHandler::getGpioIdFromSwitchNr: Unknown heater switch number"
+ << std::endl;
+ break;
+ }
+ return gpioId;
+}
+
+MessageQueueId_t HeaterHandler::getCommandQueue() const {
+ return commandQueue->getId();
+}
+
+void HeaterHandler::sendFuseOnCommand(uint8_t fuseNr) const {
+}
+
+ReturnValue_t HeaterHandler::getSwitchState( uint8_t switchNr ) const {
+ return 0;
+}
+
+ReturnValue_t HeaterHandler::getFuseState( uint8_t fuseNr ) const {
+ return 0;
+}
+
+uint32_t HeaterHandler::getSwitchDelayMs(void) const {
+ return 0;
+}
diff --git a/bsp_q7s/devices/HeaterHandler.h b/bsp_q7s/devices/HeaterHandler.h
new file mode 100644
index 00000000..8969ebd9
--- /dev/null
+++ b/bsp_q7s/devices/HeaterHandler.h
@@ -0,0 +1,177 @@
+#ifndef MISSION_DEVICES_HEATERHANDLER_H_
+#define MISSION_DEVICES_HEATERHANDLER_H_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/**
+ * @brief This class intends the control of heaters.
+ *
+ * @author J. Meier
+ */
+class HeaterHandler: public ExecutableObjectIF,
+ public PowerSwitchIF,
+ public SystemObject,
+ public HasActionsIF {
+public:
+
+ /** Device command IDs */
+ static const DeviceCommandId_t SWITCH_HEATER = 0x0;
+
+ HeaterHandler(object_id_t setObjectId, object_id_t gpioDriverId, CookieIF * gpioCookie,
+ object_id_t mainLineSwitcherObjectId, uint8_t mainLineSwitch);
+
+ virtual ~HeaterHandler();
+
+ virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
+
+ virtual void sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) const override;
+ virtual void sendFuseOnCommand(uint8_t fuseNr) const override;
+ /**
+ * @brief This function will be called from the Heater object to check
+ * the current switch state.
+ */
+ virtual ReturnValue_t getSwitchState( uint8_t switchNr ) const override;
+ virtual ReturnValue_t getFuseState( uint8_t fuseNr ) const override;
+ virtual uint32_t getSwitchDelayMs(void) const override;
+
+ virtual MessageQueueId_t getCommandQueue() const override;
+ virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
+ const uint8_t* data, size_t size) override;
+ virtual ReturnValue_t initialize() override;
+
+private:
+
+ static const uint8_t INTERFACE_ID = CLASS_ID::HEATER_HANDLER;
+
+ static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1);
+ static const ReturnValue_t INIT_FAILED = MAKE_RETURN_CODE(0xA2);
+ static const ReturnValue_t INVALID_SWITCH_NR = MAKE_RETURN_CODE(0xA3);
+ static const ReturnValue_t MAIN_SWITCH_SET_TIMEOUT = MAKE_RETURN_CODE(0xA4);
+ static const ReturnValue_t COMMAND_ALREADY_WAITING = MAKE_RETURN_CODE(0xA5);
+
+ static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HEATER_HANDLER;
+ static const Event GPIO_PULL_HIGH_FAILED = MAKE_EVENT(0, severity::LOW);
+ static const Event GPIO_PULL_LOW_FAILED = MAKE_EVENT(1, severity::LOW);
+ static const Event SWITCH_ALREADY_ON = MAKE_EVENT(2, severity::LOW);
+ static const Event SWITCH_ALREADY_OFF = MAKE_EVENT(3, severity::LOW);
+ static const Event MAIN_SWITCH_TIMEOUT = MAKE_EVENT(4, severity::LOW);
+
+ static const MessageQueueId_t NO_COMMANDER = 0;
+
+ enum SwitchState : bool {
+ ON = true,
+ OFF = false
+ };
+
+
+ /**
+ * @brief Struct holding information about a heater command to execute.
+ *
+ * @param action The action to perform.
+ * @param replyQueue The queue of the commander to which status replies
+ * will be sent.
+ * @param active True if command is waiting for execution, otherwise false.
+ * @param waitSwitchOn True if the command is waiting for the main switch being set on.
+ * @param mainSwitchCountdown Sets timeout to wait for main switch being set on.
+ */
+ typedef struct HeaterCommandInfo {
+ uint8_t action;
+ MessageQueueId_t replyQueue;
+ bool active = false;
+ bool waitMainSwitchOn = false;
+ Countdown mainSwitchCountdown;
+ } HeaterCommandInfo_t;
+
+ enum SwitchAction {
+ SET_SWITCH_OFF,
+ SET_SWITCH_ON
+ };
+
+ using switchNr_t = uint8_t;
+ using HeaterMap = std::unordered_map;
+ using HeaterMapIter = HeaterMap::iterator;
+
+ HeaterMap heaterMap;
+
+ bool switchStates[heaterSwitches::NUMBER_OF_SWITCHES];
+
+ /** Size of command queue */
+ size_t cmdQueueSize = 20;
+
+ /**
+ * The object ID of the GPIO driver which enables and disables the
+ * heaters.
+ */
+ object_id_t gpioDriverId;
+
+ CookieIF * gpioCookie;
+
+ GpioIF* gpioInterface = nullptr;
+
+ /** Queue to receive messages from other objects. */
+ MessageQueueIF* commandQueue = nullptr;
+
+ object_id_t mainLineSwitcherObjectId;
+
+ /** Switch number of the heater power supply switch */
+ uint8_t mainLineSwitch;
+
+ /**
+ * Power switcher object which controls the 8V main line of the heater
+ * logic on the TCS board.
+ */
+ PowerSwitchIF *mainLineSwitcher = nullptr;
+
+ ActionHelper actionHelper;
+
+ StorageManagerIF *IPCStore = nullptr;
+
+ void readCommandQueue();
+
+ /**
+ * @brief Returns the state of a switch (ON - true, or OFF - false).
+ * @param switchNr The number of the switch to check.
+ */
+ bool checkSwitchState(int switchNr);
+
+ /**
+ * @brief Returns the ID of the GPIO related to a heater identified by the switch number
+ * which is defined in the heaterSwitches list.
+ */
+ gpioId_t getGpioIdFromSwitchNr(int switchNr);
+
+ /**
+ * @brief This function runs commands waiting for execution.
+ */
+ void handleActiveCommands();
+
+ ReturnValue_t initializeHeaterMap();
+
+ /**
+ * @brief Sets all switches to OFF.
+ */
+ void setInitialSwitchStates();
+
+ void handleSwitchOnCommand(HeaterMapIter heaterMapIter);
+
+ void handleSwitchOffCommand(HeaterMapIter heaterMapIter);
+
+ /**
+ * @brief Checks if all switches are off.
+ * @return True if all switches are off, otherwise false.
+ */
+ bool allSwitchesOff();
+
+};
+
+#endif /* MISSION_DEVICES_HEATERHANDLER_H_ */
diff --git a/bsp_q7s/devices/SolarArrayDeploymentHandler.cpp b/bsp_q7s/devices/SolarArrayDeploymentHandler.cpp
new file mode 100644
index 00000000..25be3927
--- /dev/null
+++ b/bsp_q7s/devices/SolarArrayDeploymentHandler.cpp
@@ -0,0 +1,201 @@
+#include "SolarArrayDeploymentHandler.h"
+
+#include
+#include
+
+#include
+#include
+
+
+SolarArrayDeploymentHandler::SolarArrayDeploymentHandler(object_id_t setObjectId_,
+ object_id_t gpioDriverId_, CookieIF * gpioCookie_, object_id_t mainLineSwitcherObjectId_,
+ uint8_t mainLineSwitch_, gpioId_t deplSA1, gpioId_t deplSA2, uint32_t burnTimeMs) :
+ SystemObject(setObjectId_), gpioDriverId(gpioDriverId_), gpioCookie(gpioCookie_),
+ mainLineSwitcherObjectId(mainLineSwitcherObjectId_), mainLineSwitch(mainLineSwitch_),
+ deplSA1(deplSA1), deplSA2(deplSA2), burnTimeMs(burnTimeMs), actionHelper(this, nullptr) {
+ commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize,
+ MessageQueueMessage::MAX_MESSAGE_SIZE);
+}
+
+SolarArrayDeploymentHandler::~SolarArrayDeploymentHandler() {
+}
+
+ReturnValue_t SolarArrayDeploymentHandler::performOperation(uint8_t operationCode) {
+
+ if (operationCode == DeviceHandlerIF::PERFORM_OPERATION) {
+ handleStateMachine();
+ return RETURN_OK;
+ }
+ return RETURN_OK;
+}
+
+ReturnValue_t SolarArrayDeploymentHandler::initialize() {
+ ReturnValue_t result = SystemObject::initialize();
+ if (result != RETURN_OK) {
+ return ObjectManagerIF::CHILD_INIT_FAILED;
+ }
+
+ gpioInterface = objectManager->get(gpioDriverId);
+ if (gpioInterface == nullptr) {
+ sif::error << "SolarArrayDeploymentHandler::initialize: Invalid Gpio interface."
+ << std::endl;
+ return ObjectManagerIF::CHILD_INIT_FAILED;
+ }
+
+ result = gpioInterface->addGpios(dynamic_cast(gpioCookie));
+ if (result != RETURN_OK) {
+ sif::error << "SolarArrayDeploymentHandler::initialize: Failed to initialize Gpio interface"
+ << std::endl;
+ return ObjectManagerIF::CHILD_INIT_FAILED;
+ }
+
+ if (mainLineSwitcherObjectId != objects::NO_OBJECT) {
+ mainLineSwitcher = objectManager->get(mainLineSwitcherObjectId);
+ if (mainLineSwitcher == nullptr) {
+ sif::error
+ << "SolarArrayDeploymentHandler::initialize: Main line switcher failed to fetch object"
+ << "from object ID." << std::endl;
+ return ObjectManagerIF::CHILD_INIT_FAILED;
+ }
+ }
+
+ result = actionHelper.initialize(commandQueue);
+ if (result != RETURN_OK) {
+ return ObjectManagerIF::CHILD_INIT_FAILED;
+ }
+
+ return RETURN_OK;
+}
+
+void SolarArrayDeploymentHandler::handleStateMachine() {
+ switch (stateMachine) {
+ case WAIT_ON_DELOYMENT_COMMAND:
+ readCommandQueue();
+ break;
+ case SWITCH_8V_ON:
+ mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_ON);
+ mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs());
+ stateMachine = WAIT_ON_8V_SWITCH;
+ break;
+ case WAIT_ON_8V_SWITCH:
+ performWaitOn8VActions();
+ break;
+ case SWITCH_DEPL_GPIOS:
+ switchDeploymentTransistors();
+ break;
+ case WAIT_ON_DEPLOYMENT_FINISH:
+ handleDeploymentFinish();
+ break;
+ case WAIT_FOR_MAIN_SWITCH_OFF:
+ if (mainLineSwitcher->getSwitchState(mainLineSwitch) == PowerSwitchIF::SWITCH_OFF) {
+ stateMachine = WAIT_ON_DELOYMENT_COMMAND;
+ } else if (mainSwitchCountdown.hasTimedOut()) {
+ triggerEvent(MAIN_SWITCH_OFF_TIMEOUT);
+ sif::error << "SolarArrayDeploymentHandler::handleStateMachine: Failed to switch main"
+ << " switch off" << std::endl;
+ stateMachine = WAIT_ON_DELOYMENT_COMMAND;
+ }
+ break;
+ default:
+ sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Invalid state" << std::endl;
+ break;
+ }
+}
+
+void SolarArrayDeploymentHandler::performWaitOn8VActions() {
+ if (mainLineSwitcher->getSwitchState(mainLineSwitch) == PowerSwitchIF::SWITCH_ON) {
+ stateMachine = SWITCH_DEPL_GPIOS;
+ } else {
+ if (mainSwitchCountdown.hasTimedOut()) {
+ triggerEvent(MAIN_SWITCH_ON_TIMEOUT);
+ actionHelper.finish(false, rememberCommanderId, DEPLOY_SOLAR_ARRAYS,
+ MAIN_SWITCH_TIMEOUT_FAILURE);
+ stateMachine = WAIT_ON_DELOYMENT_COMMAND;
+ }
+ }
+}
+
+void SolarArrayDeploymentHandler::switchDeploymentTransistors() {
+ ReturnValue_t result = RETURN_OK;
+ result = gpioInterface->pullHigh(deplSA1);
+ if (result != RETURN_OK) {
+ sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
+ " array deployment switch 1 high " << std::endl;
+ /* If gpio switch high failed, state machine is reset to wait for a command reinitiating
+ * the deployment sequence. */
+ stateMachine = WAIT_ON_DELOYMENT_COMMAND;
+ triggerEvent(DEPL_SA1_GPIO_SWTICH_ON_FAILED);
+ actionHelper.finish(false, rememberCommanderId, DEPLOY_SOLAR_ARRAYS,
+ SWITCHING_DEPL_SA2_FAILED);
+ mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
+ }
+ result = gpioInterface->pullHigh(deplSA2);
+ if (result != RETURN_OK) {
+ sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
+ " array deployment switch 2 high " << std::endl;
+ stateMachine = WAIT_ON_DELOYMENT_COMMAND;
+ triggerEvent(DEPL_SA2_GPIO_SWTICH_ON_FAILED);
+ actionHelper.finish(false, rememberCommanderId, DEPLOY_SOLAR_ARRAYS,
+ SWITCHING_DEPL_SA2_FAILED);
+ mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
+ }
+ deploymentCountdown.setTimeout(burnTimeMs);
+ stateMachine = WAIT_ON_DEPLOYMENT_FINISH;
+}
+
+void SolarArrayDeploymentHandler::handleDeploymentFinish() {
+ ReturnValue_t result = RETURN_OK;
+ if (deploymentCountdown.hasTimedOut()) {
+ actionHelper.finish(true, rememberCommanderId, DEPLOY_SOLAR_ARRAYS, RETURN_OK);
+ result = gpioInterface->pullLow(deplSA1);
+ if (result != RETURN_OK) {
+ sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
+ " array deployment switch 1 low " << std::endl;
+ }
+ result = gpioInterface->pullLow(deplSA2);
+ if (result != RETURN_OK) {
+ sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
+ " array deployment switch 2 low " << std::endl;
+ }
+ mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
+ mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs());
+ stateMachine = WAIT_FOR_MAIN_SWITCH_OFF;
+ }
+}
+
+void SolarArrayDeploymentHandler::readCommandQueue() {
+ CommandMessage command;
+ ReturnValue_t result = commandQueue->receiveMessage(&command);
+ if (result != RETURN_OK) {
+ return;
+ }
+
+ result = actionHelper.handleActionMessage(&command);
+ if (result == RETURN_OK) {
+ return;
+ }
+}
+
+ReturnValue_t SolarArrayDeploymentHandler::executeAction(ActionId_t actionId,
+ MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
+ ReturnValue_t result;
+ if (stateMachine != WAIT_ON_DELOYMENT_COMMAND) {
+ sif::error << "SolarArrayDeploymentHandler::executeAction: Received command while not in"
+ << "waiting-on-command-state" << std::endl;
+ return DEPLOYMENT_ALREADY_EXECUTING;
+ }
+ if (actionId != DEPLOY_SOLAR_ARRAYS) {
+ sif::error << "SolarArrayDeploymentHandler::executeAction: Received invalid command"
+ << std::endl;
+ result = COMMAND_NOT_SUPPORTED;
+ } else {
+ stateMachine = SWITCH_8V_ON;
+ rememberCommanderId = commandedBy;
+ result = RETURN_OK;
+ }
+ return result;
+}
+
+MessageQueueId_t SolarArrayDeploymentHandler::getCommandQueue() const {
+ return commandQueue->getId();
+}
diff --git a/bsp_q7s/devices/SolarArrayDeploymentHandler.h b/bsp_q7s/devices/SolarArrayDeploymentHandler.h
new file mode 100644
index 00000000..5e573128
--- /dev/null
+++ b/bsp_q7s/devices/SolarArrayDeploymentHandler.h
@@ -0,0 +1,158 @@
+#ifndef MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_
+#define MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/**
+ * @brief This class is used to control the solar array deployment.
+ *
+ * @author J. Meier
+ */
+class SolarArrayDeploymentHandler: public ExecutableObjectIF,
+ public SystemObject,
+ public HasReturnvaluesIF,
+ public HasActionsIF {
+public:
+
+ static const DeviceCommandId_t DEPLOY_SOLAR_ARRAYS = 0x5;
+
+ /**
+ * @brief constructor
+ *
+ * @param setObjectId The object id of the SolarArrayDeploymentHandler.
+ * @param gpioDriverId The id of the gpio com if.
+ * @param gpioCookie GpioCookie holding information about the gpios used to switch the
+ * transistors.
+ * @param mainLineSwitcherObjectId The object id of the object responsible for switching
+ * the 8V power source. This is normally the PCDU.
+ * @param mainLineSwitch The id of the main line switch. This is defined in
+ * powerSwitcherList.h.
+ * @param deplSA1 gpioId of the GPIO controlling the deployment 1 transistor.
+ * @param deplSA2 gpioId of the GPIO controlling the deployment 2 transistor.
+ * @param burnTimeMs Time duration the power will be applied to the burn wires.
+ */
+ SolarArrayDeploymentHandler(object_id_t setObjectId, object_id_t gpioDriverId,
+ CookieIF * gpioCookie, object_id_t mainLineSwitcherObjectId, uint8_t mainLineSwitch,
+ gpioId_t deplSA1, gpioId_t deplSA2, uint32_t burnTimeMs);
+
+ virtual ~SolarArrayDeploymentHandler();
+
+ virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
+
+ virtual MessageQueueId_t getCommandQueue() const override;
+ virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
+ const uint8_t* data, size_t size) override;
+ virtual ReturnValue_t initialize() override;
+
+private:
+
+ static const uint8_t INTERFACE_ID = CLASS_ID::SA_DEPL_HANDLER;
+ static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA0);
+ static const ReturnValue_t DEPLOYMENT_ALREADY_EXECUTING = MAKE_RETURN_CODE(0xA1);
+ static const ReturnValue_t MAIN_SWITCH_TIMEOUT_FAILURE = MAKE_RETURN_CODE(0xA2);
+ static const ReturnValue_t SWITCHING_DEPL_SA1_FAILED = MAKE_RETURN_CODE(0xA3);
+ static const ReturnValue_t SWITCHING_DEPL_SA2_FAILED = MAKE_RETURN_CODE(0xA4);
+
+ static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SA_DEPL_HANDLER;
+ static const Event MAIN_SWITCH_ON_TIMEOUT = MAKE_EVENT(0, severity::LOW);
+ static const Event MAIN_SWITCH_OFF_TIMEOUT = MAKE_EVENT(1, severity::LOW);
+ static const Event DEPLOYMENT_FAILED = MAKE_EVENT(2, severity::HIGH);
+ static const Event DEPL_SA1_GPIO_SWTICH_ON_FAILED = MAKE_EVENT(3, severity::HIGH);
+ static const Event DEPL_SA2_GPIO_SWTICH_ON_FAILED = MAKE_EVENT(4, severity::HIGH);
+
+
+ enum StateMachine {
+ WAIT_ON_DELOYMENT_COMMAND,
+ SWITCH_8V_ON,
+ WAIT_ON_8V_SWITCH,
+ SWITCH_DEPL_GPIOS,
+ WAIT_ON_DEPLOYMENT_FINISH,
+ WAIT_FOR_MAIN_SWITCH_OFF
+ };
+
+ StateMachine stateMachine = WAIT_ON_DELOYMENT_COMMAND;
+
+ /**
+ * This countdown is used to check if the PCDU sets the 8V line on in the intended time.
+ */
+ Countdown mainSwitchCountdown;
+
+ /**
+ * This countdown is used to wait for the burn wire being successful cut.
+ */
+ Countdown deploymentCountdown;
+
+
+ /**
+ * The message queue id of the component commanding an action will be stored in this variable.
+ * This is necessary to send later the action finish replies.
+ */
+ MessageQueueId_t rememberCommanderId = 0;
+
+ /** Size of command queue */
+ size_t cmdQueueSize = 20;
+
+ /** The object ID of the GPIO driver which switches the deployment transistors */
+ object_id_t gpioDriverId;
+
+ CookieIF * gpioCookie;
+
+ /** Object id of the object responsible to switch the 8V power input. Typically the PCDU. */
+ object_id_t mainLineSwitcherObjectId;
+
+ /** Switch number of the 8V power switch */
+ uint8_t mainLineSwitch;
+
+ gpioId_t deplSA1;
+ gpioId_t deplSA2;
+
+ GpioIF* gpioInterface = nullptr;
+
+ /** Time duration switches are active to cut the burn wire */
+ uint32_t burnTimeMs;
+
+ /** Queue to receive messages from other objects. */
+ MessageQueueIF* commandQueue = nullptr;
+
+ /**
+ * After initialization this pointer will hold the reference to the main line switcher object.
+ */
+ PowerSwitchIF *mainLineSwitcher = nullptr;
+
+ ActionHelper actionHelper;
+
+ void readCommandQueue();
+
+ /**
+ * @brief This function performs actions dependent on the current state.
+ */
+ void handleStateMachine();
+
+ /**
+ * @brief This function polls the 8V switch state and changes the state machine when the
+ * switch has been enabled.
+ */
+ void performWaitOn8VActions();
+
+ /**
+ * @brief This functions handles the switching of the solar array deployment transistors.
+ */
+ void switchDeploymentTransistors();
+
+ /**
+ * @brief This function performs actions to finish the deployment. Essentially switches
+ * are turned of after the burn time has expired.
+ */
+ void handleDeploymentFinish();
+};
+
+#endif /* MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_ */
diff --git a/bsp_q7s/gpio/CMakeLists.txt b/bsp_q7s/gpio/CMakeLists.txt
new file mode 100644
index 00000000..dd657546
--- /dev/null
+++ b/bsp_q7s/gpio/CMakeLists.txt
@@ -0,0 +1,3 @@
+target_sources(${TARGET_NAME} PRIVATE
+ gpioCallbacks.cpp
+)
diff --git a/bsp_q7s/gpio/gpioCallbacks.cpp b/bsp_q7s/gpio/gpioCallbacks.cpp
new file mode 100644
index 00000000..086e6469
--- /dev/null
+++ b/bsp_q7s/gpio/gpioCallbacks.cpp
@@ -0,0 +1,221 @@
+#include "gpioCallbacks.h"
+#include
+
+#include
+#include
+#include
+
+
+namespace gpioCallbacks {
+
+GpioIF* gpioComInterface;
+
+void initTcsBoardDecoder(GpioIF* gpioComIF) {
+
+ ReturnValue_t result;
+
+ if (gpioComIF == nullptr) {
+ sif::debug << "initTcsBoardDecoder: Invalid gpioComIF" << std::endl;
+ return;
+ }
+
+ gpioComInterface = gpioComIF;
+
+ GpioCookie* spiMuxGpios = new GpioCookie;
+ /**
+ * Initial values of the spi mux gpios can all be set to an arbitrary value expect for spi mux
+ * bit 1. Setting spi mux bit 1 to high will pull all decoder outputs to high voltage level.
+ */
+ GpiodRegular* spiMuxBit1 = new GpiodRegular(std::string("gpiochip7"), 13,
+ std::string("SPI Mux Bit 1"), gpio::OUT, 1);
+ spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_1, spiMuxBit1);
+ GpiodRegular* spiMuxBit2 = new GpiodRegular(std::string("gpiochip7"), 14,
+ std::string("SPI Mux Bit 2"), gpio::OUT, 0);
+ spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_2, spiMuxBit2);
+ GpiodRegular* spiMuxBit3 = new GpiodRegular(std::string("gpiochip7"), 15,
+ std::string("SPI Mux Bit 3"), gpio::OUT, 0);
+ spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_3, spiMuxBit3);
+ GpiodRegular* spiMuxBit4 = new GpiodRegular(std::string("gpiochip7"), 16,
+ std::string("SPI Mux Bit 4"), gpio::OUT, 0);
+ spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_4, spiMuxBit4);
+ GpiodRegular* spiMuxBit5 = new GpiodRegular(std::string("gpiochip7"), 17,
+ std::string("SPI Mux Bit 5"), gpio::OUT, 0);
+ spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_5, spiMuxBit5);
+ GpiodRegular* spiMuxBit6 = new GpiodRegular(std::string("gpiochip7"), 18,
+ std::string("SPI Mux Bit 6"), gpio::OUT, 0);
+ spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_6, spiMuxBit6);
+
+ result = gpioComInterface->addGpios(spiMuxGpios);
+ if (result != HasReturnvaluesIF::RETURN_OK) {
+ sif::error << "initTcsBoardDecoder: Failed to add mux bit gpios to gpioComIF"
+ << std::endl;
+ return;
+ }
+}
+
+void tcsBoardDecoderCallback(gpioId_t gpioId, gpio::GpioOperation gpioOp, int value,
+ void* args) {
+
+ if (gpioComInterface == nullptr) {
+ sif::debug << "tcsBoardDecoderCallback: No gpioComIF specified. Call initTcsBoardDecoder "
+ << "to specify gpioComIF" << std::endl;
+ return;
+ }
+
+ /* Read is not supported by the callback function */
+ if (gpioOp == gpio::GpioOperation::READ) {
+ return;
+ }
+
+ if (value == 1) {
+ /* This will pull all 16 decoder outputs to high */
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_1);
+ }
+ else if (value == 0) {
+ switch (gpioId) {
+ case(gpioIds::RTD_IC3): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC4): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC5): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC6): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC7): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC8): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC9): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC10): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC11): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC12): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC13): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC14): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC15): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC16): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC17): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ case(gpioIds::RTD_IC18): {
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
+ gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
+ gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
+ break;
+ }
+ default:
+ sif::debug << "tcsBoardDecoderCallback: Invalid gpioid " << gpioId << std::endl;
+ }
+ }
+ else {
+ sif::debug << "tcsBoardDecoderCallback: Invalid value. Must be 0 or 1" << std::endl;
+ }
+}
+
+}
diff --git a/bsp_q7s/gpio/gpioCallbacks.h b/bsp_q7s/gpio/gpioCallbacks.h
new file mode 100644
index 00000000..845127fb
--- /dev/null
+++ b/bsp_q7s/gpio/gpioCallbacks.h
@@ -0,0 +1,23 @@
+#ifndef LINUX_GPIO_GPIOCALLBACKS_H_
+#define LINUX_GPIO_GPIOCALLBACKS_H_
+
+#include
+#include
+
+
+namespace gpioCallbacks {
+
+ /**
+ * @brief This function initializes the GPIOs used to control the SN74LVC138APWR decoders on
+ * the TCS Board.
+ */
+ void initTcsBoardDecoder(GpioIF* gpioComIF);
+
+ /**
+ * @brief This function implements the decoding to multiply gpios by using the two decoder
+ * chips SN74LVC138APWR on the TCS board.
+ */
+ void tcsBoardDecoderCallback(gpioId_t gpioId, gpio::GpioOperation gpioOp, int value, void* args);
+}
+
+#endif /* LINUX_GPIO_GPIOCALLBACKS_H_ */
diff --git a/bsp_linux/main.cpp b/bsp_q7s/main.cpp
similarity index 79%
rename from bsp_linux/main.cpp
rename to bsp_q7s/main.cpp
index 5f6be8db..b087e315 100644
--- a/bsp_linux/main.cpp
+++ b/bsp_q7s/main.cpp
@@ -1,5 +1,4 @@
#include "InitMission.h"
-
#include
#include
@@ -14,15 +13,15 @@
int main(void)
{
std::cout << "-- EIVE OBSW --" << std::endl;
- std::cout << "-- Compiled for Linux " << " --" << std::endl;
+ std::cout << "-- Compiled for Linux (Xiphos Q7S) --" << std::endl;
std::cout << "-- Software version " << SW_NAME << " v" << SW_VERSION << "."
<< SW_SUBVERSION << "." << SW_SUBSUBVERSION << " -- " << std::endl;
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
- InitMission::initMission();
+ initmission::initMission();
for(;;) {
- // suspend main thread by sleeping it.
+ /* Suspend main thread by sleeping it. */
TaskFactory::delayTask(5000);
}
}
diff --git a/bsp_rpi/CMakeLists.txt b/bsp_rpi/CMakeLists.txt
new file mode 100644
index 00000000..da35633d
--- /dev/null
+++ b/bsp_rpi/CMakeLists.txt
@@ -0,0 +1,14 @@
+target_sources(${TARGET_NAME} PUBLIC
+ InitMission.cpp
+ main.cpp
+ ObjectFactory.cpp
+)
+
+add_subdirectory(boardconfig)
+add_subdirectory(boardtest)
+add_subdirectory(gpio)
+
+
+
+
+
diff --git a/bsp_rpi/InitMission.cpp b/bsp_rpi/InitMission.cpp
new file mode 100644
index 00000000..40c38e6c
--- /dev/null
+++ b/bsp_rpi/InitMission.cpp
@@ -0,0 +1,177 @@
+#include "InitMission.h"
+#include "ObjectFactory.h"
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+ServiceInterfaceStream sif::debug("DEBUG");
+ServiceInterfaceStream sif::info("INFO");
+ServiceInterfaceStream sif::warning("WARNING");
+ServiceInterfaceStream sif::error("ERROR");
+
+ObjectManagerIF *objectManager = nullptr;
+
+void initmission::initMission() {
+ sif::info << "Building global objects.." << std::endl;
+ /* Instantiate global object manager and also create all objects */
+ objectManager = new ObjectManager(ObjectFactory::produce);
+ sif::info << "Initializing all objects.." << std::endl;
+ objectManager->initialize();
+
+ /* This function creates and starts all tasks */
+ initTasks();
+}
+
+void initmission::initTasks() {
+ TaskFactory* factory = TaskFactory::instance();
+ 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);
+ 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* udpBridgeTask = factory->createPeriodicTask(
+ "UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
+ result = udpBridgeTask->addComponent(objects::UDP_BRIDGE);
+ if(result != HasReturnvaluesIF::RETURN_OK) {
+ sif::error << "Add component UDP Unix Bridge failed" << std::endl;
+ }
+ PeriodicTaskIF* udpPollingTask = factory->createPeriodicTask(
+ "UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
+ result = udpPollingTask->addComponent(objects::UDP_POLLING_TASK);
+ 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;
+ }
+
+ 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* 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);
+ }
+
+#if RPI_TEST_ACS_BOARD == 1
+ FixedTimeslotTaskIF* acsTask = factory->createFixedTimeslotTask(
+ "ACS_PST", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 2.0, missedDeadlineFunc);
+ result = pst::pollingSequenceAcsTest(acsTask);
+ if(result != HasReturnvaluesIF::RETURN_OK) {
+ sif::warning << "initmission::initTasks: ACS PST initialization failed!" << std::endl;
+ }
+#endif /* RPI_TEST_ACS_BOARD == 1 */
+
+ 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);
+ }
+#endif /* OBSW_ADD_TEST_CODE == 1 */
+#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);
+ }
+#endif /* RPI_ADD_GPIO_TEST == 1 */
+
+ sif::info << "Starting tasks.." << std::endl;
+ tmTcDistributor->startTask();
+ udpBridgeTask->startTask();
+ udpPollingTask->startTask();
+
+ pusVerification->startTask();
+ pusEvents->startTask();
+ pusHighPrio->startTask();
+ pusMedPrio->startTask();
+ pusLowPrio->startTask();
+
+#if OBSW_ADD_TEST_CODE == 1
+ testTask->startTask();
+#endif /* OBSW_ADD_TEST_CODE == 1 */
+
+#if RPI_TEST_ACS_BOARD == 1
+ acsTask->startTask();
+#endif /* RPI_TEST_ACS_BOARD == 1 */
+ sif::info << "Tasks started.." << std::endl;
+}
diff --git a/bsp_linux/InitMission.h b/bsp_rpi/InitMission.h
similarity index 85%
rename from bsp_linux/InitMission.h
rename to bsp_rpi/InitMission.h
index 5ecf9e41..01c72008 100644
--- a/bsp_linux/InitMission.h
+++ b/bsp_rpi/InitMission.h
@@ -1,7 +1,7 @@
#ifndef BSP_LINUX_INITMISSION_H_
#define BSP_LINUX_INITMISSION_H_
-namespace InitMission {
+namespace initmission {
void initMission();
void initTasks();
};
diff --git a/bsp_rpi/ObjectFactory.cpp b/bsp_rpi/ObjectFactory.cpp
new file mode 100644
index 00000000..960abfe6
--- /dev/null
+++ b/bsp_rpi/ObjectFactory.cpp
@@ -0,0 +1,125 @@
+#include "ObjectFactory.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+/* UDP server includes */
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+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::UDP_BRIDGE;
+ // No storage object for now.
+ TmFunnel::storageDestination = objects::NO_OBJECT;
+
+ LocalDataPoolManager::defaultHkDestination = objects::NO_OBJECT;
+
+ VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
+ TmPacketStored::timeStamperId = objects::TIME_STAMPER;
+}
+
+
+
+void ObjectFactory::produce(){
+ Factory::setStaticFrameworkObjectIds();
+ ObjectFactory::produceGenericObjects();
+
+ new UdpTmTcBridge(objects::UDP_BRIDGE,
+ objects::CCSDS_PACKET_DISTRIBUTOR,
+ objects::TM_STORE, objects::TC_STORE);
+ new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
+
+ GpioIF* gpioIF = new LinuxLibgpioIF(objects::GPIO_IF);
+
+#if RPI_ADD_SPI_TEST == 1
+ new SpiTestClass(objects::SPI_TEST, gpioIF);
+#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);
+#endif /* RPI_LOOPBACK_TEST_GPIO == 1 */
+
+ new SpiComIF(objects::SPI_COM_IF, gpioIF);
+
+#if RPI_TEST_ACS_BOARD == 1
+
+ GpioCookie* gpioCookieAcsBoard = new GpioCookie();
+ gpio::createRpiGpioConfig(gpioCookieAcsBoard, gpioIds::MGM_0_LIS3_CS, gpio::MGM_0_BCM_PIN,
+ "MGM_0_LIS3", gpio::Direction::OUT, 1);
+ gpio::createRpiGpioConfig(gpioCookieAcsBoard, gpioIds::MGM_1_RM3100_CS, gpio::MGM_1_BCM_PIN,
+ "MGM_1_RM3100", gpio::Direction::OUT, 1);
+ gpio::createRpiGpioConfig(gpioCookieAcsBoard, gpioIds::MGM_2_LIS3_CS, gpio::MGM_2_BCM_PIN,
+ "MGM_2_LIS3", gpio::Direction::OUT, 1);
+ gpio::createRpiGpioConfig(gpioCookieAcsBoard, gpioIds::MGM_3_RM3100_CS, gpio::MGM_3_BCM_PIN,
+ "MGM_3_RM3100", gpio::Direction::OUT, 1);
+ gpio::createRpiGpioConfig(gpioCookieAcsBoard, gpioIds::GYRO_0_ADIS_CS, gpio::GYRO_0_BCM_PIN,
+ "GYRO_0_ADIS", gpio::Direction::OUT, 1);
+ gpio::createRpiGpioConfig(gpioCookieAcsBoard, gpioIds::GYRO_1_L3G_CS, gpio::GYRO_1_BCM_PIN,
+ "GYRO_1_L3G", gpio::Direction::OUT, 1);
+ gpio::createRpiGpioConfig(gpioCookieAcsBoard, gpioIds::GYRO_2_L3G_CS, gpio::GYRO_2_BCM_PIN,
+ "GYRO_2_L3G", gpio::Direction::OUT, 1);
+ gpioIF->addGpios(gpioCookieAcsBoard);
+
+ std::string spiDev = "/dev/spidev0.0";
+ SpiCookie* 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 MGMHandlerLIS3MDL(objects::MGM_0_LIS3_HANDLER,
+ objects::SPI_COM_IF, spiCookie);
+ mgmLis3Handler->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 MGMHandlerRM3100(objects::MGM_1_RM3100_HANDLER,
+ objects::SPI_COM_IF, spiCookie);
+ mgmRm3100Handler->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);
+ gyroL3gHandler->setStartUpImmediately();
+
+#endif /* RPI_TEST_ACS_BOARD == 1 */
+}
diff --git a/hosted/ObjectFactory.h b/bsp_rpi/ObjectFactory.h
similarity index 100%
rename from hosted/ObjectFactory.h
rename to bsp_rpi/ObjectFactory.h
diff --git a/bsp_rpi/boardconfig/CMakeLists.txt b/bsp_rpi/boardconfig/CMakeLists.txt
new file mode 100644
index 00000000..c32b326d
--- /dev/null
+++ b/bsp_rpi/boardconfig/CMakeLists.txt
@@ -0,0 +1,10 @@
+target_sources(${TARGET_NAME} PRIVATE
+ print.c
+)
+
+target_include_directories(${TARGET_NAME} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+
+
diff --git a/bsp_rpi/boardconfig/etl_profile.h b/bsp_rpi/boardconfig/etl_profile.h
new file mode 100644
index 00000000..c35ffb46
--- /dev/null
+++ b/bsp_rpi/boardconfig/etl_profile.h
@@ -0,0 +1,38 @@
+///\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
diff --git a/bsp_rpi/boardconfig/gcov.h b/bsp_rpi/boardconfig/gcov.h
new file mode 100644
index 00000000..491d24c6
--- /dev/null
+++ b/bsp_rpi/boardconfig/gcov.h
@@ -0,0 +1,14 @@
+#ifndef LINUX_GCOV_H_
+#define LINUX_GCOV_H_
+#include
+
+#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_ */
diff --git a/bsp_rpi/boardconfig/print.c b/bsp_rpi/boardconfig/print.c
new file mode 100644
index 00000000..c501e0b7
--- /dev/null
+++ b/bsp_rpi/boardconfig/print.c
@@ -0,0 +1,14 @@
+#include
+#include
+
+void printChar(const char* character, bool errStream) {
+ if(errStream) {
+ putc(*character, stderr);
+ return;
+ }
+ putc(*character, stdout);
+}
+
+
+
+
diff --git a/hosted/boardconfig/print.h b/bsp_rpi/boardconfig/print.h
similarity index 100%
rename from hosted/boardconfig/print.h
rename to bsp_rpi/boardconfig/print.h
diff --git a/bsp_rpi/boardconfig/rpi_config.h b/bsp_rpi/boardconfig/rpi_config.h
new file mode 100644
index 00000000..a9f4fd9f
--- /dev/null
+++ b/bsp_rpi/boardconfig/rpi_config.h
@@ -0,0 +1,24 @@
+#ifndef BSP_RPI_BOARDCONFIG_RPI_CONFIG_H_
+#define BSP_RPI_BOARDCONFIG_RPI_CONFIG_H_
+
+#include
+
+#define RPI_ADD_GPIO_TEST 0
+#define RPI_LOOPBACK_TEST_GPIO 0
+
+/* Only one of those 2 should be enabled! */
+#define RPI_ADD_SPI_TEST 0
+#define RPI_TEST_ACS_BOARD 0
+
+/* Adapt these values accordingly */
+namespace gpio {
+static constexpr uint8_t MGM_0_BCM_PIN = 0;
+static constexpr uint8_t MGM_1_BCM_PIN = 1;
+static constexpr uint8_t MGM_2_BCM_PIN = 17;
+static constexpr uint8_t MGM_3_BCM_PIN = 27;
+static constexpr uint8_t GYRO_0_BCM_PIN = 5;
+static constexpr uint8_t GYRO_1_BCM_PIN = 6;
+static constexpr uint8_t GYRO_2_BCM_PIN = 4;
+}
+
+#endif /* BSP_RPI_BOARDCONFIG_RPI_CONFIG_H_ */
diff --git a/bsp_rpi/boardtest/CMakeLists.txt b/bsp_rpi/boardtest/CMakeLists.txt
new file mode 100644
index 00000000..0599b73f
--- /dev/null
+++ b/bsp_rpi/boardtest/CMakeLists.txt
@@ -0,0 +1,6 @@
+target_sources(${TARGET_NAME} PRIVATE
+)
+
+
+
+
diff --git a/bsp_rpi/gpio/CMakeLists.txt b/bsp_rpi/gpio/CMakeLists.txt
new file mode 100644
index 00000000..b816684d
--- /dev/null
+++ b/bsp_rpi/gpio/CMakeLists.txt
@@ -0,0 +1,8 @@
+target_sources(${TARGET_NAME} PUBLIC
+)
+
+
+
+
+
+
diff --git a/bsp_rpi/main.cpp b/bsp_rpi/main.cpp
new file mode 100644
index 00000000..8eea768c
--- /dev/null
+++ b/bsp_rpi/main.cpp
@@ -0,0 +1,28 @@
+#include "InitMission.h"
+#include
+
+#include
+
+#include
+
+/**
+ * @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 (Raspberry Pi) --" << std::endl;
+ std::cout << "-- Software version " << SW_NAME << " v" << SW_VERSION << "."
+ << SW_SUBVERSION << "." << SW_SUBSUBVERSION << " -- " << std::endl;
+ std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
+
+ initmission::initMission();
+
+ for(;;) {
+ /* Suspend main thread by sleeping it. */
+ TaskFactory::delayTask(5000);
+ }
+}
+
+
diff --git a/cmake/BuildType.cmake b/cmake/BuildType.cmake
new file mode 100644
index 00000000..e078e5c7
--- /dev/null
+++ b/cmake/BuildType.cmake
@@ -0,0 +1,45 @@
+function(set_build_type)
+
+message(STATUS "Used build generator: ${CMAKE_GENERATOR}")
+
+# Set a default build type if none was specified
+set(DEFAULT_BUILD_TYPE "RelWithDebInfo")
+if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
+ set(DEFAULT_BUILD_TYPE "Debug")
+endif()
+
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+ message(STATUS
+ "Setting build type to '${DEFAULT_BUILD_TYPE}' as none was specified."
+ )
+ set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE
+ STRING "Choose the type of build." FORCE
+ )
+ # Set the possible values of build type for cmake-gui
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+ "Debug" "Release" "MinSizeRel" "RelWithDebInfo"
+ )
+endif()
+
+if(${CMAKE_BUILD_TYPE} MATCHES "Debug")
+ message(STATUS
+ "Building Debug application with flags: ${CMAKE_C_FLAGS_DEBUG}"
+ )
+elseif(${CMAKE_BUILD_TYPE} MATCHES "RelWithDebInfo")
+ message(STATUS
+ "Building Release (Debug) application with "
+ "flags: ${CMAKE_C_FLAGS_RELWITHDEBINFO}"
+ )
+elseif(${CMAKE_BUILD_TYPE} MATCHES "MinSizeRel")
+ message(STATUS
+ "Building Release (Size) application with "
+ "flags: ${CMAKE_C_FLAGS_MINSIZEREL}"
+ )
+else()
+ message(STATUS
+ "Building Release (Speed) application with "
+ "flags: ${CMAKE_C_FLAGS_RELEASE}"
+ )
+endif()
+
+endfunction()
diff --git a/cmake/HardwareOsPostConfig.cmake b/cmake/HardwareOsPostConfig.cmake
new file mode 100644
index 00000000..73a8d8b1
--- /dev/null
+++ b/cmake/HardwareOsPostConfig.cmake
@@ -0,0 +1,62 @@
+function(post_source_hw_os_config)
+
+if(LINK_LWIP)
+ message(STATUS "Linking against ${LIB_LWIP_NAME} lwIP library")
+ if(LIB_LWIP_NAME)
+ target_link_libraries(${TARGET_NAME} PUBLIC
+ ${LIB_LWIP_NAME}
+ )
+ else()
+ message(WARNING "lwIP library name not set!")
+ endif()
+endif()
+
+if(LINK_HAL)
+ message(STATUS "Linking against ${LIB_HAL_NAME} HAL library")
+ if(LIB_HAL_NAME)
+ target_link_libraries(${TARGET_NAME} PUBLIC
+ ${LIB_HAL_NAME}
+ )
+ else()
+ message(WARNING "HAL library name not set!")
+ endif()
+endif()
+
+if(LINKER_SCRIPT)
+ target_link_options(${TARGET_NAME} PRIVATE
+ -T${LINKER_SCRIPT}
+ )
+endif()
+
+set(C_FLAGS "" CACHE INTERNAL "C flags")
+
+set(C_DEFS ""
+ CACHE INTERNAL
+ "C Defines"
+)
+
+set(CXX_FLAGS ${C_FLAGS})
+set(CXX_DEFS ${C_DEFS})
+
+if(CMAKE_VERBOSE)
+ message(STATUS "C Flags: ${C_FLAGS}")
+ message(STATUS "CXX Flags: ${CXX_FLAGS}")
+ message(STATUS "C Defs: ${C_DEFS}")
+ message(STATUS "CXX Defs: ${CXX_DEFS}")
+endif()
+
+# Generator expression. Can be used to set different C, CXX and ASM flags.
+target_compile_options(${TARGET_NAME} PRIVATE
+ $<$:${C_DEFS} ${C_FLAGS}>
+ $<$:${CXX_DEFS} ${CXX_FLAGS}>
+ $<$:${ASM_FLAGS}>
+)
+
+add_custom_command(
+ TARGET ${TARGET_NAME}
+ POST_BUILD
+ COMMAND ${CMAKE_OBJCOPY} -O binary ${TARGET_NAME} ${TARGET_NAME}.bin
+ COMMENT "Generating binary file ${CMAKE_PROJECT_NAME}.bin.."
+)
+
+endfunction()
\ No newline at end of file
diff --git a/cmake/HardwareOsPreConfig.cmake b/cmake/HardwareOsPreConfig.cmake
new file mode 100644
index 00000000..ab5c16fd
--- /dev/null
+++ b/cmake/HardwareOsPreConfig.cmake
@@ -0,0 +1,70 @@
+function(pre_source_hw_os_config)
+
+# FreeRTOS
+if(${OS_FSFW} MATCHES freertos)
+ message(FATAL_ERROR "No FreeRTOS support implemented yet.")
+# RTEMS
+elseif(${OS_FSFW} STREQUAL rtems)
+ add_definitions(-DRTEMS)
+ message(FATAL_ERROR "No RTEMS support implemented yet.")
+elseif(${OS_FSFW} STREQUAL linux)
+ add_definitions(-DUNIX -DLINUX)
+ find_package(Threads REQUIRED)
+# Hosted
+else()
+ set(BSP_PATH "bsp_hosted")
+ if(WIN32)
+ add_definitions(-DWIN32)
+ elseif(UNIX)
+ find_package(Threads REQUIRED)
+ add_definitions(-DUNIX -DLINUX)
+ endif()
+endif()
+
+# Cross-compile information
+if(CMAKE_CROSSCOMPILING)
+ # set(CMAKE_VERBOSE TRUE)
+
+ message(STATUS "Cross-compiling for ${TGT_BSP} target")
+ message(STATUS "Cross-compile gcc: ${CMAKE_C_COMPILER}")
+ message(STATUS "Cross-compile g++: ${CMAKE_CXX_COMPILER}")
+
+ if(CMAKE_VERBOSE)
+ message(STATUS "Cross-compile linker: ${CMAKE_LINKER}")
+ message(STATUS "Cross-compile size utility: ${CMAKE_SIZE}")
+ message(STATUS "Cross-compile objcopy utility: ${CMAKE_OBJCOPY}")
+ message(STATUS "Cross-compile ranlib utility: ${CMAKE_RANLIB}")
+ message(STATUS "Cross-compile ar utility: ${CMAKE_AR}")
+ message(STATUS "Cross-compile nm utility: ${CMAKE_NM}")
+ message(STATUS "Cross-compile strip utility: ${CMAKE_STRIP}")
+ message(STATUS
+ "Cross-compile assembler: ${CMAKE_ASM_COMPILER} "
+ "-x assembler-with-cpp"
+ )
+ message(STATUS "ABI flags: ${ABI_FLAGS}")
+ message(STATUS "Custom linker script: ${LINKER_SCRIPT}")
+ endif()
+
+ set_property(CACHE TGT_BSP
+ PROPERTY STRINGS
+ "arm/q7s" "arm/raspberrypi"
+ )
+endif()
+
+
+if(TGT_BSP)
+ if (${TGT_BSP} MATCHES "arm/raspberrypi")
+ set(BSP_PATH "bsp_rpi")
+ elseif(${TGT_BSP} MATCHES "arm/q7s")
+ set(BSP_PATH "bsp_q7s")
+ else()
+ message(WARNING "CMake not configured for this target!")
+ message(FATAL_ERROR "Target: ${TGT_BSP}!")
+ endif()
+else()
+ set(BSP_PATH "bsp_hosted")
+endif()
+
+set(BSP_PATH ${BSP_PATH} PARENT_SCOPE)
+
+endfunction()
\ No newline at end of file
diff --git a/cmake/PreProjectConfig.cmake b/cmake/PreProjectConfig.cmake
new file mode 100644
index 00000000..f54da048
--- /dev/null
+++ b/cmake/PreProjectConfig.cmake
@@ -0,0 +1,59 @@
+function(pre_project_config)
+
+# Basic input sanitization
+if(DEFINED TGT_BSP)
+ if(${TGT_BSP} MATCHES "arm/raspberrypi" AND NOT ${OS_FSFW} MATCHES linux)
+ message(STATUS "FSFW OSAL invalid for specified target BSP ${TGT_BSP}!")
+ message(STATUS "Setting valid OS_FSFW: linux")
+ set(OS_FSFW "linux")
+ endif()
+endif()
+
+# Disable compiler checks for cross-compiling.
+if(${OS_FSFW} STREQUAL linux AND TGT_BSP)
+
+ if(${TGT_BSP} MATCHES "arm/q7s")
+ set(CMAKE_TOOLCHAIN_FILE
+ "${CMAKE_SCRIPT_PATH}/Q7SCrossCompileConfig.cmake"
+ PARENT_SCOPE
+ )
+ elseif (${TGT_BSP} MATCHES "arm/raspberrypi")
+ if(NOT DEFINED ENV{RASPBIAN_ROOTFS})
+ if(NOT DEFINED RASPBIAN_ROOTFS)
+ message(WARNING "No RASPBIAN_ROOTFS environmental or CMake variable set!")
+ set(ENV{RASPBIAN_ROOTFS} "$ENV{HOME}/raspberrypi/rootfs")
+ else()
+ set(ENV{RASPBIAN_ROOTFS} "${RASPBIAN_ROOTFS}")
+ endif()
+ else()
+ message(STATUS
+ "RASPBIAN_ROOTFS from environmental variables used: $ENV{RASPBIAN_ROOTFS}"
+ )
+ endif()
+
+ if(NOT DEFINED ENV{RASPBERRY_VERSION})
+ if(NOT RASPBERRY_VERSION)
+ message(STATUS "No RASPBERRY_VERSION specified, setting to 4")
+ set(RASPBERRY_VERSION "4" CACHE STRING "Raspberry Pi version")
+ else()
+ message(STATUS "Setting RASPBERRY_VERSION to ${RASPBERRY_VERSION}")
+ set(RASPBERRY_VERSION ${RASPBERRY_VERSION} CACHE STRING "Raspberry Pi version")
+ set(ENV{RASPBERRY_VERSION} ${RASPBERRY_VERSION})
+ endif()
+ else()
+ message(STATUS
+ "RASPBERRY_VERSION from environmental variables used: "
+ "$ENV{RASPBERRY_VERSION}"
+ )
+ endif()
+
+ set(CMAKE_TOOLCHAIN_FILE
+ "${CMAKE_SCRIPT_PATH}/RPiCrossCompileConfig.cmake"
+ PARENT_SCOPE
+ )
+ else()
+ message(WARNING "Target BSP (TGT_BSP) ${TGT_BSP} unknown!")
+ endif()
+endif()
+
+endfunction()
\ No newline at end of file
diff --git a/cmake/Q7SCrossCompileConfig.cmake b/cmake/Q7SCrossCompileConfig.cmake
new file mode 100644
index 00000000..2c5bd4e9
--- /dev/null
+++ b/cmake/Q7SCrossCompileConfig.cmake
@@ -0,0 +1,88 @@
+# CROSS_COMPILE also needs to be set accordingly or passed to the CMake command
+
+if(NOT DEFINED ENV{Q7S_SYSROOT})
+# message(FATAL_ERROR
+# "Define the Q7S_ROOTFS variable to "
+# "point to the raspbian rootfs."
+# )
+else()
+ set(SYSROOT_PATH "$ENV{Q7S_SYSROOT}")
+endif()
+
+if(NOT DEFINED ENV{CROSS_COMPILE})
+ set(CROSS_COMPILE "arm-linux-gnueabihf")
+ message(STATUS
+ "No CROSS_COMPILE environmental variable set, using default ARM linux "
+ "cross compiler name ${CROSS_COMPILE}"
+ )
+else()
+ set(CROSS_COMPILE "$ENV{CROSS_COMPILE}")
+ message(STATUS
+ "Using environmental variable CROSS_COMPILE as cross-compiler: "
+ "$ENV{CROSS_COMPILE}"
+ )
+endif()
+
+message(STATUS "Using sysroot path: ${SYSROOT_PATH}")
+
+set(CROSS_COMPILE_CC "${CROSS_COMPILE}-gcc")
+set(CROSS_COMPILE_CXX "${CROSS_COMPILE}-g++")
+set(CROSS_COMPILE_LD "${CROSS_COMPILE}-ld")
+set(CROSS_COMPILE_AR "${CROSS_COMPILE}-ar")
+set(CROSS_COMPILE_RANLIB "${CROSS_COMPILE}-ranlib")
+set(CROSS_COMPILE_STRIP "${CROSS_COMPILE}-strip")
+set(CROSS_COMPILE_NM "${CROSS_COMPILE}-nm")
+set(CROSS_COMPILE_OBJCOPY "${CROSS_COMPILE}-objcopy")
+set(CROSS_COMPILE_SIZE "${CROSS_COMPILE}-size")
+
+# At the very least, cross compile gcc and g++ have to be set!
+find_program (CROSS_COMPILE_CC_FOUND ${CROSS_COMPILE_CC} REQUIRED)
+find_program (CROSS_COMPILE_CXX_FOUND ${CROSS_COMPILE_CXX} REQUIRED)
+
+set(CMAKE_CROSSCOMPILING TRUE)
+set(CMAKE_SYSROOT "${SYSROOT_PATH}")
+
+# Define name of the target system
+set(CMAKE_SYSTEM_NAME "Linux")
+set(CMAKE_SYSTEM_PROCESSOR "armv7")
+
+# Define the compiler
+set(CMAKE_C_COMPILER ${CROSS_COMPILE_CC})
+set(CMAKE_CXX_COMPILER ${CROSS_COMPILE_CXX})
+
+# List of library dirs where LD has to look. Pass them directly through gcc.
+set(LIB_DIRS
+ "${SYSROOT_PATH}/usr/include"
+ "${SYSROOT_PATH}/usr/include/linux"
+ "${SYSROOT_PATH}/usr/lib"
+ "${SYSROOT_PATH}/lib"
+ "${SYSROOT_PATH}"
+ "${SYSROOT_PATH}/usr/lib/arm-xiphos-linux-gnueabi"
+)
+# You can additionally check the linker paths if you add the
+# flags ' -Xlinker --verbose'
+set(COMMON_FLAGS "-I${SYSROOT_PATH}/usr/lib")
+foreach(LIB ${LIB_DIRS})
+ set(COMMON_FLAGS "${COMMON_FLAGS} -L${LIB} -Wl,-rpath-link,${LIB}")
+endforeach()
+
+set(CMAKE_PREFIX_PATH
+ "${CMAKE_PREFIX_PATH}"
+ # "${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}"
+)
+
+set(CMAKE_C_FLAGS
+ "-mcpu=cortex-a9 -mfpu=neon-vfpv3 -mfloat-abi=hard ${COMMON_FLAGS} -lgpiod"
+ CACHE STRING "C flags for Q7S"
+)
+set(CMAKE_CXX_FLAGS
+ "${CMAKE_C_FLAGS}"
+ CACHE STRING "CPP flags for Q7S"
+)
+
+# search for programs in the build host directories
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+# for libraries and headers in the target directories
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
diff --git a/cmake/RPiCrossCompileConfig.cmake b/cmake/RPiCrossCompileConfig.cmake
new file mode 100644
index 00000000..e1b4cce3
--- /dev/null
+++ b/cmake/RPiCrossCompileConfig.cmake
@@ -0,0 +1,146 @@
+# Based on https://github.com/Pro/raspi-toolchain but rewritten completely.
+
+# Adapted for the FSFW Example
+if(NOT $ENV{RASPBERRY_VERSION})
+ message(STATUS "Raspberry Pi version not specified, setting version 4!")
+ set(RASPBERRY_VERSION 4)
+else()
+ set(RASPBERRY_VERSION $ENV{RASPBERRY_VERSION})
+endif()
+
+
+# RASPBIAN_ROOTFS should point to the local directory which contains all the
+# libraries and includes from the target raspi.
+# The following command can be used to do this, replace and the
+# local accordingly:
+# rsync -vR --progress -rl --delete-after --safe-links pi@:/{lib,usr,opt/vc/lib}
+# RASPBIAN_ROOTFS needs to be passed to the CMake command or defined in the
+# application CMakeLists.txt before loading the toolchain file.
+
+# CROSS_COMPILE also needs to be set accordingly or passed to the CMake command
+
+if(NOT DEFINED ENV{RASPBIAN_ROOTFS})
+ message(FATAL_ERROR
+ "Define the RASPBIAN_ROOTFS variable to "
+ "point to the raspbian rootfs."
+ )
+else()
+ set(SYSROOT_PATH "$ENV{RASPBIAN_ROOTFS}")
+endif()
+
+if(NOT DEFINED ENV{CROSS_COMPILE})
+ set(CROSS_COMPILE "arm-linux-gnueabihf")
+ message(STATUS
+ "No CROSS_COMPILE environmental variable set, using default ARM linux "
+ "cross compiler name ${CROSS_COMPILE}"
+ )
+else()
+ set(CROSS_COMPILE "$ENV{CROSS_COMPILE}")
+ message(STATUS
+ "Using environmental variable CROSS_COMPILE as cross-compiler: "
+ "$ENV{CROSS_COMPILE}"
+ )
+endif()
+
+message(STATUS "Using sysroot path: ${SYSROOT_PATH}")
+
+set(CROSS_COMPILE_CC "${CROSS_COMPILE}-gcc")
+set(CROSS_COMPILE_CXX "${CROSS_COMPILE}-g++")
+set(CROSS_COMPILE_LD "${CROSS_COMPILE}-ld")
+set(CROSS_COMPILE_AR "${CROSS_COMPILE}-ar")
+set(CROSS_COMPILE_RANLIB "${CROSS_COMPILE}-ranlib")
+set(CROSS_COMPILE_STRIP "${CROSS_COMPILE}-strip")
+set(CROSS_COMPILE_NM "${CROSS_COMPILE}-nm")
+set(CROSS_COMPILE_OBJCOPY "${CROSS_COMPILE}-objcopy")
+set(CROSS_COMPILE_SIZE "${CROSS_COMPILE}-size")
+
+# At the very least, cross compile gcc and g++ have to be set!
+find_program (CROSS_COMPILE_CC_FOUND ${CROSS_COMPILE_CC} REQUIRED)
+find_program (CROSS_COMPILE_CXX_FOUND ${CROSS_COMPILE_CXX} REQUIRED)
+
+set(CMAKE_CROSSCOMPILING TRUE)
+set(CMAKE_SYSROOT "${SYSROOT_PATH}")
+
+# Define name of the target system
+set(CMAKE_SYSTEM_NAME "Linux")
+if(RASPBERRY_VERSION VERSION_GREATER 1)
+ set(CMAKE_SYSTEM_PROCESSOR "armv7")
+else()
+ set(CMAKE_SYSTEM_PROCESSOR "arm")
+endif()
+
+# Define the compiler
+set(CMAKE_C_COMPILER ${CROSS_COMPILE_CC})
+set(CMAKE_CXX_COMPILER ${CROSS_COMPILE_CXX})
+
+# List of library dirs where LD has to look. Pass them directly through gcc.
+# LD_LIBRARY_PATH is not evaluated by arm-*-ld
+set(LIB_DIRS
+ "/opt/cross-pi-gcc/arm-linux-gnueabihf/lib"
+ "/opt/cross-pi-gcc/lib"
+ "${SYSROOT_PATH}/opt/vc/lib"
+ "${SYSROOT_PATH}/lib/${CROSS_COMPILE}"
+ "${SYSROOT_PATH}/usr/local/lib"
+ "${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}"
+ "${SYSROOT_PATH}/usr/lib"
+ "${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}/blas"
+ "${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}/lapack"
+)
+# You can additionally check the linker paths if you add the
+# flags ' -Xlinker --verbose'
+set(COMMON_FLAGS "-I${SYSROOT_PATH}/usr/include")
+foreach(LIB ${LIB_DIRS})
+ set(COMMON_FLAGS "${COMMON_FLAGS} -L${LIB} -Wl,-rpath-link,${LIB}")
+endforeach()
+
+set(CMAKE_PREFIX_PATH
+ "${CMAKE_PREFIX_PATH}"
+ "${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}"
+)
+
+if(RASPBERRY_VERSION VERSION_GREATER 3)
+ set(CMAKE_C_FLAGS
+ "-mcpu=cortex-a72 -mfpu=neon-vfpv4 -mfloat-abi=hard ${COMMON_FLAGS}"
+ CACHE STRING "CPP flags for Raspberry PI 4"
+ )
+ set(CMAKE_CXX_FLAGS
+ "${CMAKE_C_FLAGS}"
+ CACHE STRING "C flags for Raspberry PI 4"
+ )
+elseif(RASPBERRY_VERSION VERSION_GREATER 2)
+ set(CMAKE_C_FLAGS
+ "-mcpu=cortex-a53 -mfpu=neon-vfpv4 -mfloat-abi=hard ${COMMON_FLAGS}"
+ CACHE STRING "C flags for Raspberry PI 3"
+ )
+ set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}"
+ CACHE STRING "CPP flags for Raspberry PI 3"
+ )
+elseif(RASPBERRY_VERSION VERSION_GREATER 1)
+ set(CMAKE_C_FLAGS
+ "-mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard ${COMMON_FLAGS}"
+ CACHE STRING "C flags for Raspberry PI 2"
+ )
+ set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}"
+ CACHE STRING "CPP flags for Raspberry PI 2"
+ )
+else()
+ set(CMAKE_C_FLAGS
+ "-mcpu=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard ${COMMON_FLAGS}"
+ CACHE STRING "C flags for Raspberry PI 1 B+ Zero"
+ )
+ set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}"
+ CACHE STRING "CPP flags for Raspberry PI 1 B+ Zero"
+ )
+endif()
+
+set(CMAKE_FIND_ROOT_PATH
+ "${CMAKE_INSTALL_PREFIX};${CMAKE_PREFIX_PATH};${CMAKE_SYSROOT}"
+)
+
+
+# search for programs in the build host directories
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+# for libraries and headers in the target directories
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
diff --git a/cmake/scripts/.idea/inspectionProfiles/profiles_settings.xml b/cmake/scripts/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 00000000..105ce2da
--- /dev/null
+++ b/cmake/scripts/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cmake/scripts/.idea/misc.xml b/cmake/scripts/.idea/misc.xml
new file mode 100644
index 00000000..d56657ad
--- /dev/null
+++ b/cmake/scripts/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/cmake/scripts/.idea/modules.xml b/cmake/scripts/.idea/modules.xml
new file mode 100644
index 00000000..bb83e262
--- /dev/null
+++ b/cmake/scripts/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cmake/scripts/.idea/scripts.iml b/cmake/scripts/.idea/scripts.iml
new file mode 100644
index 00000000..d0876a78
--- /dev/null
+++ b/cmake/scripts/.idea/scripts.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cmake/scripts/.idea/vcs.xml b/cmake/scripts/.idea/vcs.xml
new file mode 100644
index 00000000..c2365ab1
--- /dev/null
+++ b/cmake/scripts/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cmake/scripts/.idea/workspace.xml b/cmake/scripts/.idea/workspace.xml
new file mode 100644
index 00000000..70a189f3
--- /dev/null
+++ b/cmake/scripts/.idea/workspace.xml
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1609084345199
+
+
+ 1609084345199
+
+
+
+
+
+
+
+
+