Compare commits

...

No commits in common. "v1.2.0" and "main" have entirely different histories.
v1.2.0 ... main

1072 changed files with 110487 additions and 39352 deletions

8
.clang-format Normal file
View File

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

27
.gitignore vendored
View File

@ -1,19 +1,28 @@
/build*
/cmake-build*
Debug
Debug*
Release
Release*
# Eclipse
.settings
.metadata
.project
.cproject
__pycache__
.idea
!misc/eclipse/**/.cproject
!misc/eclipse/**/.project
#vscode
/.vscode
# IntelliJ
/.idea/*
# Python
__pycache__
# CLion
!/.idea/cmake.xml
generators/*.db
# Clangd LSP
/compile_commands.json
/.cache

23
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "etl"]
path = thirdparty/etl
url = https://github.com/ETLCPP/etl.git
[submodule "arduino"]
path = arduino
url = https://egit.irs.uni-stuttgart.de/eive/eive_arduino_interface.git
@ -9,13 +6,19 @@
url = https://egit.irs.uni-stuttgart.de/eive/fsfw.git
[submodule "tmtc"]
path = tmtc
url = https://egit.irs.uni-stuttgart.de/eive/eive_tmtc.git
url = https://egit.irs.uni-stuttgart.de/eive/eive-tmtc.git
[submodule "thirdparty/lwgps"]
path = thirdparty/lwgps
url = https://github.com/rmspacefish/lwgps.git
[submodule "fsfw_hal"]
path = fsfw_hal
url = https://egit.irs.uni-stuttgart.de/fsfw/fsfw-hal.git
[submodule "generators/fsfwgen"]
path = generators/fsfwgen
url = https://egit.irs.uni-stuttgart.de/fsfw/fsfw-generators.git
[submodule "thirdparty/json"]
path = thirdparty/json
url = https://github.com/nlohmann/json.git
[submodule "thirdparty/rapidcsv"]
path = thirdparty/rapidcsv
url = https://github.com/d99kris/rapidcsv.git
[submodule "thirdparty/gomspace-sw"]
path = thirdparty/gomspace-sw
url = https://egit.irs.uni-stuttgart.de/eive/gomspace-sw.git
[submodule "thirdparty/sagittactl"]
path = thirdparty/sagittactl
url = https://egit.irs.uni-stuttgart.de/eive/sagittactl.git

16
.idea/cmake.xml Normal file
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeSharedSettings">
<configurations>
<configuration PROFILE_NAME="Debug Q7S" ENABLED="true" CONFIG_NAME="Debug" TOOLCHAIN_NAME="Default" GENERATION_OPTIONS="-DTGT_BSP=&quot;arm/q7s&quot;" NO_GENERATOR="true">
<ADDITIONAL_GENERATION_ENVIRONMENT>
<envs>
<env name="ZYNQ_7020_ROOTFS" value="/opt/xiphos/sdk/ark/sysroots/cortexa9hf-neon-xiphos-linux-gnueabi" />
<env name="CROSS_COMPILE" value="/opt/q7s-gcc/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf" />
</envs>
</ADDITIONAL_GENERATION_ENVIRONMENT>
</configuration>
<configuration PROFILE_NAME="Debug" ENABLED="true" CONFIG_NAME="Debug" NO_GENERATOR="true" />
</configurations>
</component>
</project>

10
.run/Q7S FM.run.xml Normal file
View File

@ -0,0 +1,10 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Q7S FM" type="com.jetbrains.cidr.remote.gdbserver.type" factoryName="com.jetbrains.cidr.remote.gdbserver.factory" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="eive-obsw" TARGET_NAME="eive-obsw" CONFIG_NAME="Debug" version="1" RUN_TARGET_PROJECT_NAME="eive-obsw" RUN_TARGET_NAME="eive-obsw">
<custom-gdb-server version="1" gdb-connect="localhost:1234" executable="" warmup-ms="0" download-type="NONE" sshConfigName="Q7S FM" uploadFile="/tmp/eive-obsw" defaultGdbServerArgs=":1234 /tmp/eive-obsw">
<debugger kind="GDB" isBundled="true" />
</custom-gdb-server>
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
</component>

2299
CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,250 +1,581 @@
################################################################################
# ##############################################################################
# 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(OBSW_VERSION_MAJOR 8)
set(OBSW_VERSION_MINOR 0)
set(OBSW_VERSION_REVISION 0)
# set(CMAKE_VERBOSE TRUE)
set(CMAKE_SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
option(
EIVE_HARDCODED_TOOLCHAIN_FILE
"\
For Linux Board Target BSPs, a default toolchain file will be set. Should be set to OFF \
if a different toolchain file is set externally"
ON)
option(ADD_ETL_LIB "Add ETL library" ON)
if(NOT OS_FSFW)
set(OS_FSFW host CACHE STRING "OS for the FSFW.")
if(NOT FSFW_OSAL)
set(FSFW_OSAL
linux
CACHE STRING "OS for the FSFW.")
endif()
if(TGT_BSP MATCHES "arm/raspberrypi" OR TGT_BSP MATCHES "arm/beagleboneblack")
if(TGT_BSP)
if(TGT_BSP MATCHES "arm/q7s"
OR TGT_BSP MATCHES "arm/raspberrypi"
OR TGT_BSP MATCHES "arm/beagleboneblack")
option(LINUX_CROSS_COMPILE ON)
endif()
if(TGT_BSP MATCHES "arm/raspberrypi" OR TGT_BSP MATCHES "arm/beagleboneblack")
option(EIVE_BUILD_GPSD_GPS_HANDLER "Build GPSD dependent GPS Handler" OFF)
elseif(TGT_BSP MATCHES "arm/q7s")
option(EIVE_Q7S_EM "Build configuration for the EM" OFF)
option(EIVE_BUILD_GPSD_GPS_HANDLER "Build GPSD dependent GPS Handler" ON)
endif()
option(EIVE_CREATE_UNIQUE_OBSW_BIN "Append username to generated binary name"
ON)
else()
option(EIVE_CREATE_UNIQUE_OBSW_BIN "Append username to generated binary name"
OFF)
endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# Perform steps like loading toolchain files where applicable.
include(${CMAKE_SCRIPT_PATH}/PreProjectConfig.cmake)
include(PreProjectConfig)
pre_project_config()
# Project Name
project(eive_obsw ASM C CXX)
################################################################################
# Pre-Sources preparation
################################################################################
project(eive-obsw)
# Specify the C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
include(EiveHelpers)
option(EIVE_ADD_ETL_LIB "Add ETL library" ON)
option(EIVE_ADD_JSON_LIB "Add JSON library" ON)
set(OBSW_MAX_SCHEDULED_TCS 4000)
if(EIVE_Q7S_EM)
set(OBSW_Q7S_EM
1
CACHE STRING "Q7S EM configuration")
set(INIT_VAL 0)
set(OBSW_STAR_TRACKER_GROUND_CONFIG 1)
else()
set(OBSW_Q7S_EM
0
CACHE STRING "Q7S EM configuration")
set(INIT_VAL 1)
set(OBSW_STAR_TRACKER_GROUND_CONFIG 0)
endif()
set(OBSW_ADD_TMTC_TCP_SERVER
${OBSW_Q7S_EM}
CACHE STRING "Add TCP TMTC Server")
set(OBSW_ADD_TMTC_UDP_SERVER
0
CACHE STRING "Add UDP TMTC Server")
set(OBSW_ADD_MGT
${INIT_VAL}
CACHE STRING "Add MGT module")
set(OBSW_ADD_BPX_BATTERY_HANDLER
1
CACHE STRING "Add BPX battery module")
set(OBSW_ADD_STAR_TRACKER
1
CACHE STRING "Add Startracker module")
set(OBSW_ADD_SUN_SENSORS
${INIT_VAL}
CACHE STRING "Add sun sensor module")
set(OBSW_ADD_SUS_BOARD_ASS
${INIT_VAL}
CACHE STRING "Add sun sensor board assembly")
set(OBSW_ADD_THERMAL_TEMP_INSERTER
${OBSW_Q7S_EM}
CACHE STRING "Add thermal sensor temperature inserter")
set(OBSW_ADD_ACS_BOARD
1
CACHE STRING "Add ACS board module")
set(OBSW_ADD_GPS_CTRL
${INIT_VAL}
CACHE STRING "Add GPS controllers")
set(OBSW_ADD_CCSDS_IP_CORES
1
CACHE STRING "Add CCSDS IP cores")
set(OBSW_TM_TO_PTME
1
CACHE STRING "Send telemetry to PTME IP core")
set(OBSW_TC_FROM_PDEC
1
CACHE STRING "Poll telecommand from PDEC IP core")
set(OBSW_ADD_TCS_CTRL
1
CACHE STRING "Add TCS controllers")
set(OBSW_ADD_HEATERS
1
CACHE STRING "Add TCS heaters")
set(OBSW_ADD_PLOC_SUPERVISOR
1
CACHE STRING "Add PLOC supervisor handler")
set(OBSW_ADD_SA_DEPL
${INIT_VAL}
CACHE STRING "Add SA deployment handler")
set(OBSW_ADD_PLOC_MPSOC
1
CACHE STRING "Add MPSoC handler")
set(OBSW_ADD_ACS_CTRL
${INIT_VAL}
CACHE STRING "Add ACS controller")
set(OBSW_ADD_RTD_DEVICES
${INIT_VAL}
CACHE STRING "Add RTD devices")
set(OBSW_ADD_RAD_SENSORS
${INIT_VAL}
CACHE STRING "Add Rad Sensor module")
set(OBSW_ADD_PL_PCDU
1
CACHE STRING "Add Payload PCDU modukle")
set(OBSW_ADD_SYRLINKS
1
CACHE STRING "Add Syrlinks module")
set(OBSW_ADD_TMP_DEVICES
1
CACHE STRING "Add TMP devices")
set(OBSW_ADD_GOMSPACE_PCDU
1
CACHE STRING "Add GomSpace PCDU modules")
set(OBSW_ADD_GOMSPACE_ACU
${INIT_VAL}
CACHE STRING "Add GomSpace ACU submodule")
set(OBSW_ADD_RW
${INIT_VAL}
CACHE STRING "Add RW modules")
set(OBSW_ADD_SCEX_DEVICE
1
CACHE STRING "Add Solar Cell Experiment module")
set(OBSW_SYRLINKS_SIMULATED
0
CACHE STRING "Syrlinks is simulated")
# ##############################################################################
# Pre-Sources preparation
# ##############################################################################
# Version handling
set(GIT_VER_HANDLING_OK FALSE)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
determine_version_with_git("--exclude" "docker_*")
set(GIT_INFO
${GIT_INFO}
CACHE STRING "Version information retrieved with git describe")
if(GIT_INFO)
set(GIT_INFO
${GIT_INFO}
CACHE STRING "Version information retrieved with git describe")
# CMakeLists.txt is now single source of information. list(GET GIT_INFO 1
# OBSW_VERSION_MAJOR) list(GET GIT_INFO 2 OBSW_VERSION_MINOR) list(GET
# GIT_INFO 3 OBSW_VERSION_REVISION)
list(LENGTH GIT_INFO LIST_LEN)
if(LIST_LEN GREATER 4)
list(GET GIT_INFO 4 OBSW_VERSION_CST_GIT_SHA1)
endif()
set(GIT_VER_HANDLING_OK TRUE)
else()
set(GIT_VER_HANDLING_OK FALSE)
endif()
endif()
# Set names and variables
set(TARGET_NAME ${CMAKE_PROJECT_NAME})
set(OBSW_NAME ${CMAKE_PROJECT_NAME})
set(WATCHDOG_NAME eive-watchdog)
set(SIMPLE_OBSW_NAME eive-simple)
set(UNITTEST_NAME eive-unittest)
set(LIB_FSFW_NAME fsfw)
set(LIB_ETL_NAME etl)
set(LIB_EIVE_MISSION eive-mission)
set(LIB_ETL_TARGET etl::etl)
set(LIB_CSP_NAME libcsp)
set(LIB_FSFW_HAL_NAME fsfw_hal)
set(LIB_LWGPS_NAME lwgps)
set(LIB_ARCSEC wire)
set(LIB_GOMSPACE_CLIENTS gs_clients)
set(LIB_GOMSPACE_CSP gs_csp)
set(THIRD_PARTY_FOLDER thirdparty)
set(LIB_CXX_FS -lstdc++fs)
set(LIB_CATCH2 Catch2)
set(LIB_GPS gps)
set(LIB_JSON_NAME nlohmann_json::nlohmann_json)
set(LIB_DUMMIES dummies)
# Set path names
set(FSFW_PATH fsfw)
set(MISSION_PATH mission)
set(TEST_PATH test/testtasks)
set(TEST_PATH test)
set(UNITTEST_PATH unittest)
set(LINUX_PATH linux)
set(LIB_GOMSPACE_PATH ${THIRD_PARTY_FOLDER}/gomspace-sw)
set(COMMON_PATH common)
set(DUMMY_PATH dummies)
set(WATCHDOG_PATH watchdog)
set(COMMON_CONFIG_PATH ${COMMON_PATH}/config)
set(UNITTEST_CFG_PATH ${UNITTEST_PATH}/testcfg)
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(LIB_EIVE_MISSION_PATH mission)
set(LIB_ETL_PATH ${THIRD_PARTY_FOLDER}/etl)
set(LIB_CATCH2_PATH ${THIRD_PARTY_FOLDER}/Catch2)
set(LIB_LWGPS_PATH ${THIRD_PARTY_FOLDER}/lwgps)
set(LIB_ARCSEC_PATH ${THIRD_PARTY_FOLDER}/sagittactl)
set(LIB_JSON_PATH ${THIRD_PARTY_FOLDER}/json)
set(FSFW_WARNING_SHADOW_LOCAL_GCC OFF)
set(ADD_LINUX_FILES False)
set(EIVE_ADD_LINUX_FILES OFF)
set(FSFW_ADD_TMSTORAGE ON)
set(FSFW_ADD_COORDINATES ON)
set(FSFW_ADD_SGP4_PROPAGATOR ON)
# 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"
OR ${TGT_BSP} MATCHES "arm/beagleboneblack"
)
set(FSFW_CONFIG_PATH "linux/fsfwconfig")
set(ADD_LINUX_FILES TRUE)
set(ADD_CSP_LIB TRUE)
set(FSFW_HAL_ADD_LINUX ON)
endif()
if(${TGT_BSP} MATCHES "arm/raspberrypi")
add_definitions(-DRASPBERRY_PI)
set(FSFW_HAL_ADD_RASPBERRY_PI ON)
endif()
if(${TGT_BSP} MATCHES "arm/beagleboneblack")
add_definitions(-DBEAGLEBONEBLACK)
endif()
if(${TGT_BSP} MATCHES "arm/q7s")
add_definitions(-DXIPHOS_Q7S)
set(LIBGPS_VERSION_MAJOR 3)
# I assume a newer version than 3.17 will be installed on other Linux board
# than the Q7S
set(LIBGPS_VERSION_MINOR 20)
if(TGT_BSP MATCHES "arm/q7s"
OR TGT_BSP MATCHES "arm/raspberrypi"
OR TGT_BSP MATCHES "arm/beagleboneblack"
OR TGT_BSP MATCHES "arm/egse"
OR TGT_BSP MATCHES "arm/te0720-1cfa")
find_library(${LIB_GPS} gps)
set(FSFW_CONFIG_PATH "linux/fsfwconfig")
if(NOT BUILD_Q7S_SIMPLE_MODE)
set(EIVE_ADD_LINUX_FILES TRUE)
set(EIVE_ADD_LINUX_FSFWCONFIG TRUE)
set(ADD_GOMSPACE_CSP TRUE)
set(ADD_GOMSPACE_CLIENTS TRUE)
set(FSFW_HAL_ADD_LINUX ON)
set(FSFW_HAL_LINUX_ADD_LIBGPIOD ON)
set(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS ON)
endif()
elseif(UNIX)
set(EIVE_ADD_LINUX_FILES ON)
endif()
if(TGT_BSP MATCHES "arm/raspberrypi")
# Used by configure file
set(RASPBERRY_PI ON)
set(FSFW_HAL_ADD_RASPBERRY_PI ON)
endif()
if(TGT_BSP MATCHES "arm/egse")
# Used by configure file
set(EGSE ON)
set(FSFW_HAL_LINUX_ADD_LIBGPIOD OFF)
set(OBSW_ADD_STAR_TRACKER 1)
set(OBSW_DEBUG_STARTRACKER 1)
endif()
if(TGT_BSP MATCHES "arm/beagleboneblack")
# Used by configure file
set(BEAGLEBONEBLACK ON)
endif()
if(TGT_BSP MATCHES "arm/q7s")
# Used by configure file
set(XIPHOS_Q7S ON)
set(LIBGPS_VERSION_MAJOR 3)
set(LIBGPS_VERSION_MINOR 17)
endif()
if(TGT_BSP MATCHES "arm/te0720-1cfa")
set(TE0720_1CFA ON)
endif()
else()
# Required by FSFW library
set(FSFW_CONFIG_PATH "${BSP_PATH}/fsfwconfig")
# Required by FSFW library
set(FSFW_CONFIG_PATH "${BSP_PATH}/fsfwconfig")
if(UNIX)
set(EIVE_ADD_LINUX_FILES ON)
endif()
endif()
include(BuildType)
set_build_type()
set(FSFW_DEBUG_INFO 0)
set(OBSW_ENABLE_PERIODIC_HK 1)
set(Q7S_CHECK_FOR_ALREADY_RUNNING_IMG 0)
if(RELEASE_BUILD MATCHES 0)
set(FSFW_DEBUG_INFO 1)
set(OBSW_ENABLE_PERIODIC_HK 0)
set(Q7S_CHECK_FOR_ALREADY_RUNNING_IMG 1)
endif()
# Configuration files
configure_file(${COMMON_CONFIG_PATH}/commonConfig.h.in commonConfig.h)
configure_file(${FSFW_CONFIG_PATH}/FSFWConfig.h.in FSFWConfig.h)
configure_file(${FSFW_CONFIG_PATH}/OBSWConfig.h.in OBSWConfig.h)
if(${TGT_BSP} MATCHES "arm/q7s")
configure_file(${BSP_PATH}/boardconfig/q7sConfig.h.in q7sConfig.h)
elseif(${TGT_BSP} MATCHES "arm/raspberrypi")
configure_file(${BSP_PATH}/boardconfig/rpiConfig.h.in rpiConfig.h)
configure_file(${BSP_PATH}/OBSWConfig.h.in OBSWConfig.h)
if(TGT_BSP MATCHES "arm/q7s")
configure_file(${BSP_PATH}/boardconfig/q7sConfig.h.in q7sConfig.h)
elseif(TGT_BSP MATCHES "arm/raspberrypi" OR TGT_BSP MATCHES "arm/egse")
configure_file(${BSP_PATH}/boardconfig/rpiConfig.h.in rpiConfig.h)
endif()
configure_file(${WATCHDOG_PATH}/watchdogConf.h.in watchdogConf.h)
# Set common config path for FSFW
set(FSFW_ADDITIONAL_INC_PATHS
"${COMMON_PATH}/config"
${CMAKE_CURRENT_BINARY_DIR}
)
# Set for lwgps library
set(LWGPS_CONFIG_PATH "${COMMON_PATH}/config")
set(FSFW_ADDITIONAL_INC_PATHS "${COMMON_PATH}/config"
${CMAKE_CURRENT_BINARY_DIR})
################################################################################
# ##############################################################################
# Executable and Sources
################################################################################
# ##############################################################################
# Add executable
add_executable(${TARGET_NAME})
# global compiler options need to be set before adding executables
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# Remove unused sections.
add_compile_options("-ffunction-sections" "-fdata-sections")
if(ADD_CSP_LIB)
add_subdirectory(${CSP_LIB_PATH})
# Removed unused sections.
add_link_options("-Wl,--gc-sections")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(COMPILER_FLAGS "/permissive-")
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}
${CMAKE_CURRENT_BINARY_DIR}
)
add_library(${LIB_EIVE_MISSION})
add_library(${LIB_DUMMIES})
# Add main executable
add_executable(${OBSW_NAME})
set(OBSW_BIN_NAME ${CMAKE_PROJECT_NAME})
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"
)
set(WARNING_FLAGS
"-Wall"
"-Wextra"
"-Wimplicit-fallthrough=1"
"-Wno-unused-parameter"
"-Wno-psabi"
"-Wshadow=local"
"-Wduplicated-cond" # check for duplicate conditions
"-Wduplicated-branches" # check for duplicate branches
"-Wlogical-op" # Search for bitwise operations instead of logical
"-Wnull-dereference" # Search for NULL dereference
"-Wundef" # Warn if undefind marcos are used
"-Wformat=2" # Format string problem detection
"-Wformat-overflow=2" # Formatting issues in printf
"-Wformat-truncation=2" # Formatting issues in printf
"-Wformat-security" # Search for dangerous printf operations
"-Wstrict-overflow=3" # Warn if integer overflows might happen
"-Warray-bounds=2" # Some array bounds violations will be found
"-Wshift-overflow=2" # Search for bit left shift overflows (<c++14)
"-Wcast-qual" # Warn if the constness is cast away
"-Wstringop-overflow=4"
# -Wstack-protector # Emits a few false positives for low level access
# -Wconversion # Creates many false positives -Warith-conversion # Use
# with Wconversion to find more implicit conversions -fanalyzer # Should
# be used to look through problems
)
target_compile_options(${OBSW_NAME} PRIVATE ${WARNING_FLAGS})
target_compile_options(${LIB_EIVE_MISSION} PRIVATE ${WARNING_FLAGS})
target_compile_options(${LIB_DUMMIES} PRIVATE ${WARNING_FLAGS})
endif()
# Removed unused sections.
target_link_options(${TARGET_NAME} PRIVATE
"-Wl,--gc-sections"
)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(COMPILER_FLAGS "/permissive-")
set_target_properties(${OBSW_NAME} PROPERTIES OUTPUT_NAME ${OBSW_BIN_NAME})
# Watchdog
if(TGT_BSP MATCHES "arm/q7s")
add_executable(${WATCHDOG_NAME})
else()
add_executable(${WATCHDOG_NAME} EXCLUDE_FROM_ALL)
endif()
add_subdirectory(${WATCHDOG_PATH})
target_link_libraries(${WATCHDOG_NAME} PUBLIC ${LIB_CXX_FS})
target_include_directories(${WATCHDOG_NAME} PUBLIC ${CMAKE_BINARY_DIR})
# unittests
if(NOT TGT_BSP)
add_executable(${UNITTEST_NAME})
else()
add_executable(${UNITTEST_NAME} EXCLUDE_FROM_ALL)
endif()
if(EIVE_ADD_ETL_LIB)
endif()
if(EIVE_ADD_JSON_LIB)
add_subdirectory(${LIB_JSON_PATH})
endif()
add_subdirectory(thirdparty)
if(EIVE_ADD_LINUX_FILES)
if(TGT_BSP MATCHES "arm/q7s")
add_subdirectory(${LIB_GOMSPACE_PATH})
endif()
add_subdirectory(${LINUX_PATH})
endif()
add_subdirectory(${BSP_PATH})
add_subdirectory(${COMMON_PATH})
add_subdirectory(${DUMMY_PATH})
add_subdirectory(${FSFW_PATH})
add_subdirectory(${LIB_EIVE_MISSION_PATH})
add_subdirectory(${TEST_PATH})
add_subdirectory(${UNITTEST_PATH})
# This should have already been downloaded by the FSFW Still include it to be
# safe find_package(etl ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET) Not
# installed, so use FetchContent to download and provide etl if(NOT etl_FOUND)
message(
STATUS
"No ETL installation was found with find_package. Installing and providing "
"etl with FindPackage")
include(FetchContent)
FetchContent_Declare(
etl
GIT_REPOSITORY https://github.com/ETLCPP/etl
GIT_TAG ${FSFW_ETL_LIB_VERSION})
list(APPEND FSFW_FETCH_CONTENT_TARGETS etl)
# endif()
# Use same Catch2 version as framework
if(NOT (TGT_BSP MATCHES "arm/te0720-1cfa")
AND NOT (TGT_BSP MATCHES "arm/q7s")
AND NOT (TGT_BSP MATCHES "arm/raspberrypi"))
# Check whether the user has already installed Catch2 first
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION} CONFIG QUIET)
# Not installed, so use FetchContent to download and provide Catch2
if(NOT Catch2_FOUND)
message(
STATUS
"${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent"
)
include(FetchContent)
FetchContent_Declare(
Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG ${FSFW_CATCH2_LIB_VERSION})
list(APPEND FSFW_FETCH_CONTENT_TARGETS Catch2)
endif()
endif()
# The documentation for FetchContent recommends declaring all the dependencies
# before making them available. We make all declared dependency available here
# after their declaration
if(FSFW_FETCH_CONTENT_TARGETS)
FetchContent_MakeAvailable(${FSFW_FETCH_CONTENT_TARGETS})
if(TARGET etl)
add_library(${LIB_ETL_TARGET} ALIAS etl)
endif()
if(TARGET Catch2)
# Fixes regression -preview4, to be confirmed in later releases Related
# GitHub issue: https://github.com/catchorg/Catch2/issues/2417
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
set_target_properties(Catch2 PROPERTIES EXCLUDE_FROM_ALL "true")
set_target_properties(Catch2WithMain PROPERTIES EXCLUDE_FROM_ALL "true")
endif()
endif()
# ##############################################################################
# Post-Sources preparation
# ##############################################################################
# Add libraries
target_link_libraries(${LIB_EIVE_MISSION} PUBLIC ${LIB_FSFW_NAME}
${LIB_OS_NAME})
target_link_libraries(${LIB_DUMMIES} PUBLIC ${LIB_EIVE_MISSION}
${LIB_FSFW_NAME} ${LIB_JSON_NAME})
target_link_libraries(${OBSW_NAME} PRIVATE ${LIB_EIVE_MISSION} ${LIB_DUMMIES})
if(TGT_BSP MATCHES "arm/q7s")
target_link_libraries(${LIB_EIVE_MISSION} PUBLIC ${LIB_GPS} ${LIB_ARCSEC}
${LIB_GOMSPACE_CLIENTS})
endif()
target_link_libraries(${UNITTEST_NAME} PRIVATE Catch2 ${LIB_EIVE_MISSION}
rapidcsv ${LIB_DUMMIES})
if(TGT_BSP MATCHES "arm/egse")
target_link_libraries(${OBSW_NAME} PRIVATE ${LIB_ARCSEC})
endif()
if(EIVE_ADD_ETL_LIB)
target_link_libraries(${LIB_EIVE_MISSION} PUBLIC ${LIB_ETL_TARGET})
endif()
if(EIVE_ADD_JSON_LIB)
target_link_libraries(${LIB_EIVE_MISSION} PUBLIC ${LIB_JSON_NAME})
endif()
target_link_libraries(${LIB_EIVE_MISSION} PUBLIC ${LIB_CXX_FS})
# Add include paths for all sources.
target_include_directories(
${LIB_EIVE_MISSION} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${FSFW_CONFIG_PATH}
${CMAKE_CURRENT_BINARY_DIR} ${LIB_ARCSEC_PATH})
target_include_directories(
${LIB_DUMMIES} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${FSFW_CONFIG_PATH}
${CMAKE_CURRENT_BINARY_DIR})
if(TGT_BSP MATCHES "arm/q7s" OR TGT_BSP MATCHES "arm/egse")
target_include_directories(${LIB_EIVE_MISSION} PUBLIC ${ARCSEC_LIB_PATH})
endif()
if(CMAKE_VERBOSE)
message(STATUS "Warning flags: ${WARNING_FLAGS}")
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()
if(CMAKE_CROSSCOMPILING)
include(HardwareOsPostConfig)
post_source_hw_os_config()
endif()
if(NOT CMAKE_SIZE)
set(CMAKE_SIZE size)
if(WIN32)
set(FILE_SUFFIX ".exe")
endif()
set(CMAKE_SIZE size)
if(WIN32)
set(FILE_SUFFIX ".exe")
endif()
endif()
if(TGT_BSP)
set(TARGET_STRING "Target BSP: ${TGT_BSP}")
if(EIVE_BUILD_WATCHDOG)
set(TARGET_STRING "OBSW Watchdog")
else()
set(TARGET_STRING "Target BSP: Hosted")
if(TGT_BSP)
set(TARGET_STRING "Target BSP: ${TGT_BSP}")
else()
set(TARGET_STRING "Target BSP: Hosted")
endif()
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}"
)
install(TARGETS ${OBSW_NAME} RUNTIME DESTINATION bin)
string(CONCAT POST_BUILD_COMMENT "Build directory: ${CMAKE_BINARY_DIR}\n"
"Target OSAL: ${FSFW_OSAL}\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()
TARGET ${OBSW_NAME}
POST_BUILD
COMMAND ${CMAKE_SIZE} ${OBSW_BIN_NAME}${FILE_SUFFIX}
COMMENT ${POST_BUILD_COMMENT})

12
Justfile Normal file
View File

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

202
LICENSE Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

13
NOTICE Normal file
View File

@ -0,0 +1,13 @@
Copyright 2021 Institute of Space Systems (IRS), University of Stuttgart
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

1412
README.md

File diff suppressed because it is too large Load Diff

1559
archive/PlocMpsocHandler.cpp Normal file

File diff suppressed because it is too large Load Diff

322
archive/PlocMpsocHandler.h Normal file
View File

@ -0,0 +1,322 @@
#ifndef BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_
#define BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_
#include <linux/payload/PlocMpsocSpecialComHelperLegacy.h>
#include <linux/payload/plocMpsocHelpers.h>
#include <linux/payload/plocSupvDefs.h>
#include <mission/controller/controllerdefinitions/PowerCtrlDefinitions.h>
#include "fsfw/action/CommandActionHelper.h"
#include "fsfw/action/CommandsActionsIF.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/tmtcservices/SourceSequenceCounter.h"
#include "fsfw_hal/linux/gpio/Gpio.h"
#include "fsfw_hal/linux/serial/SerialComIF.h"
static constexpr bool DEBUG_MPSOC_COMMUNICATION = true;
/**
* @brief This is the device handler for the MPSoC of the payload computer.
*
* @details The PLOC uses the space packet protocol for communication. Each command will be
* answered with at least one acknowledgment and one execution report.
* Flight manual:
* https://egit.irs.uni-stuttgart.de/redmine/projects/eive-flight-manual/wiki/PLOC_MPSoC ICD:
* https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_TAS-ILH-IRS/ICD-PLOC/ILH&fileid=1030263
*
* @note The sequence count in the space packets must be incremented with each received and sent
* packet otherwise the MPSoC will reply with an acknowledgment failure report.
*
* NOTE: This is not an example for a good device handler, DO NOT USE THIS AS A REFERENCE HANDLER.
* @author J. Meier, R. Mueller
*/
class PlocMpsocHandler : public DeviceHandlerBase, public CommandsActionsIF {
public:
/**
* @brief Constructor
*
* @param ojectId Object ID of the MPSoC handler
* @param uartcomIFid Object ID of the UART communication interface
* @param comCookie UART communication cookie
* @param plocMPSoCHelper Pointer to MPSoC helper object
* @param uartIsolatorSwitch Gpio object representing the GPIO connected to the UART isolator
* module in the programmable logic
* @param supervisorHandler Object ID of the supervisor handler
*/
PlocMpsocHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF* comCookie,
PlocMpsocSpecialComHelperLegacy* plocMPSoCHelper, Gpio uartIsolatorSwitch,
object_id_t supervisorHandler);
virtual ~PlocMpsocHandler();
virtual ReturnValue_t initialize() override;
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override;
void performOperationHook() override;
MessageQueueIF* getCommandQueuePtr() override;
void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) override;
void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) override;
void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) override;
void completionSuccessfulReceived(ActionId_t actionId) override;
void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) override;
protected:
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t* id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t* id) override;
void fillCommandAndReplyMap() override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t* commandData,
size_t commandDataLen) override;
ReturnValue_t scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId,
size_t* foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) override;
void setNormalDatapoolEntriesInvalid() override;
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator command,
uint8_t expectedReplies = 1, bool useAlternateId = false,
DeviceCommandId_t alternateReplyID = 0) override;
size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override;
ReturnValue_t doSendReadHook() override;
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
bool dontCheckQueue() override;
private:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_MPSOC_HANDLER;
//! [EXPORT] : [COMMENT] PLOC crc failure in telemetry packet
static const Event MEMORY_READ_RPT_CRC_FAILURE = MAKE_EVENT(1, severity::LOW);
//! [EXPORT] : [COMMENT] PLOC receive acknowledgment failure report
//! P1: Command Id which leads the acknowledgment failure report
//! P2: The status field inserted by the MPSoC into the data field
static const Event ACK_FAILURE = MAKE_EVENT(2, severity::LOW);
//! [EXPORT] : [COMMENT] PLOC receive execution failure report
//! P1: Command Id which leads the execution failure report
//! P2: The status field inserted by the MPSoC into the data field
static const Event EXE_FAILURE = MAKE_EVENT(3, severity::LOW);
//! [EXPORT] : [COMMENT] PLOC reply has invalid crc
static const Event MPSOC_HANDLER_CRC_FAILURE = MAKE_EVENT(4, severity::LOW);
//! [EXPORT] : [COMMENT] Packet sequence count in received space packet does not match expected
//! count P1: Expected sequence count P2: Received sequence count
static const Event MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH = MAKE_EVENT(5, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and
//! thus also to shutdown the supervisor.
static const Event MPSOC_SHUTDOWN_FAILED = MAKE_EVENT(6, severity::HIGH);
//! [EXPORT] : [COMMENT] SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for
//! ON transition.
static constexpr Event SUPV_NOT_ON = event::makeEvent(SUBSYSTEM_ID, 7, severity::LOW);
static constexpr Event SUPV_REPLY_TIMEOUT = event::makeEvent(SUBSYSTEM_ID, 8, severity::LOW);
static const uint16_t APID_MASK = 0x7FF;
static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF;
mpsoc::HkReport hkReport;
Countdown mpsocBootTransitionCd = Countdown(6500);
Countdown supvTransitionCd = Countdown(3000);
MessageQueueIF* eventQueue = nullptr;
MessageQueueIF* commandActionHelperQueue = nullptr;
SourceSequenceCounter sequenceCount = SourceSequenceCounter(0);
uint8_t commandBuffer[mpsoc::MAX_COMMAND_SIZE];
SpacePacketCreator creator;
ploc::SpTcParams spParams = ploc::SpTcParams(creator);
PoolEntry<uint32_t> peStatus = PoolEntry<uint32_t>();
PoolEntry<uint8_t> peMode = PoolEntry<uint8_t>();
PoolEntry<uint8_t> peDownlinkPwrOn = PoolEntry<uint8_t>();
PoolEntry<uint8_t> peDownlinkReplyActive = PoolEntry<uint8_t>();
PoolEntry<uint8_t> peDownlinkJesdSyncStatus = PoolEntry<uint8_t>();
PoolEntry<uint8_t> peDownlinkDacStatus = PoolEntry<uint8_t>();
PoolEntry<uint8_t> peCameraStatus = PoolEntry<uint8_t>();
PoolEntry<uint8_t> peCameraSdiStatus = PoolEntry<uint8_t>();
PoolEntry<float> peCameraFpgaTemp = PoolEntry<float>();
PoolEntry<float> peCameraSocTemp = PoolEntry<float>();
PoolEntry<float> peSysmonTemp = PoolEntry<float>();
PoolEntry<float> peSysmonVccInt = PoolEntry<float>();
PoolEntry<float> peSysmonVccAux = PoolEntry<float>();
PoolEntry<float> peSysmonVccBram = PoolEntry<float>();
PoolEntry<float> peSysmonVccPaux = PoolEntry<float>();
PoolEntry<float> peSysmonVccPint = PoolEntry<float>();
PoolEntry<float> peSysmonVccPdro = PoolEntry<float>();
PoolEntry<float> peSysmonMb12V = PoolEntry<float>();
PoolEntry<float> peSysmonMb3V3 = PoolEntry<float>();
PoolEntry<float> peSysmonMb1V8 = PoolEntry<float>();
PoolEntry<float> peSysmonVcc12V = PoolEntry<float>();
PoolEntry<float> peSysmonVcc5V = PoolEntry<float>();
PoolEntry<float> peSysmonVcc3V3 = PoolEntry<float>();
PoolEntry<float> peSysmonVcc3V3VA = PoolEntry<float>();
PoolEntry<float> peSysmonVcc2V5DDR = PoolEntry<float>();
PoolEntry<float> peSysmonVcc1V2DDR = PoolEntry<float>();
PoolEntry<float> peSysmonVcc0V9 = PoolEntry<float>();
PoolEntry<float> peSysmonVcc0V6VTT = PoolEntry<float>();
PoolEntry<float> peSysmonSafeCotsCur = PoolEntry<float>();
PoolEntry<float> peSysmonNvm4XoCur = PoolEntry<float>();
PoolEntry<uint16_t> peSemUncorrectableErrs = PoolEntry<uint16_t>();
PoolEntry<uint16_t> peSemCorrectableErrs = PoolEntry<uint16_t>();
PoolEntry<uint8_t> peSemStatus = PoolEntry<uint8_t>();
PoolEntry<uint8_t> peRebootMpsocRequired = PoolEntry<uint8_t>();
/**
* This variable is used to store the id of the next reply to receive. This is necessary
* because the PLOC sends as reply to each command at least one acknowledgment and execution
* report.
*/
DeviceCommandId_t nextReplyId = mpsoc::NONE;
SerialComIF* uartComIf = nullptr;
PlocMpsocSpecialComHelperLegacy* specialComHelper = nullptr;
Gpio uartIsolatorSwitch;
object_id_t supervisorHandler = 0;
CommandActionHelper commandActionHelper;
// Used to block incoming commands when MPSoC helper class is currently executing a command
bool specialComHelperExecuting = false;
bool commandIsPending = false;
struct TmMemReadReport {
static const uint8_t FIX_SIZE = 14;
size_t rememberRequestedSize = 0;
};
TmMemReadReport tmMemReadReport;
Countdown cmdCountdown = Countdown(15000);
struct TelemetryBuffer {
uint16_t length = 0;
uint8_t buffer[mpsoc::SP_MAX_SIZE];
};
size_t foundPacketLen = 0;
TelemetryBuffer tmBuffer;
enum class StartupState { IDLE, HW_INIT, DONE } startupState = StartupState::IDLE;
enum class PowerState { IDLE, PENDING_STARTUP, PENDING_SHUTDOWN, SUPV_FAILED, DONE };
PowerState powerState = PowerState::IDLE;
uint8_t skipSupvCommandingToOn = false;
/**
* @brief Handles events received from the PLOC MPSoC helper
*/
void handleEvent(EventMessage* eventMessage);
ReturnValue_t prepareTcMemWrite(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareTcMemRead(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareTcFlashDelete(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareTcReplayStart(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareTcReplayStop();
ReturnValue_t prepareTcDownlinkPwrOn(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareTcDownlinkPwrOff();
ReturnValue_t prepareTcGetHkReport();
ReturnValue_t prepareTcGetDirContent(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareTcReplayWriteSequence(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareTcCamCmdSend(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareTcModeIdle();
ReturnValue_t prepareTcCamTakePic(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareTcSimplexSendFile(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareTcDownlinkDataModulate(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareTcModeSnapshot();
ReturnValue_t finishTcPrep(mpsoc::TcBase& tcBase);
/**
* @brief This function checks the crc of the received PLOC reply.
*
* @param start Pointer to the first byte of the reply.
* @param foundLen Pointer to the length of the whole packet.
*
* @return returnvalue::OK if CRC is ok, otherwise CRC_FAILURE.
*/
ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen);
/**
* @brief This function handles the acknowledgment report.
*
* @param data Pointer to the data holding the acknowledgment report.
*
* @return returnvalue::OK if successful, otherwise an error code.
*/
ReturnValue_t handleAckReport(const uint8_t* data);
/**
* @brief This function handles the data of a execution report.
*
* @param data Pointer to the received data packet.
*
* @return returnvalue::OK if successful, otherwise an error code.
*/
ReturnValue_t handleExecutionReport(const uint8_t* data);
/**
* @brief This function handles the memory read report.
*
* @param data Pointer to the data buffer holding the memory read report.
*
* @return returnvalue::OK if successful, otherwise an error code.
*/
ReturnValue_t handleMemoryReadReport(const uint8_t* data);
ReturnValue_t handleGetHkReport(const uint8_t* data);
ReturnValue_t handleCamCmdRpt(const uint8_t* data);
/**
* @brief Depending on the current active command, this function sets the reply id of the
* next reply after a successful acknowledgment report has been received. This is
* required by the function getNextReplyLength() to identify the length of the next
* reply to read.
*/
void setNextReplyId();
/**
* @brief This function handles action message replies in case the telemetry has been
* requested by another object.
*
* @param data Pointer to the telemetry data.
* @param dataSize Size of telemetry in bytes.
* @param replyId Id of the reply. This will be added to the ActionMessage.
*/
void handleDeviceTm(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId);
/**
* @brief In case an acknowledgment failure reply has been received this function disables
* all previously enabled commands and resets the exepected replies variable of an
* active command.
*/
void disableAllReplies();
/**
* @brief This function sends a failure report if the active action was commanded by an other
* object.
*
* @param replyId The id of the reply which signals a failure.
* @param status A status byte which gives information about the failure type.
*/
void sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status);
/**
* @brief This function disables the execution report reply. Within this function also the
* the variable expectedReplies of an active command will be set to 0.
*/
void disableExeReportReply();
ReturnValue_t prepareTcModeReplay();
void cmdDoneHandler(bool success, ReturnValue_t result);
bool handleHwStartup();
bool handleHwShutdown();
void stopSpecialComHelper();
void handleActionCommandFailure(ActionId_t actionId);
pwrctrl::EnablePl enablePl = pwrctrl::EnablePl(objects::POWER_CONTROLLER);
ReturnValue_t checkModeCommand(Mode_t commandedMode, Submode_t commandedSubmode,
uint32_t* msToReachTheMode) override;
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) override;
};
#endif /* BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_ */

View File

@ -0,0 +1,545 @@
#include <fsfw/globalfunctions/arrayprinter.h>
#include <fsfw/tasks/TaskFactory.h>
#include <linux/payload/PlocMpsocSpecialComHelperLegacy.h>
#include <unistd.h>
#include <filesystem>
#include <fstream>
#ifdef XIPHOS_Q7S
#include "bsp_q7s/fs/FilesystemHelper.h"
#endif
#include "mission/utility/Timestamp.h"
using namespace ploc;
PlocMpsocSpecialComHelperLegacy::PlocMpsocSpecialComHelperLegacy(object_id_t objectId)
: SystemObject(objectId) {
spParams.buf = commandBuffer;
spParams.maxSize = sizeof(commandBuffer);
}
PlocMpsocSpecialComHelperLegacy::~PlocMpsocSpecialComHelperLegacy() {}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::initialize() {
#ifdef XIPHOS_Q7S
sdcMan = SdCardManager::instance();
if (sdcMan == nullptr) {
sif::warning << "PlocMPSoCHelper::initialize: Invalid SD Card Manager" << std::endl;
return returnvalue::FAILED;
}
#endif
return returnvalue::OK;
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::performOperation(uint8_t operationCode) {
ReturnValue_t result = returnvalue::OK;
semaphore.acquire();
while (true) {
#if OBSW_THREAD_TRACING == 1
trace::threadTrace(opCounter, "PLOC MPSOC Helper");
#endif
switch (internalState) {
case InternalState::IDLE: {
semaphore.acquire();
break;
}
case InternalState::FLASH_WRITE: {
result = performFlashWrite();
if (result == returnvalue::OK) {
triggerEvent(MPSOC_FLASH_WRITE_SUCCESSFUL, sequenceCount->get());
} else {
triggerEvent(MPSOC_FLASH_WRITE_FAILED, sequenceCount->get());
}
internalState = InternalState::IDLE;
break;
}
case InternalState::FLASH_READ: {
result = performFlashRead();
if (result == returnvalue::OK) {
triggerEvent(MPSOC_FLASH_READ_SUCCESSFUL, sequenceCount->get());
} else {
triggerEvent(MPSOC_FLASH_READ_FAILED, sequenceCount->get());
}
internalState = InternalState::IDLE;
break;
}
default:
sif::debug << "PlocMPSoCHelper::performOperation: Invalid state" << std::endl;
break;
}
}
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::setComIF(
DeviceCommunicationIF* communicationInterface_) {
uartComIF = dynamic_cast<SerialComIF*>(communicationInterface_);
if (uartComIF == nullptr) {
sif::warning << "PlocMPSoCHelper::initialize: Invalid uart com if" << std::endl;
return returnvalue::FAILED;
}
return returnvalue::OK;
}
void PlocMpsocSpecialComHelperLegacy::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; }
void PlocMpsocSpecialComHelperLegacy::setSequenceCount(SourceSequenceCounter* sequenceCount_) {
sequenceCount = sequenceCount_;
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::startFlashWrite(std::string obcFile,
std::string mpsocFile) {
if (internalState != InternalState::IDLE) {
return returnvalue::FAILED;
}
ReturnValue_t result = startFlashReadOrWriteBase(std::move(obcFile), std::move(mpsocFile));
if (result != returnvalue::OK) {
return result;
}
internalState = InternalState::FLASH_WRITE;
return semaphore.release();
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::startFlashRead(std::string obcFile,
std::string mpsocFile,
size_t readFileSize) {
if (internalState != InternalState::IDLE) {
return returnvalue::FAILED;
}
ReturnValue_t result = startFlashReadOrWriteBase(std::move(obcFile), std::move(mpsocFile));
if (result != returnvalue::OK) {
return result;
}
flashReadAndWrite.totalReadSize = readFileSize;
internalState = InternalState::FLASH_READ;
return semaphore.release();
}
void PlocMpsocSpecialComHelperLegacy::resetHelper() {
spParams.buf = commandBuffer;
terminate = false;
uartComIF->flushUartRxBuffer(comCookie);
}
void PlocMpsocSpecialComHelperLegacy::stopProcess() { terminate = true; }
ReturnValue_t PlocMpsocSpecialComHelperLegacy::performFlashWrite() {
ReturnValue_t result = returnvalue::OK;
std::ifstream file(flashReadAndWrite.obcFile, std::ifstream::binary);
if (file.bad()) {
return returnvalue::FAILED;
}
result = flashfopen(mpsoc::FileAccessModes::WRITE | mpsoc::FileAccessModes::OPEN_ALWAYS);
if (result != returnvalue::OK) {
return result;
}
// Set position of next character to end of file input stream
file.seekg(0, file.end);
// tellg returns position of character in input stream
size_t remainingSize = file.tellg();
size_t dataLength = 0;
size_t bytesRead = 0;
while (remainingSize > 0) {
if (terminate) {
return returnvalue::OK;
}
// The minus 4 is necessary for unknown reasons. Maybe some bug in the ILH software?
if (remainingSize > mpsoc::MAX_FLASH_WRITE_DATA_SIZE - 4) {
dataLength = mpsoc::MAX_FLASH_WRITE_DATA_SIZE - 4;
} else {
dataLength = remainingSize;
}
if (file.bad() or not file.is_open()) {
return FILE_WRITE_ERROR;
}
file.seekg(bytesRead, file.beg);
file.read(reinterpret_cast<char*>(fileBuf.data()), dataLength);
bytesRead += dataLength;
remainingSize -= dataLength;
mpsoc::TcFlashWrite tc(spParams, *sequenceCount);
result = tc.setPayload(fileBuf.data(), dataLength);
if (result != returnvalue::OK) {
return result;
}
result = tc.finishPacket();
if (result != returnvalue::OK) {
return result;
}
(*sequenceCount)++;
result = handlePacketTransmissionNoReply(tc);
if (result != returnvalue::OK) {
return result;
}
}
result = flashfclose();
if (result != returnvalue::OK) {
return result;
}
return result;
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::performFlashRead() {
std::error_code e;
std::ofstream ofile(flashReadAndWrite.obcFile, std::ios::trunc | std::ios::binary);
if (ofile.bad()) {
return returnvalue::FAILED;
}
ReturnValue_t result = flashfopen(mpsoc::FileAccessModes::READ);
if (result != returnvalue::OK) {
std::filesystem::remove(flashReadAndWrite.obcFile, e);
return result;
}
size_t readSoFar = 0;
size_t nextReadSize = mpsoc::MAX_FLASH_READ_DATA_SIZE;
while (readSoFar < flashReadAndWrite.totalReadSize) {
if (terminate) {
std::filesystem::remove(flashReadAndWrite.obcFile, e);
return returnvalue::OK;
}
nextReadSize = mpsoc::MAX_FLASH_READ_DATA_SIZE;
if (flashReadAndWrite.totalReadSize - readSoFar < mpsoc::MAX_FLASH_READ_DATA_SIZE) {
nextReadSize = flashReadAndWrite.totalReadSize - readSoFar;
}
if (ofile.bad() or not ofile.is_open()) {
std::filesystem::remove(flashReadAndWrite.obcFile, e);
return FILE_READ_ERROR;
}
mpsoc::TcFlashRead flashReadRequest(spParams, *sequenceCount);
result = flashReadRequest.setPayload(nextReadSize);
if (result != returnvalue::OK) {
std::filesystem::remove(flashReadAndWrite.obcFile, e);
return result;
}
result = flashReadRequest.finishPacket();
if (result != returnvalue::OK) {
std::filesystem::remove(flashReadAndWrite.obcFile, e);
return result;
}
(*sequenceCount)++;
result = handlePacketTransmissionFlashRead(flashReadRequest, ofile, nextReadSize);
if (result != returnvalue::OK) {
std::filesystem::remove(flashReadAndWrite.obcFile, e);
return result;
}
readSoFar += nextReadSize;
}
result = flashfclose();
if (result != returnvalue::OK) {
return result;
}
return result;
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::flashfopen(uint8_t mode) {
spParams.buf = commandBuffer;
mpsoc::FlashFopen flashFopen(spParams, *sequenceCount);
ReturnValue_t result = flashFopen.setPayload(flashReadAndWrite.mpsocFile, mode);
if (result != returnvalue::OK) {
return result;
}
result = flashFopen.finishPacket();
if (result != returnvalue::OK) {
return result;
}
(*sequenceCount)++;
result = handlePacketTransmissionNoReply(flashFopen);
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::flashfclose() {
spParams.buf = commandBuffer;
mpsoc::FlashFclose flashFclose(spParams, *sequenceCount);
ReturnValue_t result = flashFclose.finishPacket();
if (result != returnvalue::OK) {
return result;
}
(*sequenceCount)++;
result = handlePacketTransmissionNoReply(flashFclose);
if (result != returnvalue::OK) {
return result;
}
return result;
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::handlePacketTransmissionFlashRead(
mpsoc::TcFlashRead& tc, std::ofstream& ofile, size_t expectedReadLen) {
ReturnValue_t result = sendCommand(tc);
if (result != returnvalue::OK) {
return result;
}
result = handleAck();
if (result != returnvalue::OK) {
return result;
}
result = handleTmReception();
if (result != returnvalue::OK) {
return result;
}
// We have the nominal case where the flash read report appears first, or the case where we
// get an EXE failure immediately.
if (spReader.getApid() == mpsoc::apid::TM_FLASH_READ_REPORT) {
result = handleFlashReadReply(ofile, expectedReadLen);
if (result != returnvalue::OK) {
return result;
}
return handleExe();
} else if (spReader.getApid() == mpsoc::apid::EXE_FAILURE) {
handleExeFailure();
} else {
triggerEvent(MPSOC_EXE_INVALID_APID, spReader.getApid(), static_cast<uint32_t>(internalState));
sif::warning << "PLOC MPSoC: Expected execution report "
<< "but received space packet with apid " << std::hex << spReader.getApid()
<< std::endl;
}
return returnvalue::FAILED;
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::handlePacketTransmissionNoReply(ploc::SpTcBase& tc) {
ReturnValue_t result = sendCommand(tc);
if (result != returnvalue::OK) {
return result;
}
result = handleAck();
if (result != returnvalue::OK) {
return result;
}
return handleExe();
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::sendCommand(ploc::SpTcBase& tc) {
ReturnValue_t result = returnvalue::OK;
result = uartComIF->sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen());
if (result != returnvalue::OK) {
sif::warning << "PlocMPSoCHelper::sendCommand: Failed to send command" << std::endl;
triggerEvent(MPSOC_SENDING_COMMAND_FAILED, result, static_cast<uint32_t>(internalState));
return result;
}
return result;
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::handleAck() {
ReturnValue_t result = returnvalue::OK;
result = handleTmReception();
if (result != returnvalue::OK) {
return result;
}
result = checkReceivedTm();
if (result != returnvalue::OK) {
return result;
}
uint16_t apid = spReader.getApid();
if (apid != mpsoc::apid::ACK_SUCCESS) {
handleAckApidFailure(spReader);
return returnvalue::FAILED;
}
return returnvalue::OK;
}
void PlocMpsocSpecialComHelperLegacy::handleAckApidFailure(const ploc::SpTmReader& reader) {
uint16_t apid = reader.getApid();
if (apid == mpsoc::apid::ACK_FAILURE) {
uint16_t status = mpsoc::getStatusFromRawData(reader.getFullData());
sif::warning << "PLOC MPSoC ACK Failure: " << mpsoc::getStatusString(status) << std::endl;
triggerEvent(MPSOC_ACK_FAILURE_REPORT, static_cast<uint32_t>(internalState), status);
} else {
triggerEvent(MPSOC_ACK_INVALID_APID, apid, static_cast<uint32_t>(internalState));
sif::warning << "PlocMPSoCHelper::handleAckApidFailure: Expected acknowledgement report "
<< "but received space packet with apid " << std::hex << apid << std::endl;
}
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::handleExe() {
ReturnValue_t result = returnvalue::OK;
result = handleTmReception();
if (result != returnvalue::OK) {
return result;
}
result = checkReceivedTm();
if (result != returnvalue::OK) {
return result;
}
uint16_t apid = spReader.getApid();
if (apid == mpsoc::apid::EXE_FAILURE) {
handleExeFailure();
return returnvalue::FAILED;
} else if (apid != mpsoc::apid::EXE_SUCCESS) {
triggerEvent(MPSOC_EXE_INVALID_APID, apid, static_cast<uint32_t>(internalState));
sif::warning << "PLOC MPSoC: Expected execution report "
<< "but received space packet with apid " << std::hex << apid << std::endl;
}
return returnvalue::OK;
}
void PlocMpsocSpecialComHelperLegacy::handleExeFailure() {
uint16_t status = mpsoc::getStatusFromRawData(spReader.getFullData());
sif::warning << "PLOC MPSoC EXE Failure: " << mpsoc::getStatusString(status) << std::endl;
triggerEvent(MPSOC_EXE_FAILURE_REPORT, static_cast<uint32_t>(internalState));
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::handleTmReception() {
ReturnValue_t result = returnvalue::OK;
tmCountdown.resetTimer();
size_t readBytes = 0;
size_t currentBytes = 0;
uint32_t usleepDelay = 5;
size_t fullPacketLen = 0;
while (true) {
if (tmCountdown.hasTimedOut()) {
triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs());
return returnvalue::FAILED;
}
result = receive(tmBuf.data() + readBytes, 6, &currentBytes);
if (result != returnvalue::OK) {
return result;
}
spReader.setReadOnlyData(tmBuf.data(), tmBuf.size());
fullPacketLen = spReader.getFullPacketLen();
readBytes += currentBytes;
if (readBytes == 6) {
break;
}
usleep(usleepDelay);
if (usleepDelay < 200000) {
usleepDelay *= 4;
}
}
while (true) {
if (tmCountdown.hasTimedOut()) {
triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs());
return returnvalue::FAILED;
}
result = receive(tmBuf.data() + readBytes, fullPacketLen - readBytes, &currentBytes);
readBytes += currentBytes;
if (fullPacketLen == readBytes) {
break;
}
usleep(usleepDelay);
if (usleepDelay < 200000) {
usleepDelay *= 4;
}
}
// arrayprinter::print(tmBuf.data(), readBytes);
return result;
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::handleFlashReadReply(std::ofstream& ofile,
size_t expectedReadLen) {
ReturnValue_t result = checkReceivedTm();
if (result != returnvalue::OK) {
return result;
}
uint16_t apid = spReader.getApid();
if (apid != mpsoc::apid::TM_FLASH_READ_REPORT) {
triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_APID_ERROR);
sif::warning << "PLOC MPSoC Flash Read: Unexpected APID" << std::endl;
return result;
}
const uint8_t* packetData = spReader.getPacketData();
size_t deserDummy = spReader.getPacketDataLen() - mpsoc::CRC_SIZE;
uint32_t receivedReadLen = 0;
// I think this is buggy, weird stuff in the short name field.
// std::string receivedShortName = std::string(reinterpret_cast<const char*>(packetData), 12);
// if (receivedShortName != flashReadAndWrite.mpsocFile.substr(0, 11)) {
// sif::warning << "PLOC MPSoC Flash Read: Missmatch between request file name and "
// "received file name"
// << std::endl;
// triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_FILENAME_ERROR);
// return returnvalue::FAILED;
// }
packetData += 12;
result = SerializeAdapter::deSerialize(&receivedReadLen, &packetData, &deserDummy,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
if (receivedReadLen != expectedReadLen) {
sif::warning << "PLOC MPSoC Flash Read: Missmatch between request read length and "
"received read length"
<< std::endl;
triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_READLEN_ERROR);
return returnvalue::FAILED;
}
ofile.write(reinterpret_cast<const char*>(packetData), receivedReadLen);
return returnvalue::OK;
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::fileCheck(std::string obcFile) {
#ifdef XIPHOS_Q7S
ReturnValue_t result = FilesystemHelper::checkPath(obcFile);
if (result != returnvalue::OK) {
return result;
}
#elif defined(TE0720_1CFA)
if (not std::filesystem::exists(obcFile)) {
sif::warning << "PlocMPSoCHelper::startFlashWrite: File " << obcFile << "does not exist"
<< std::endl;
return returnvalue::FAILED;
}
#endif
return returnvalue::OK;
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::startFlashReadOrWriteBase(std::string obcFile,
std::string mpsocFile) {
ReturnValue_t result = fileCheck(obcFile);
if (result != returnvalue::OK) {
return result;
}
flashReadAndWrite.obcFile = std::move(obcFile);
flashReadAndWrite.mpsocFile = std::move(mpsocFile);
resetHelper();
return returnvalue::OK;
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::checkReceivedTm() {
ReturnValue_t result = spReader.checkSize();
if (result != returnvalue::OK) {
sif::error << "PLOC MPSoC: Size check on received TM failed" << std::endl;
triggerEvent(MPSOC_TM_SIZE_ERROR);
return result;
}
result = spReader.checkCrc();
if (result != returnvalue::OK) {
sif::warning << "PLOC MPSoC: CRC check failed" << std::endl;
triggerEvent(MPSOC_TM_CRC_MISSMATCH, *sequenceCount);
return result;
}
uint16_t recvSeqCnt = spReader.getSequenceCount();
if (recvSeqCnt != *sequenceCount) {
triggerEvent(MPSOC_HELPER_SEQ_CNT_MISMATCH, *sequenceCount, recvSeqCnt);
*sequenceCount = recvSeqCnt;
}
// This sequence count ping pong does not make any sense but it is how the MPSoC expects it.
(*sequenceCount)++;
return returnvalue::OK;
}
ReturnValue_t PlocMpsocSpecialComHelperLegacy::receive(uint8_t* data, size_t requestBytes,
size_t* readBytes) {
ReturnValue_t result = returnvalue::OK;
uint8_t* buffer = nullptr;
result = uartComIF->requestReceiveMessage(comCookie, requestBytes);
if (result != returnvalue::OK) {
sif::warning << "PlocMPSoCHelper::receive: Failed to request reply" << std::endl;
triggerEvent(MPSOC_HELPER_REQUESTING_REPLY_FAILED, result,
static_cast<uint32_t>(static_cast<uint32_t>(internalState)));
return returnvalue::FAILED;
}
result = uartComIF->readReceivedMessage(comCookie, &buffer, readBytes);
if (result != returnvalue::OK) {
sif::warning << "PlocMPSoCHelper::receive: Failed to read received message" << std::endl;
triggerEvent(MPSOC_HELPER_READING_REPLY_FAILED, result, static_cast<uint32_t>(internalState));
return returnvalue::FAILED;
}
if (*readBytes > 0) {
std::memcpy(data, buffer, *readBytes);
}
return result;
}

View File

@ -0,0 +1,200 @@
#ifndef BSP_Q7S_DEVICES_PLOCMPSOCHELPER_H_
#define BSP_Q7S_DEVICES_PLOCMPSOCHELPER_H_
#include <linux/payload/plocMpsocHelpers.h>
#include <mission/utility/trace.h>
#include <string>
#include "OBSWConfig.h"
#include "fsfw/devicehandlers/CookieIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/osal/linux/BinarySemaphore.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tmtcservices/SourceSequenceCounter.h"
#include "fsfw_hal/linux/serial/SerialComIF.h"
#ifdef XIPHOS_Q7S
#include "bsp_q7s/fs/SdCardManager.h"
#endif
/**
* @brief Helper class for MPSoC of PLOC intended to accelerate large data transfers between
* MPSoC and OBC.
* @author J. Meier
*/
class PlocMpsocSpecialComHelperLegacy : public SystemObject, public ExecutableObjectIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_MPSOC_HELPER;
//! [EXPORT] : [COMMENT] Flash write fails
static const Event MPSOC_FLASH_WRITE_FAILED = MAKE_EVENT(0, severity::LOW);
//! [EXPORT] : [COMMENT] Flash write successful
static const Event MPSOC_FLASH_WRITE_SUCCESSFUL = MAKE_EVENT(1, severity::INFO);
//! [EXPORT] : [COMMENT] Communication interface returned failure when trying to send the command
//! to the MPSoC
//! P1: Return value returned by the communication interface sendMessage function
//! P2: Internal state of MPSoC helper
static const Event MPSOC_SENDING_COMMAND_FAILED = MAKE_EVENT(2, severity::LOW);
//! [EXPORT] : [COMMENT] Request receive message of communication interface failed
//! P1: Return value returned by the communication interface requestReceiveMessage function
//! P2: Internal state of MPSoC helper
static const Event MPSOC_HELPER_REQUESTING_REPLY_FAILED = MAKE_EVENT(3, severity::LOW);
//! [EXPORT] : [COMMENT] Reading receive message of communication interface failed
//! P1: Return value returned by the communication interface readingReceivedMessage function
//! P2: Internal state of MPSoC helper
static const Event MPSOC_HELPER_READING_REPLY_FAILED = MAKE_EVENT(4, severity::LOW);
//! [EXPORT] : [COMMENT] Did not receive acknowledgment report
//! P1: Number of bytes missing
//! P2: Internal state of MPSoC helper
static const Event MPSOC_MISSING_ACK = MAKE_EVENT(5, severity::LOW);
//! [EXPORT] : [COMMENT] Did not receive execution report
//! P1: Number of bytes missing
//! P2: Internal state of MPSoC helper
static const Event MPSOC_MISSING_EXE = MAKE_EVENT(6, severity::LOW);
//! [EXPORT] : [COMMENT] Received acknowledgment failure report
//! P1: Internal state of MPSoC
static const Event MPSOC_ACK_FAILURE_REPORT = MAKE_EVENT(7, severity::LOW);
//! [EXPORT] : [COMMENT] Received execution failure report
//! P1: Internal state of MPSoC
static const Event MPSOC_EXE_FAILURE_REPORT = MAKE_EVENT(8, severity::LOW);
//! [EXPORT] : [COMMENT] Expected acknowledgment report but received space packet with other apid
//! P1: Apid of received space packet
//! P2: Internal state of MPSoC
static const Event MPSOC_ACK_INVALID_APID = MAKE_EVENT(9, severity::LOW);
//! [EXPORT] : [COMMENT] Expected execution report but received space packet with other apid
//! P1: Apid of received space packet
//! P2: Internal state of MPSoC
static const Event MPSOC_EXE_INVALID_APID = MAKE_EVENT(10, severity::LOW);
//! [EXPORT] : [COMMENT] Received sequence count does not match expected sequence count
//! P1: Expected sequence count
//! P2: Received sequence count
static const Event MPSOC_HELPER_SEQ_CNT_MISMATCH = MAKE_EVENT(11, severity::LOW);
static const Event MPSOC_TM_SIZE_ERROR = MAKE_EVENT(12, severity::LOW);
static const Event MPSOC_TM_CRC_MISSMATCH = MAKE_EVENT(13, severity::LOW);
static const Event MPSOC_FLASH_READ_PACKET_ERROR = MAKE_EVENT(14, severity::LOW);
static const Event MPSOC_FLASH_READ_FAILED = MAKE_EVENT(15, severity::LOW);
static const Event MPSOC_FLASH_READ_SUCCESSFUL = MAKE_EVENT(16, severity::INFO);
static const Event MPSOC_READ_TIMEOUT = MAKE_EVENT(17, severity::LOW);
enum FlashReadErrorType : uint32_t {
FLASH_READ_APID_ERROR = 0,
FLASH_READ_FILENAME_ERROR = 1,
FLASH_READ_READLEN_ERROR = 2
};
PlocMpsocSpecialComHelperLegacy(object_id_t objectId);
virtual ~PlocMpsocSpecialComHelperLegacy();
ReturnValue_t initialize() override;
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
ReturnValue_t setComIF(DeviceCommunicationIF* communicationInterface_);
void setComCookie(CookieIF* comCookie_);
/**
* @brief Starts flash write sequence
*
* @param obcFile File where to read from the data
* @param mpsocFile The file of the MPSoC where should be written to
*
* @return returnvalue::OK if successful, otherwise error return value
*/
ReturnValue_t startFlashWrite(std::string obcFile, std::string mpsocFile);
/**
*
* @param obcFile Full target file name on OBC
* @param mpsocFile The file on the MPSoC which should be copied ot the OBC
* @param readFileSize The size of the file on the MPSoC.
* @return
*/
ReturnValue_t startFlashRead(std::string obcFile, std::string mpsocFile, size_t readFileSize);
/**
* @brief Can be used to interrupt a running data transfer.
*/
void stopProcess();
/**
* @brief Sets the sequence count object responsible for the sequence count handling
*/
void setSequenceCount(SourceSequenceCounter* sequenceCount_);
private:
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_MPSOC_HELPER;
//! [EXPORT] : [COMMENT] File error occured for file transfers from OBC to the MPSoC.
static const ReturnValue_t FILE_WRITE_ERROR = MAKE_RETURN_CODE(0xA0);
//! [EXPORT] : [COMMENT] File error occured for file transfers from MPSoC to OBC.
static const ReturnValue_t FILE_READ_ERROR = MAKE_RETURN_CODE(0xA1);
// Maximum number of times the communication interface retries polling data from the reply
// buffer
static const int RETRIES = 10000;
struct FlashInfo {
std::string obcFile;
std::string mpsocFile;
};
struct FlashRead : public FlashInfo {
size_t totalReadSize = 0;
};
struct FlashRead flashReadAndWrite;
#if OBSW_THREAD_TRACING == 1
uint32_t opCounter = 0;
#endif
enum class InternalState { IDLE, FLASH_WRITE, FLASH_READ };
InternalState internalState = InternalState::IDLE;
BinarySemaphore semaphore;
#ifdef XIPHOS_Q7S
SdCardManager* sdcMan = nullptr;
#endif
uint8_t commandBuffer[mpsoc::MAX_COMMAND_SIZE];
SpacePacketCreator creator;
ploc::SpTcParams spParams = ploc::SpTcParams(creator);
Countdown tmCountdown = Countdown(5000);
std::array<uint8_t, mpsoc::SP_MAX_DATA_SIZE> fileBuf{};
std::array<uint8_t, mpsoc::MAX_REPLY_SIZE> tmBuf{};
bool terminate = false;
/**
* Communication interface of MPSoC responsible for low level access. Must be set by the
* MPSoC Handler.
*/
SerialComIF* uartComIF = nullptr;
// Communication cookie. Must be set by the MPSoC Handler
CookieIF* comCookie = nullptr;
// Sequence count, must be set by Ploc MPSoC Handler
SourceSequenceCounter* sequenceCount = nullptr;
ploc::SpTmReader spReader;
void resetHelper();
ReturnValue_t performFlashWrite();
ReturnValue_t performFlashRead();
ReturnValue_t flashfopen(uint8_t accessMode);
ReturnValue_t flashfclose();
ReturnValue_t handlePacketTransmissionNoReply(ploc::SpTcBase& tc);
ReturnValue_t handlePacketTransmissionFlashRead(mpsoc::TcFlashRead& tc, std::ofstream& ofile,
size_t expectedReadLen);
ReturnValue_t handleFlashReadReply(std::ofstream& ofile, size_t expectedReadLen);
ReturnValue_t sendCommand(ploc::SpTcBase& tc);
ReturnValue_t receive(uint8_t* data, size_t requestBytes, size_t* readBytes);
ReturnValue_t handleAck();
ReturnValue_t handleExe();
ReturnValue_t startFlashReadOrWriteBase(std::string obcFile, std::string mpsocFile);
ReturnValue_t fileCheck(std::string obcFile);
void handleAckApidFailure(const ploc::SpTmReader& reader);
void handleExeFailure();
ReturnValue_t handleTmReception();
ReturnValue_t checkReceivedTm();
};
#endif /* BSP_Q7S_DEVICES_PLOCMPSOCHELPER_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,389 @@
#ifndef MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_
#define MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_
#include <linux/payload/PlocSupvUartMan.h>
#include <linux/payload/plocSupvDefs.h>
#include <mission/controller/controllerdefinitions/PowerCtrlDefinitions.h>
#include "OBSWConfig.h"
#include "devices/powerSwitcherList.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/timemanager/Countdown.h"
#include "fsfw_hal/linux/gpio/Gpio.h"
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
#include "fsfw_hal/linux/serial/SerialComIF.h"
#ifdef XIPHOS_Q7S
#include "bsp_q7s/fs/SdCardManager.h"
#endif
using supv::ExecutionReport;
using supv::TcBase;
static constexpr bool DEBUG_PLOC_SUPV = true;
static constexpr bool REDUCE_NORMAL_MODE_PRINTOUT = true;
/**
* @brief This is the device handler for the supervisor of the PLOC which is programmed by
* Thales.
*
* @details The PLOC uses the space packet protocol for communication. On each command the PLOC
* answers with at least one acknowledgment and one execution report.
* Flight manual:
* https://egit.irs.uni-stuttgart.de/redmine/projects/eive-flight-manual/wiki/PLOC_Commands
* ILH ICD: https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/
* Arbeitsdaten/08_Used%20Components/PLOC&fileid=940960
* @author J. Meier
*/
class PlocSupervisorHandler : public DeviceHandlerBase {
public:
PlocSupervisorHandler(object_id_t objectId, CookieIF* comCookie, Gpio uartIsolatorSwitch,
power::Switch_t powerSwitch, PlocSupvUartManager& supvHelper);
virtual ~PlocSupervisorHandler();
virtual ReturnValue_t initialize() override;
void performOperationHook() override;
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override;
protected:
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t* id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t* id) override;
void fillCommandAndReplyMap() override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t* commandData,
size_t commandDataLen) override;
ReturnValue_t scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId,
size_t* foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) override;
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator command,
uint8_t expectedReplies = 1, bool useAlternateId = false,
DeviceCommandId_t alternateReplyID = 0) override;
size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override;
// ReturnValue_t doSendReadHook() override;
void doOffActivity() override;
private:
static const uint16_t APID_MASK = 0x7FF;
static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF;
static const uint8_t EXE_STATUS_OFFSET = 10;
static const uint8_t SIZE_NULL_TERMINATOR = 1;
// 5 s
static const uint32_t EXECUTION_DEFAULT_TIMEOUT = 5000;
// 70 S
static const uint32_t ACKNOWLEDGE_DEFAULT_TIMEOUT = 5000;
// 60 s
static const uint32_t MRAM_DUMP_EXECUTION_TIMEOUT = 60000;
// 70 s
static const uint32_t COPY_ADC_TO_MRAM_TIMEOUT = 70000;
// 60 s
static const uint32_t MRAM_DUMP_TIMEOUT = 60000;
enum class StartupState : uint8_t {
OFF,
BOOTING,
SET_TIME,
WAIT_FOR_TIME_REPLY,
TIME_WAS_SET,
ON
};
static constexpr bool SET_TIME_DURING_BOOT = true;
StartupState startupState = StartupState::OFF;
uint8_t commandBuffer[supv::MAX_COMMAND_SIZE];
SpacePacketCreator creator;
supv::TcParams spParams = supv::TcParams(creator);
/**
* This variable is used to store the id of the next reply to receive. This is necessary
* because the PLOC sends as reply to each command at least one acknowledgment and execution
* report.
*/
DeviceCommandId_t nextReplyId = supv::NONE;
SerialComIF* uartComIf = nullptr;
LinuxLibgpioIF* gpioComIF = nullptr;
Gpio uartIsolatorSwitch;
bool shutdownCmdSent = false;
// Yeah, I am using an extra variable because I once again don't know
// what the hell the base class is doing and I don't care anymore.
bool normalCommandIsPending = false;
// True men implement their reply timeout handling themselves!
Countdown normalCmdCd = Countdown(2000);
bool commandIsPending = false;
Countdown cmdCd = Countdown(2000);
supv::HkSet hkset;
supv::BootStatusReport bootStatusReport;
supv::LatchupStatusReport latchupStatusReport;
supv::CountersReport countersReport;
supv::AdcReport adcReport;
const power::Switch_t powerSwitch = power::NO_SWITCH;
supv::TmBase tmReader;
PlocSupvUartManager& uartManager;
MessageQueueIF* eventQueue = nullptr;
/** Number of expected replies following the MRAM dump command */
uint32_t expectedMramDumpPackets = 0;
uint32_t receivedMramDumpPackets = 0;
/** Set to true as soon as a complete space packet is present in the spacePacketBuffer */
bool packetInBuffer = false;
/** This buffer is used to concatenate space packets received in two different read steps */
uint8_t spacePacketBuffer[supv::MAX_PACKET_SIZE];
#ifdef XIPHOS_Q7S
SdCardManager* sdcMan = nullptr;
#endif
// Path to supervisor specific files on SD card
std::string supervisorFilePath = "ploc/supervisor";
std::string activeMramFile;
Countdown executionReportTimeout = Countdown(EXECUTION_DEFAULT_TIMEOUT, false);
Countdown acknowledgementReportTimeout = Countdown(ACKNOWLEDGE_DEFAULT_TIMEOUT, false);
// Vorago nees some time to boot properly
Countdown bootTimeout = Countdown(supv::BOOT_TIMEOUT_MS);
Countdown mramDumpTimeout = Countdown(MRAM_DUMP_TIMEOUT);
PoolEntry<uint16_t> adcRawEntry = PoolEntry<uint16_t>(16);
PoolEntry<uint16_t> adcEngEntry = PoolEntry<uint16_t>(16);
PoolEntry<uint32_t> latchupCounters = PoolEntry<uint32_t>(7);
PoolEntry<uint8_t> fmcStateEntry = PoolEntry<uint8_t>(1);
PoolEntry<uint8_t> bootStateEntry = PoolEntry<uint8_t>(1);
PoolEntry<uint8_t> bootCyclesEntry = PoolEntry<uint8_t>(1);
PoolEntry<uint32_t> tempSupEntry = PoolEntry<uint32_t>(1);
/**
* @brief Adjusts the timeout of the execution report dependent on command
*/
void setExecutionTimeout(DeviceCommandId_t command);
void handlePacketPrint();
/**
* @brief Handles event messages received from the supervisor helper
*/
void handleEvent(EventMessage* eventMessage);
ReturnValue_t getSwitches(const uint8_t** switches, uint8_t* numberOfSwitches);
/**
* @brief This function checks the crc of the received PLOC reply.
*
* @param start Pointer to the first byte of the reply.
* @param foundLen Pointer to the length of the whole packet.
*
* @return returnvalue::OK if CRC is ok, otherwise CRC_FAILURE.
*/
ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen);
/**
* @brief This function handles the acknowledgment report.
*
* @param data Pointer to the data holding the acknowledgment report.
*
* @return returnvalue::OK if successful, otherwise an error code.
*/
ReturnValue_t handleAckReport(const uint8_t* data);
/**
* @brief This function handles the data of a execution report.
*
* @param data Pointer to the received data packet.
*
* @return returnvalue::OK if successful, otherwise an error code.
*/
ReturnValue_t handleExecutionReport(const uint8_t* data);
/**
* @brief This function handles the housekeeping report. This means verifying the CRC of the
* reply and filling the appropriate dataset.
*
* @param data Pointer to the data buffer holding the housekeeping read report.
*
* @return returnvalue::OK if successful, otherwise an error code.
*/
ReturnValue_t handleHkReport(const uint8_t* data);
/**
* @brief This function calls the function to check the CRC of the received boot status report
* and fills the associated dataset with the boot status information.
*/
ReturnValue_t handleBootStatusReport(const uint8_t* data);
ReturnValue_t handleLatchupStatusReport(const uint8_t* data);
ReturnValue_t handleCounterReport(const uint8_t* data);
void handleBadApidServiceCombination(Event result, unsigned int apid, unsigned int serviceId);
ReturnValue_t handleAdcReport(const uint8_t* data);
ReturnValue_t genericHandleTm(const char* contextString, const uint8_t* data,
LocalPoolDataSetBase& set);
void disableCommand(DeviceCommandId_t cmd);
/**
* @brief Depending on the current active command, this function sets the reply id of the
* next reply after a successful acknowledgment report has been received. This is
* required by the function getNextReplyLength() to identify the length of the next
* reply to read.
*/
void setNextReplyId();
/**
* @brief This function handles action message replies in case the telemetry has been
* requested by another object.
*
* @param data Pointer to the telemetry data.
* @param dataSize Size of telemetry in bytes.
* @param replyId Id of the reply. This will be added to the ActionMessage.
*/
void handleDeviceTm(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId);
/**
* @brief This function prepares a space packet which does not transport any data in the
* packet data field apart from the crc.
*/
ReturnValue_t prepareEmptyCmd(uint16_t apid, uint8_t serviceId);
/**
* @brief This function initializes the space packet to select the boot image of the MPSoC.
*/
ReturnValue_t prepareSelBootImageCmd(const uint8_t* commandData);
ReturnValue_t prepareDisableHk();
/**
* @brief This function fills the commandBuffer with the data to update the time of the
* PLOC supervisor.
*/
ReturnValue_t prepareSetTimeRefCmd();
/**
* @brief This function fills the commandBuffer with the data to change the boot timeout
* value in the PLOC supervisor.
*/
ReturnValue_t prepareSetBootTimeoutCmd(const uint8_t* commandData);
ReturnValue_t prepareRestartTriesCmd(const uint8_t* commandData);
ReturnValue_t prepareFactoryResetCmd(const uint8_t* commandData, size_t len);
/**
* @brief This function fills the command buffer with the packet to enable or disable the
* watchdogs on the PLOC.
*/
void prepareWatchdogsEnableCmd(const uint8_t* commandData);
/**
* @brief This function fills the command buffer with the packet to set the watchdog timer
* of one of the three watchdogs (PS, PL, INT).
*/
ReturnValue_t prepareWatchdogsConfigTimeoutCmd(const uint8_t* commandData);
ReturnValue_t prepareLatchupConfigCmd(const uint8_t* commandData,
DeviceCommandId_t deviceCommand);
ReturnValue_t prepareSetAlertLimitCmd(const uint8_t* commandData);
ReturnValue_t prepareSetAdcEnabledChannelsCmd(const uint8_t* commandData);
ReturnValue_t prepareSetAdcWindowAndStrideCmd(const uint8_t* commandData);
ReturnValue_t prepareSetAdcThresholdCmd(const uint8_t* commandData);
ReturnValue_t prepareRunAutoEmTest(const uint8_t* commandData);
ReturnValue_t prepareWipeMramCmd(const uint8_t* commandData);
ReturnValue_t prepareSetGpioCmd(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareReadGpioCmd(const uint8_t* commandData, size_t commandDataLen);
/**
* @brief Copies the content of a space packet to the command buffer.
*/
void finishTcPrep(TcBase& tc);
/**
* @brief In case an acknowledgment failure reply has been received this function disables
* all previously enabled commands and resets the exepected replies variable of an
* active command.
*/
void disableAllReplies();
void disableReply(DeviceCommandId_t replyId);
/**
* @brief This function sends a failure report if the active action was commanded by an other
* object.
*
* @param replyId The id of the reply which signals a failure.
* @param status A status byte which gives information about the failure type.
*/
void sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status);
/**
* @brief This function disables the execution report reply. Within this function also the
* the variable expectedReplies of an active command will be set to 0.
*/
void disableExeReportReply();
/**
* @brief This function generates the Service 8 packets for the MRAM dump data.
*/
ReturnValue_t handleMramDumpPacket(DeviceCommandId_t id);
/**
* @brief With this function the number of expected replies following an MRAM dump command
* will be increased. This is necessary to release the command in case not all replies
* have been received.
*/
void increaseExpectedMramReplies(DeviceCommandId_t id);
/**
* @brief Writes the data of the MRAM dump to a file. The file will be created when receiving
* the first packet.
*/
ReturnValue_t handleMramDumpFile(DeviceCommandId_t id);
/**
* @brief Extracts the length field of a spacePacket referenced by the spacePacket pointer.
*
* @param spacePacket Pointer to the buffer holding the space packet.
*
* @return The value stored in the length field of the data field.
*/
uint16_t readSpacePacketLength(uint8_t* spacePacket);
/**
* @brief Extracts the sequence flags from a space packet referenced by the spacePacket
* pointer.
*
* @param spacePacket Pointer to the buffer holding the space packet.
*
* @return uint8_t where the two least significant bits hold the sequence flags.
*/
uint8_t readSequenceFlags(uint8_t* spacePacket);
ReturnValue_t createMramDumpFile();
ReturnValue_t getTimeStampString(std::string& timeStamp);
ReturnValue_t prepareSetShutdownTimeoutCmd(const uint8_t* commandData);
ReturnValue_t extractUpdateCommand(const uint8_t* commandData, size_t size,
supv::UpdateParams& params);
ReturnValue_t extractBaseParams(const uint8_t** commandData, size_t& remSize,
supv::UpdateParams& params);
ReturnValue_t eventSubscription();
ReturnValue_t handleExecutionSuccessReport(ExecutionReport& report);
void handleExecutionFailureReport(ExecutionReport& report);
void printAckFailureInfo(uint16_t statusCode, DeviceCommandId_t commandId);
pwrctrl::EnablePl enablePl = pwrctrl::EnablePl(objects::POWER_CONTROLLER);
ReturnValue_t checkModeCommand(Mode_t commandedMode, Submode_t commandedSubmode,
uint32_t* msToReachTheMode) override;
};
#endif /* MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ */

View File

@ -0,0 +1,32 @@
#include "GpioCookie.h"
#include <fsfw/serviceinterface/ServiceInterface.h>
GpioCookie::GpioCookie() {}
ReturnValue_t GpioCookie::addGpio(gpioId_t gpioId, GpioBase* gpioConfig) {
if (gpioConfig == nullptr) {
sif::debug << "GpioCookie::addGpio: gpioConfig is nullpointer" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
auto gpioMapIter = gpioMap.find(gpioId);
if (gpioMapIter == gpioMap.end()) {
auto statusPair = gpioMap.emplace(gpioId, gpioConfig);
if (statusPair.second == false) {
#if FSFW_VERBOSE_LEVEL >= 1
sif::error << "GpioCookie::addGpio: Failed to add GPIO " << gpioId << " to GPIO map"
<< std::endl;
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}
#if FSFW_VERBOSE_LEVEL >= 1
sif::error << "GpioCookie::addGpio: GPIO already exists in GPIO map " << std::endl;
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
GpioMap GpioCookie::getGpioMap() const { return gpioMap; }
GpioCookie::~GpioCookie() {}

View File

@ -1,11 +1,12 @@
#ifndef LINUX_GPIO_GPIOCOOKIE_H_
#define LINUX_GPIO_GPIOCOOKIE_H_
#include "GpioIF.h"
#include "gpioDefinitions.h"
#include <fsfw/devicehandlers/CookieIF.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include "GpioIF.h"
#include "gpioDefinitions.h"
/**
* @brief Cookie for the GpioIF. Allows the GpioIF to determine which
* GPIOs to initialize and whether they should be configured as in- or
@ -16,24 +17,23 @@
*
* @author J. Meier
*/
class GpioCookie: public CookieIF {
public:
class GpioCookie : public CookieIF {
public:
GpioCookie();
GpioCookie();
virtual ~GpioCookie();
virtual ~GpioCookie();
ReturnValue_t addGpio(gpioId_t gpioId, GpioBase* gpioConfig);
/**
* @brief Get map with registered GPIOs.
*/
GpioMap getGpioMap() const;
ReturnValue_t addGpio(gpioId_t gpioId, GpioBase* gpioConfig);
/**
* @brief Get map with registered GPIOs.
*/
GpioMap getGpioMap() const;
private:
/**
* Returns a copy of the internal GPIO map.
*/
GpioMap gpioMap;
private:
/**
* Returns a copy of the internal GPIO map.
*/
GpioMap gpioMap;
};
#endif /* LINUX_GPIO_GPIOCOOKIE_H_ */

54
archive/gpio/GpioIF.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef LINUX_GPIO_GPIOIF_H_
#define LINUX_GPIO_GPIOIF_H_
#include <fsfw/devicehandlers/CookieIF.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include "gpioDefinitions.h"
class GpioCookie;
/**
* @brief This class defines the interface for objects requiring the control
* over GPIOs.
* @author J. Meier
*/
class GpioIF : public HasReturnvaluesIF {
public:
virtual ~GpioIF(){};
/**
* @brief Called by the GPIO using object.
* @param cookie Cookie specifying informations of the GPIOs required
* by a object.
*/
virtual ReturnValue_t addGpios(GpioCookie* cookie) = 0;
/**
* @brief By implementing this function a child must provide the
* functionality to pull a certain GPIO to high logic level.
*
* @param gpioId A unique number which specifies the GPIO to drive.
* @return Returns RETURN_OK for success. This should never return RETURN_FAILED.
*/
virtual ReturnValue_t pullHigh(gpioId_t gpioId) = 0;
/**
* @brief By implementing this function a child must provide the
* functionality to pull a certain GPIO to low logic level.
*
* @param gpioId A unique number which specifies the GPIO to drive.
*/
virtual ReturnValue_t pullLow(gpioId_t gpioId) = 0;
/**
* @brief This function requires a child to implement the functionality to read the state of
* an ouput or input gpio.
*
* @param gpioId A unique number which specifies the GPIO to read.
* @param gpioState State of GPIO will be written to this pointer.
*/
virtual ReturnValue_t readGpio(gpioId_t gpioId, int* gpioState) = 0;
};
#endif /* LINUX_GPIO_GPIOIF_H_ */

View File

@ -0,0 +1,295 @@
#include "LinuxLibgpioIF.h"
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <gpiod.h>
#include <linux/gpio/gpioDefinitions.h>
#include <unistd.h>
#include <utility>
#include "GpioCookie.h"
LinuxLibgpioIF::LinuxLibgpioIF(object_id_t objectId) : SystemObject(objectId) {
struct gpiod_chip* chip = gpiod_chip_open_by_label("/amba_pl/gpio@42030000");
sif::debug << chip->name << std::endl;
}
LinuxLibgpioIF::~LinuxLibgpioIF() {}
ReturnValue_t LinuxLibgpioIF::addGpios(GpioCookie* gpioCookie) {
ReturnValue_t result;
if (gpioCookie == nullptr) {
sif::error << "LinuxLibgpioIF::initialize: Invalid cookie" << std::endl;
return RETURN_FAILED;
}
GpioMap mapToAdd = gpioCookie->getGpioMap();
/* Check whether this ID already exists in the map and remove duplicates */
result = checkForConflicts(mapToAdd);
if (result != RETURN_OK) {
return result;
}
result = configureGpios(mapToAdd);
if (result != RETURN_OK) {
return RETURN_FAILED;
}
/* Register new GPIOs in gpioMap */
gpioMap.insert(mapToAdd.begin(), mapToAdd.end());
return RETURN_OK;
}
ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
for (auto& gpioConfig : mapToAdd) {
switch (gpioConfig.second->gpioType) {
case (gpio::GpioTypes::NONE): {
return GPIO_INVALID_INSTANCE;
}
case (gpio::GpioTypes::GPIOD_REGULAR): {
GpiodRegular* regularGpio = dynamic_cast<GpiodRegular*>(gpioConfig.second);
if (regularGpio == nullptr) {
return GPIO_INVALID_INSTANCE;
}
configureRegularGpio(gpioConfig.first, regularGpio);
break;
}
case (gpio::GpioTypes::CALLBACK): {
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioConfig.second);
if (gpioCallback->callback == nullptr) {
return GPIO_INVALID_INSTANCE;
}
gpioCallback->callback(gpioConfig.first, gpio::GpioOperation::WRITE,
gpioCallback->initValue, gpioCallback->callbackArgs);
}
}
}
return RETURN_OK;
}
ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, GpiodRegular* regularGpio) {
std::string chipname;
unsigned int lineNum;
struct gpiod_chip* chip;
gpio::Direction direction;
std::string consumer;
struct gpiod_line* lineHandle;
int result = 0;
chipname = regularGpio->chipname;
chip = gpiod_chip_open_by_name(chipname.c_str());
if (!chip) {
sif::error << "LinuxLibgpioIF::configureGpios: Failed to open chip " << chipname
<< ". Gpio ID: " << gpioId << std::endl;
return RETURN_FAILED;
}
lineNum = regularGpio->lineNum;
lineHandle = gpiod_chip_get_line(chip, lineNum);
if (!lineHandle) {
sif::error << "LinuxLibgpioIF::configureGpios: Failed to open line for GPIO with id " << gpioId
<< std::endl;
gpiod_chip_close(chip);
return RETURN_FAILED;
}
direction = regularGpio->direction;
consumer = regularGpio->consumer;
/* Configure direction and add a description to the GPIO */
switch (direction) {
case (gpio::OUT): {
result = gpiod_line_request_output(lineHandle, consumer.c_str(), regularGpio->initValue);
if (result < 0) {
sif::error << "LinuxLibgpioIF::configureGpios: Failed to request line " << lineNum
<< " from GPIO instance with ID: " << gpioId << std::endl;
gpiod_line_release(lineHandle);
return RETURN_FAILED;
}
break;
}
case (gpio::IN): {
result = gpiod_line_request_input(lineHandle, consumer.c_str());
if (result < 0) {
sif::error << "LinuxLibgpioIF::configureGpios: Failed to request line " << lineNum
<< " from GPIO instance with ID: " << gpioId << std::endl;
gpiod_line_release(lineHandle);
return RETURN_FAILED;
}
break;
}
default: {
sif::error << "LinuxLibgpioIF::configureGpios: Invalid direction specified" << std::endl;
return GPIO_INVALID_INSTANCE;
}
}
/**
* Write line handle to GPIO configuration instance so it can later be used to set or
* read states of GPIOs.
*/
regularGpio->lineHandle = lineHandle;
return RETURN_OK;
}
ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
gpioMapIter = gpioMap.find(gpioId);
if (gpioMapIter == gpioMap.end()) {
sif::warning << "LinuxLibgpioIF::driveGpio: Unknown GPIOD ID " << gpioId << std::endl;
return UNKNOWN_GPIO_ID;
}
if (gpioMapIter->second->gpioType == gpio::GpioTypes::GPIOD_REGULAR) {
return driveGpio(gpioId, dynamic_cast<GpiodRegular*>(gpioMapIter->second), 1);
} else {
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
if (gpioCallback->callback == nullptr) {
return GPIO_INVALID_INSTANCE;
}
gpioCallback->callback(gpioMapIter->first, gpio::GpioOperation::WRITE, 1,
gpioCallback->callbackArgs);
}
return GPIO_TYPE_FAILURE;
}
ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) {
gpioMapIter = gpioMap.find(gpioId);
if (gpioMapIter == gpioMap.end()) {
sif::warning << "LinuxLibgpioIF::driveGpio: Unknown GPIOD ID " << gpioId << std::endl;
return UNKNOWN_GPIO_ID;
}
if (gpioMapIter->second->gpioType == gpio::GpioTypes::GPIOD_REGULAR) {
return driveGpio(gpioId, dynamic_cast<GpiodRegular*>(gpioMapIter->second), 0);
} else {
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
if (gpioCallback->callback == nullptr) {
return GPIO_INVALID_INSTANCE;
}
gpioCallback->callback(gpioMapIter->first, gpio::GpioOperation::WRITE, 0,
gpioCallback->callbackArgs);
}
return GPIO_TYPE_FAILURE;
}
ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId, GpiodRegular* regularGpio,
unsigned int logicLevel) {
if (regularGpio == nullptr) {
return GPIO_TYPE_FAILURE;
}
int result = gpiod_line_set_value(regularGpio->lineHandle, logicLevel);
if (result < 0) {
sif::warning << "LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID " << gpioId
<< " to logic level " << logicLevel << std::endl;
return DRIVE_GPIO_FAILURE;
}
return RETURN_OK;
}
ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, int* gpioState) {
gpioMapIter = gpioMap.find(gpioId);
if (gpioMapIter == gpioMap.end()) {
sif::warning << "LinuxLibgpioIF::readGpio: Unknown GPIOD ID " << gpioId << std::endl;
return UNKNOWN_GPIO_ID;
}
if (gpioMapIter->second->gpioType == gpio::GpioTypes::GPIOD_REGULAR) {
GpiodRegular* regularGpio = dynamic_cast<GpiodRegular*>(gpioMapIter->second);
if (regularGpio == nullptr) {
return GPIO_TYPE_FAILURE;
}
*gpioState = gpiod_line_get_value(regularGpio->lineHandle);
} else {
}
return RETURN_OK;
}
ReturnValue_t LinuxLibgpioIF::checkForConflicts(GpioMap& mapToAdd) {
ReturnValue_t status = HasReturnvaluesIF::RETURN_OK;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
for (auto& gpioConfig : mapToAdd) {
switch (gpioConfig.second->gpioType) {
case (gpio::GpioTypes::GPIOD_REGULAR): {
auto regularGpio = dynamic_cast<GpiodRegular*>(gpioConfig.second);
if (regularGpio == nullptr) {
return GPIO_TYPE_FAILURE;
}
/* Check for conflicts and remove duplicates if necessary */
result = checkForConflictsRegularGpio(gpioConfig.first, regularGpio, mapToAdd);
if (result != HasReturnvaluesIF::RETURN_OK) {
status = result;
}
break;
}
case (gpio::GpioTypes::CALLBACK): {
auto callbackGpio = dynamic_cast<GpioCallback*>(gpioConfig.second);
if (callbackGpio == nullptr) {
return GPIO_TYPE_FAILURE;
}
/* Check for conflicts and remove duplicates if necessary */
result = checkForConflictsCallbackGpio(gpioConfig.first, callbackGpio, mapToAdd);
if (result != HasReturnvaluesIF::RETURN_OK) {
status = result;
}
break;
}
default: {
}
}
}
return status;
}
ReturnValue_t LinuxLibgpioIF::checkForConflictsRegularGpio(gpioId_t gpioIdToCheck,
GpiodRegular* gpioToCheck,
GpioMap& mapToAdd) {
/* Cross check with private map */
gpioMapIter = gpioMap.find(gpioIdToCheck);
if (gpioMapIter != gpioMap.end()) {
if (gpioMapIter->second->gpioType != gpio::GpioTypes::GPIOD_REGULAR) {
sif::warning << "LinuxLibgpioIF::checkForConflicts: ID already exists for different "
"GPIO type"
<< gpioIdToCheck << ". Removing duplicate." << std::endl;
mapToAdd.erase(gpioIdToCheck);
return HasReturnvaluesIF::RETURN_OK;
}
auto ownRegularGpio = dynamic_cast<GpiodRegular*>(gpioMapIter->second);
if (ownRegularGpio == nullptr) {
return GPIO_TYPE_FAILURE;
}
/* Remove element from map to add because a entry for this GPIO
already exists */
sif::warning << "LinuxLibgpioIF::checkForConflictsRegularGpio: Duplicate GPIO definition"
<< " detected. Duplicate will be removed from map to add." << std::endl;
mapToAdd.erase(gpioIdToCheck);
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t LinuxLibgpioIF::checkForConflictsCallbackGpio(gpioId_t gpioIdToCheck,
GpioCallback* callbackGpio,
GpioMap& mapToAdd) {
/* Cross check with private map */
gpioMapIter = gpioMap.find(gpioIdToCheck);
if (gpioMapIter != gpioMap.end()) {
if (gpioMapIter->second->gpioType != gpio::GpioTypes::CALLBACK) {
sif::warning << "LinuxLibgpioIF::checkForConflicts: ID already exists for different "
"GPIO type"
<< gpioIdToCheck << ". Removing duplicate." << std::endl;
mapToAdd.erase(gpioIdToCheck);
return HasReturnvaluesIF::RETURN_OK;
}
/* Remove element from map to add because a entry for this GPIO
already exists */
sif::warning << "LinuxLibgpioIF::checkForConflictsRegularGpio: Duplicate GPIO definition"
<< " detected. Duplicate will be removed from map to add." << std::endl;
mapToAdd.erase(gpioIdToCheck);
}
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -0,0 +1,75 @@
#ifndef LINUX_GPIO_LINUXLIBGPIOIF_H_
#define LINUX_GPIO_LINUXLIBGPIOIF_H_
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfwconfig/returnvalues/classIds.h>
#include <linux/gpio/GpioIF.h>
class GpioCookie;
/**
* @brief This class implements the GpioIF for a linux based system. The
* implementation is based on the libgpiod lib which requires linux 4.8
* or higher.
* @note The Petalinux SDK from Xilinx supports libgpiod since Petalinux
* 2019.1.
*/
class LinuxLibgpioIF : public GpioIF, public SystemObject {
public:
static const uint8_t gpioRetvalId = CLASS_ID::LINUX_LIBGPIO_IF;
static constexpr ReturnValue_t UNKNOWN_GPIO_ID =
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 1);
static constexpr ReturnValue_t DRIVE_GPIO_FAILURE =
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 2);
static constexpr ReturnValue_t GPIO_TYPE_FAILURE =
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 3);
static constexpr ReturnValue_t GPIO_INVALID_INSTANCE =
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 4);
LinuxLibgpioIF(object_id_t objectId);
virtual ~LinuxLibgpioIF();
ReturnValue_t addGpios(GpioCookie* gpioCookie) override;
ReturnValue_t pullHigh(gpioId_t gpioId) override;
ReturnValue_t pullLow(gpioId_t gpioId) override;
ReturnValue_t readGpio(gpioId_t gpioId, int* gpioState) override;
private:
/* Holds the information and configuration of all used GPIOs */
GpioMap gpioMap;
GpioMapIter gpioMapIter;
/**
* @brief This functions drives line of a GPIO specified by the GPIO ID.
*
* @param gpioId The GPIO ID of the GPIO to drive.
* @param logiclevel The logic level to set. O or 1.
*/
ReturnValue_t driveGpio(gpioId_t gpioId, GpiodRegularBase& regularGpio, unsigned int logiclevel);
ReturnValue_t configureRegularGpio(gpioId_t gpioId, GpiodRegularBase& regularGpio);
/**
* @brief This function checks if GPIOs are already registered and whether
* there exists a conflict in the GPIO configuration. E.g. the
* direction.
*
* @param mapToAdd The GPIOs which shall be added to the gpioMap.
*
* @return RETURN_OK if successful, otherwise RETURN_FAILED
*/
ReturnValue_t checkForConflicts(GpioMap& mapToAdd);
ReturnValue_t checkForConflictsRegularGpio(gpioId_t gpiodId, GpiodRegular* regularGpio,
GpioMap& mapToAdd);
ReturnValue_t checkForConflictsCallbackGpio(gpioId_t gpiodId, GpioCallback* regularGpio,
GpioMap& mapToAdd);
/**
* @brief Performs the initial configuration of all GPIOs specified in the GpioMap mapToAdd.
*/
ReturnValue_t configureGpios(GpioMap& mapToAdd);
};
#endif /* LINUX_GPIO_LINUXLIBGPIOIF_H_ */

View File

@ -0,0 +1,83 @@
#ifndef LINUX_GPIO_GPIODEFINITIONS_H_
#define LINUX_GPIO_GPIODEFINITIONS_H_
#include <string>
#include <unordered_map>
using gpioId_t = uint16_t;
namespace gpio {
enum class Levels : uint8_t { LOW = 0, HIGH = 1 };
enum class Direction : uint8_t { IN = 0, OUT = 1 };
enum class GpioOperation { READ, WRITE };
enum class GpioTypes { NONE, GPIOD_REGULAR, CALLBACK };
static constexpr gpioId_t NO_GPIO = -1;
} // namespace gpio
/**
* @brief Struct containing information about the GPIO to use. This is
* required by the libgpiod to access and drive a GPIO.
* @param chipname String of the chipname specifying the group which contains the GPIO to
* access. E.g. gpiochip0. To detect names of GPIO groups run gpiodetect on
* the linux command line.
* @param lineNum The offset of the GPIO within the GPIO group.
* @param consumer Name of the consumer. Simply a description of the GPIO configuration.
* @param direction Specifies whether the GPIO should be used as in- or output.
* @param initValue Defines the initial state of the GPIO when configured as output.
* Only required for output GPIOs.
* @param lineHandle The handle returned by gpiod_chip_get_line will be later written to this
* pointer.
*/
class GpioBase {
public:
GpioBase() = default;
GpioBase(gpio::GpioTypes gpioType, std::string consumer, gpio::Direction direction, int initValue)
: gpioType(gpioType), consumer(consumer), direction(direction), initValue(initValue) {}
virtual ~GpioBase(){};
/* Can be used to cast GpioBase to a concrete child implementation */
gpio::GpioTypes gpioType = gpio::GpioTypes::NONE;
std::string consumer;
gpio::Direction direction = gpio::Direction::IN;
int initValue = 0;
};
class GpiodRegular : public GpioBase {
public:
GpiodRegular()
: GpioBase(gpio::GpioTypes::GPIOD_REGULAR, std::string(), gpio::Direction::IN, 0){};
GpiodRegular(std::string chipname_, int lineNum_, std::string consumer_,
gpio::Direction direction_, int initValue_)
: GpioBase(gpio::GpioTypes::GPIOD_REGULAR, consumer_, direction_, initValue_),
chipname(chipname_),
lineNum(lineNum_) {}
std::string chipname;
int lineNum = 0;
struct gpiod_line* lineHandle = nullptr;
};
class GpioCallback : public GpioBase {
public:
GpioCallback(std::string consumer, gpio::Direction direction_, int initValue_,
void (*callback)(gpioId_t gpioId, gpio::GpioOperation gpioOp, int value, void* args),
void* callbackArgs)
: GpioBase(gpio::GpioTypes::CALLBACK, consumer, direction_, initValue_),
callback(callback),
callbackArgs(callbackArgs) {}
void (*callback)(gpioId_t gpioId, gpio::GpioOperation gpioOp, int value, void* args) = nullptr;
void* callbackArgs = nullptr;
};
using GpioMap = std::unordered_map<gpioId_t, GpioBase*>;
using GpioMapIter = GpioMap::iterator;
#endif /* LINUX_GPIO_GPIODEFINITIONS_H_ */

View File

@ -0,0 +1,128 @@
#include <fcntl.h>
#include <linux/obc/Ptme.h>
#include <sys/mman.h>
CCSDSIPCoreBridge::CCSDSIPCoreBridge(object_id_t objectId, object_id_t tcDestination,
object_id_t tmStoreId, object_id_t tcStoreId,
LinuxLibgpioIF* gpioComIF, std::string uioPtme,
gpioId_t papbBusyId, gpioId_t papbEmptyId)
: TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId),
gpioComIF(gpioComIF),
uioPtme(uioPtme),
papbBusyId(papbBusyId),
papbEmptyId(papbEmptyId) {}
CCSDSIPCoreBridge::~CCSDSIPCoreBridge() {}
ReturnValue_t CCSDSIPCoreBridge::initialize() {
ReturnValue_t result = TmTcBridge::initialize();
fd = open("/dev/uio0", O_RDWR);
if (fd < 1) {
sif::debug << "CCSDSIPCoreBridge::initialize: Invalid UIO device file" << std::endl;
return RETURN_FAILED;
}
/**
* Map uio device in virtual address space
* PROT_WRITE: Map uio device in writable only mode
*/
ptmeBaseAddress =
static_cast<uint32_t*>(mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
if (ptmeBaseAddress == MAP_FAILED) {
sif::error << "CCSDSIPCoreBridge::initialize: Failed to map uio address" << std::endl;
return RETURN_FAILED;
}
return result;
}
ReturnValue_t CCSDSIPCoreBridge::handleTm() {
#if OBSW_TEST_CCSDS_PTME == 1
return sendTestFrame();
#else
return TmTcBridge::handleTm();
#endif
}
ReturnValue_t CCSDSIPCoreBridge::sendTm(const uint8_t* data, size_t dataLen) {
if (pollPapbBusySignal() == RETURN_OK) {
startPacketTransfer();
}
for (size_t idx = 0; idx < dataLen; idx++) {
if (pollPapbBusySignal() == RETURN_OK) {
*(ptmeBaseAddress + PTME_DATA_REG_OFFSET) = static_cast<uint32_t>(*(data + idx));
} else {
sif::debug << "CCSDSIPCoreBridge::sendTm: Only written " << idx - 1 << " of " << dataLen
<< " data" << std::endl;
return RETURN_FAILED;
}
}
if (pollPapbBusySignal() == RETURN_OK) {
endPacketTransfer();
}
return RETURN_OK;
}
void CCSDSIPCoreBridge::startPacketTransfer() { *ptmeBaseAddress = PTME_CONFIG_START; }
void CCSDSIPCoreBridge::endPacketTransfer() { *ptmeBaseAddress = PTME_CONFIG_END; }
ReturnValue_t CCSDSIPCoreBridge::pollPapbBusySignal() {
int papbBusyState = 0;
ReturnValue_t result = RETURN_OK;
/** Check if PAPB interface is ready to receive data */
result = gpioComIF->readGpio(papbBusyId, &papbBusyState);
if (result != RETURN_OK) {
sif::debug << "CCSDSIPCoreBridge::pollPapbBusySignal: Failed to read papb busy signal"
<< std::endl;
return RETURN_FAILED;
}
if (!papbBusyState) {
sif::debug << "CCSDSIPCoreBridge::pollPapbBusySignal: PAPB busy" << std::endl;
return PAPB_BUSY;
}
return RETURN_OK;
}
void CCSDSIPCoreBridge::isPtmeBufferEmpty() {
ReturnValue_t result = RETURN_OK;
int papbEmptyState = 1;
result = gpioComIF->readGpio(papbEmptyId, &papbEmptyState);
if (result != RETURN_OK) {
sif::debug << "CCSDSIPCoreBridge::isPtmeBufferEmpty: Failed to read papb empty signal"
<< std::endl;
return;
}
if (papbEmptyState == 1) {
sif::debug << "CCSDSIPCoreBridge::isPtmeBufferEmpty: Buffer is empty" << std::endl;
} else {
sif::debug << "CCSDSIPCoreBridge::isPtmeBufferEmpty: Buffer is not empty" << std::endl;
}
return;
}
ReturnValue_t CCSDSIPCoreBridge::sendTestFrame() {
/** Size of one complete transfer frame data field amounts to 1105 bytes */
uint8_t testPacket[1105];
/** Fill one test packet */
for (int idx = 0; idx < 1105; idx++) {
testPacket[idx] = static_cast<uint8_t>(idx & 0xFF);
}
ReturnValue_t result = sendTm(testPacket, 1105);
if (result != RETURN_OK) {
return result;
}
return RETURN_OK;
}

View File

@ -0,0 +1,129 @@
#ifndef MISSION_OBC_CCSDSIPCOREBRIDGE_H_
#define MISSION_OBC_CCSDSIPCOREBRIDGE_H_
#include <fsfw/tmtcservices/TmTcBridge.h>
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
#include <cstring>
#include "OBSWConfig.h"
/**
* @brief This class handles the interfacing to the telemetry (PTME) and telecommand (PDEC) IP
* cores responsible for the CCSDS encoding and decoding. The IP cores are implemented
* on the programmable logic and are accessible through the linux UIO driver.
*/
class CCSDSIPCoreBridge : public TmTcBridge {
public:
/**
* @brief Constructor
*
* @param objectId
* @param tcDestination
* @param tmStoreId
* @param tcStoreId
* @param uioPtme Name of the uio device file which provides access to the PTME IP Core.
* @param papbBusyId The ID of the GPIO which is connected to the PAPBBusy_N signal of the
* PTME IP Core. A low logic level indicates the PTME is not ready to
* receive more data.
* @param papbEmptyId The ID of the GPIO which is connected to the PAPBEmpty signal of the
* PTME IP Core. The signal is high when there are no packets in the
* external buffer memory (BRAM).
*/
CCSDSIPCoreBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId,
object_id_t tcStoreId, LinuxLibgpioIF* gpioComIF, std::string uioPtme,
gpioId_t papbBusyId, gpioId_t papbEmptyId);
virtual ~CCSDSIPCoreBridge();
ReturnValue_t initialize() override;
protected:
/**
* Overwriting this function to provide the capability of testing the PTME IP Core
* implementation.
*/
virtual ReturnValue_t handleTm() override;
virtual ReturnValue_t sendTm(const uint8_t* data, size_t dataLen) override;
private:
static const uint8_t INTERFACE_ID = CLASS_ID::CCSDS_IP_CORE_BRIDGE;
static const ReturnValue_t PAPB_BUSY = MAKE_RETURN_CODE(0xA0);
/** Size of mapped address space. 4k (minimal size of pl device) */
// static const int MAP_SIZE = 0xFA0;
static const int MAP_SIZE = 0x1000;
/**
* Configuration bits:
* bit[1:0]: Size of data (1,2,3 or 4 bytes). 1 Byte <=> b00
* bit[2]: Set this bit to 1 to abort a transfered packet
* bit[3]: Signals to PTME the start of a new telemetry packet
*/
static const uint32_t PTME_CONFIG_START = 0x8;
/**
* Writing this word to the ptme base address signals to the PTME that a complete tm packet has
* been transferred.
*/
static const uint32_t PTME_CONFIG_END = 0x0;
/**
* Writing to this offset within the PTME memory space will insert data for encoding to the
* PTME IP core.
* The address offset is 0x400 (= 4 * 256)
*/
static const int PTME_DATA_REG_OFFSET = 256;
LinuxLibgpioIF* gpioComIF = nullptr;
/** The uio device file related to the PTME IP Core */
std::string uioPtme;
/** Pulled to low when PTME not ready to receive data */
gpioId_t papbBusyId = gpio::NO_GPIO;
/** High when externally buffer memory of PTME is empty */
gpioId_t papbEmptyId = gpio::NO_GPIO;
/** The file descriptor of the UIO driver */
int fd;
uint32_t* ptmeBaseAddress = nullptr;
/**
* @brief This function sends the config byte to the PTME IP Core to initiate a packet
* transfer.
*/
void startPacketTransfer();
/**
* @brief This function sends the config byte to the PTME IP Core to signal the end of a
* packet transfer.
*/
void endPacketTransfer();
/**
* @brief This function reads the papb busy signal indicating whether the PAPB interface is
* ready to receive more data or not. PAPB is ready when PAPB_Busy_N == '1'.
*
* @return RETURN_OK when ready to receive data else PAPB_BUSY.
*/
ReturnValue_t pollPapbBusySignal();
/**
* @brief This function can be used for debugging to check wheter there are packets in
* the packet buffer of the PTME or not.
*/
void isPtmeBufferEmpty();
/**
* @brief This function sends a complete telemetry transfer frame data field (1105 bytes)
* to the input of the PTME IP Core. Can be used to test the implementation.
*/
ReturnValue_t sendTestFrame();
};
#endif /* MISSION_OBC_CCSDSIPCOREBRIDGE_H_ */

27
automation/Dockerfile Normal file
View File

@ -0,0 +1,27 @@
FROM ubuntu:focal
RUN apt-get update
RUN apt-get --yes upgrade
#tzdata is a dependency, won't install otherwise
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get --yes install cmake libgpiod-dev xz-utils nano curl git gcc g++ lcov valgrind libgps-dev python3
ARG XIPHOS_SDK_NAME=sdk-xiphos-eive-v0.2.0
# Install Xiphos ARK SDK, which also installs Q7S root filesystem, required for cross-compilation.
RUN curl https://buggy.irs.uni-stuttgart.de/eive/tools/${XIPHOS_SDK_NAME}.tar | tar -x && \
cd ${XIPHOS_SDK_NAME} && \
./ark-glibc-x86_64-eive-image-cortexa9hf-neon-toolchain-nodistro.0.sh -y
# Cross compiler
RUN mkdir -p /usr/tools; \
curl https://buggy.irs.uni-stuttgart.de/eive/tools/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf.tar.gz \
| tar -xz -C /usr/tools
RUN git clone https://github.com/catchorg/Catch2.git && \
cd Catch2 && \
git checkout v3.0.0-preview5 && \
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
cmake --build build/ --target install
ENV ZYNQ_7020_SYSROOT="/opt/xiphos/sdk/ark/sysroots/cortexa9hf-neon-xiphos-linux-gnueabi"
ENV PATH=$PATH:"/usr/tools/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin"

47
automation/Jenkinsfile vendored Normal file
View File

@ -0,0 +1,47 @@
pipeline {
environment {
BUILDDIR_Q7S = 'build_q7s_fm'
BUILDDIR_Q7S_EM = 'build_q7s_em'
BUILDDIR_LINUX = 'build_linux'
}
agent {
docker {
image 'eive-obsw-ci:d5'
args '--sysctl fs.mqueue.msg_max=100'
}
}
stages {
stage('Clean') {
steps {
sh 'rm -rf $BUILDDIR_Q7S'
sh 'rm -rf $BUILDDIR_Q7S_EM'
sh 'rm -rf $BUILDDIR_LINUX'
}
}
stage('Build Q7S') {
steps {
dir(BUILDDIR_Q7S) {
sh 'cmake -DTGT_BSP="arm/q7s" -DCMAKE_BUILD_TYPE=Debug ..'
sh 'cmake --build . -j8'
}
}
}
stage('Build Q7S EM') {
steps {
dir(BUILDDIR_Q7S_EM) {
sh 'cmake -DTGT_BSP="arm/q7s" -DEIVE_Q7S_EM=ON -DCMAKE_BUILD_TYPE=Debug ..'
sh 'cmake --build . -j8'
}
}
}
stage('Build Host and Tests') {
steps {
dir(BUILDDIR_LINUX) {
sh 'cmake ..'
sh 'cmake --build . -j8'
sh './eive-unittest'
}
}
}
}
}

3
bsp_egse/CMakeLists.txt Normal file
View File

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

192
bsp_egse/InitMission.cpp Normal file
View File

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

21
bsp_egse/InitMission.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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

View File

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

View File

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

View File

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

View File

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

28
bsp_egse/main.cpp Normal file
View File

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

View File

@ -1,10 +1,4 @@
target_sources(${TARGET_NAME} PUBLIC
InitMission.cpp
main.cpp
ObjectFactory.cpp
)
target_sources(${OBSW_NAME} PUBLIC scheduling.cpp main.cpp objectFactory.cpp)
add_subdirectory(fsfwconfig)
add_subdirectory(boardconfig)

View File

@ -14,7 +14,7 @@ RUN set -ex; \
rm -rf build-hosted; \
mkdir build-hosted; \
cd build-hosted; \
cmake -DCMAKE_BUILD_TYPE=Release -DOS_FSFW=linux ..;
cmake -DCMAKE_BUILD_TYPE=Release -DOSAL_FSFW=host ..;
ENTRYPOINT ["cmake", "--build", "build-hosted"]
CMD ["-j"]

View File

@ -1,159 +0,0 @@
#include "InitMission.h"
#include "ObjectFactory.h"
#include <OBSWConfig.h>
#include <fsfw/objectmanager/ObjectManagerIF.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
#include <fsfw/tasks/PeriodicTaskIF.h>
#include <fsfw/tasks/TaskFactory.h>
#include <mission/utility/InitMission.h>
#include <iostream>
#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::instance()->setObjectFactoryFunction(ObjectFactory::produce, nullptr);
sif::info << "Initializing all objects.." << std::endl;
ObjectManager::instance()->initialize();
/* This function creates and starts all tasks */
initTasks();
}
void initmission::initTasks() {
TaskFactory* factory = TaskFactory::instance();
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;
}

View File

@ -1,9 +0,0 @@
#ifndef BSP_LINUX_INITMISSION_H_
#define BSP_LINUX_INITMISSION_H_
namespace initmission {
void initMission();
void initTasks();
};
#endif /* BSP_LINUX_INITMISSION_H_ */

127
bsp_hosted/OBSWConfig.h.in Normal file
View File

@ -0,0 +1,127 @@
/**
* @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 FSFWCONFIG_OBSWCONFIG_H_
#define FSFWCONFIG_OBSWCONFIG_H_
#include "commonConfig.h"
/*******************************************************************/
/** All of the following flags should be enabled for mission code */
/*******************************************************************/
#define OBSW_ENABLE_TIMERS 1
#define OBSW_ADD_STAR_TRACKER 0
#define OBSW_ADD_PLOC_SUPERVISOR 0
#define OBSW_ADD_PLOC_MPSOC 0
#define OBSW_ADD_SUN_SENSORS 0
#define OBSW_ADD_MGT 0
#define OBSW_ADD_ACS_BOARD 0
#define OBSW_ADD_ACS_HANDLERS 0
#define OBSW_ADD_GPS_0 0
#define OBSW_ADD_GPS_1 0
#define OBSW_ADD_RW 0
#define OBSW_DEBUG_TMP1075 0
#define OBSW_ADD_BPX_BATTERY_HANDLER 0
#define OBSW_ADD_RTD_DEVICES 0
#define OBSW_ADD_PL_PCDU 0
#define OBSW_ADD_TMP_DEVICES 0
#define OBSW_ADD_RAD_SENSORS 0
#define OBSW_ADD_SYRLINKS 0
#define OBSW_STAR_TRACKER_GROUND_CONFIG 1
// This is a really tricky switch.. It initializes the PCDU switches to their default states
// at powerup. I think it would be better
// to leave it off for now. It makes testing a lot more difficult and it might mess with
// something the operators might want to do by giving the software too much intelligence
// at the wrong place. The system component might command all the Switches accordingly anyway
#define OBSW_INITIALIZE_SWITCHES 0
#define OBSW_ENABLE_PERIODIC_HK 0
/*******************************************************************/
/** All of the following flags should be disabled for mission code */
/*******************************************************************/
// Can be used to switch device to NORMAL mode immediately
#define OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP 1
#define OBSW_PRINT_MISSED_DEADLINES 1
#define OBSW_MPSOC_JTAG_BOOT 0
#define OBSW_SYRLINKS_SIMULATED 1
#define OBSW_ADD_TEST_CODE 0
#define OBSW_ADD_TEST_TASK 0
#define OBSW_ADD_TEST_PST 0
// If this is enabled, all other SPI code should be disabled
#define OBSW_ADD_SPI_TEST_CODE 0
// If this is enabled, all other I2C code should be disabled
#define OBSW_ADD_I2C_TEST_CODE 0
#define OBSW_ADD_UART_TEST_CODE 0
#define OBSW_TEST_ACS 0
#define OBSW_DEBUG_ACS 0
#define OBSW_TEST_SUS 0
#define OBSW_DEBUG_SUS 0
#define OBSW_TEST_RTD 0
#define OBSW_DEBUG_RTD 0
#define OBSW_TEST_RAD_SENSOR 0
#define OBSW_DEBUG_RAD_SENSOR 0
#define OBSW_TEST_PL_PCDU 0
#define OBSW_DEBUG_PL_PCDU 0
#define OBSW_TEST_BPX_BATT 0
#define OBSW_DEBUG_BPX_BATT 0
#define OBSW_TEST_IMTQ 0
#define OBSW_DEBUG_IMTQ 0
#define OBSW_TEST_RW 0
#define OBSW_DEBUG_RW 0
#define OBSW_TEST_LIBGPIOD 0
#define OBSW_TEST_PLOC_HANDLER 0
#define OBSW_TEST_CCSDS_BRIDGE 0
#define OBSW_TEST_CCSDS_PTME 0
#define OBSW_TEST_TE7020_HEATER 0
#define OBSW_TEST_GPIO_OPEN_BY_LABEL 0
#define OBSW_TEST_GPIO_OPEN_BY_LINE_NAME 0
#define OBSW_DEBUG_P60DOCK 0
#define OBSW_PRINT_CORE_HK 0
#define OBSW_DEBUG_PDU1 0
#define OBSW_DEBUG_PDU2 0
#define OBSW_DEBUG_GPS 0
#define OBSW_DEBUG_ACU 0
#define OBSW_DEBUG_SYRLINKS 0
#define OBSW_DEBUG_PDEC_HANDLER 0
#define OBSW_DEBUG_PLOC_SUPERVISOR 0
#define OBSW_DEBUG_PLOC_MPSOC 0
#define OBSW_DEBUG_STARTRACKER 0
#define OBSW_TCP_SERVER_WIRETAPPING 0
/*******************************************************************/
/** CMake Defines */
/*******************************************************************/
#define OBSW_ADD_TMTC_UDP_SERVER 0
#define OBSW_ADD_TMTC_TCP_SERVER 1
#cmakedefine EIVE_BUILD_GPSD_GPS_HANDLER
#cmakedefine LIBGPS_VERSION_MAJOR @LIBGPS_VERSION_MAJOR@
#cmakedefine LIBGPS_VERSION_MINOR @LIBGPS_VERSION_MINOR@
#ifdef RASPBERRY_PI
#include "rpiConfig.h"
#elif defined(XIPHOS_Q7S)
#include "q7sConfig.h"
#endif
#ifdef __cplusplus
#include "objects/systemObjectList.h"
#include "events/subsystemIdRanges.h"
#include "returnvalues/classIds.h"
#endif
#endif /* FSFWCONFIG_OBSWCONFIG_H_ */

View File

@ -1,46 +0,0 @@
#include "ObjectFactory.h"
#include <OBSWConfig.h>
#include <objects/systemObjectList.h>
#include <tmtc/apid.h>
#include <tmtc/pusIds.h>
#include <fsfw/tmtcservices/CommandingServiceBase.h>
#include <fsfw/tmtcservices/PusServiceBase.h>
#include <mission/core/GenericFactory.h>
#include <mission/utility/TmFunnel.h>
#include <fsfw/osal/common/UdpTcPollingTask.h>
#include <fsfw/osal/common/UdpTmTcBridge.h>
#include <fsfw/tmtcpacket/pus/tm.h>
#if OBSW_ADD_TEST_CODE == 1
#include <test/testtasks/TestTask.h>
#endif
void Factory::setStaticFrameworkObjectIds(){
PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR;
PusServiceBase::packetDestination = objects::TM_FUNNEL;
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;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
}
void ObjectFactory::produce(void* args){
Factory::setStaticFrameworkObjectIds();
ObjectFactory::produceGenericObjects();
new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,11 +0,0 @@
# add main and others
CXXSRC += $(wildcard $(CURRENTPATH)/*.cpp)
CSRC += $(wildcard $(CURRENTPATH)/*.c)
CSRC += $(wildcard $(CURRENTPATH)/boardconfig/*.c)
CXXSRC += $(wildcard $(CURRENTPATH)/comIF/*.cpp)
CSRC += $(wildcard $(CURRENTPATH)/comIF/*.c)
INCLUDES += $(CURRENTPATH)/boardconfig
INCLUDES += $(CURRENTPATH)/fsfwconfig

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1 @@
target_sources(${TARGET_NAME} PUBLIC
ArduinoComIF.cpp
ArduinoCookie.cpp
)
target_sources(${OBSW_NAME} PUBLIC ArduinoComIF.cpp ArduinoCookie.cpp)

View File

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

View File

@ -7,41 +7,41 @@
//! 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
#define FSFW_CPP_OSTREAM_ENABLED 1
//! More FSFW related printouts depending on level. Useful for development.
#define FSFW_VERBOSE_LEVEL 1
#define FSFW_VERBOSE_LEVEL 1
//! 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
#define FSFW_DISABLE_PRINTOUT 0
#endif
#define FSFW_USE_PUS_C_TELEMETRY 1
#define FSFW_USE_PUS_C_TELEMETRY 1
#define FSFW_USE_PUS_C_TELECOMMANDS 1
//! Can be used to disable the ANSI color sequences for C stdio.
#define FSFW_COLORED_OUTPUT 1
#define FSFW_COLORED_OUTPUT 1
//! If FSFW_OBJ_EVENT_TRANSLATION is set to one,
//! additional output which requires the translation files translateObjects
//! and translateEvents (and their compiled source files)
#define FSFW_OBJ_EVENT_TRANSLATION 1
#define FSFW_OBJ_EVENT_TRANSLATION 1
#if FSFW_OBJ_EVENT_TRANSLATION == 1
//! Specify whether info events are printed too.
#define FSFW_DEBUG_INFO 1
#include "objects/translateObjects.h"
#define FSFW_DEBUG_INFO 1
#include "events/translateEvents.h"
#include "objects/translateObjects.h"
#else
#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
#define FSFW_USE_MODESTORE 0
//! Defines if the real time scheduler for linux should be used.
//! If set to 0, this will also disable priority settings for linux
@ -50,6 +50,8 @@
//! If set to 1 the binary needs "cap_sys_nice=eip" privileges to run
#define FSFW_USE_REALTIME_FOR_LINUX 0
#define FSFW_UDP_SEND_WIRETAPPING_ENABLED 0
namespace fsfwconfig {
//! Default timestamp size. The default timestamp will be an seven byte CDC short timestamp.
@ -58,7 +60,7 @@ static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 7;
//! Configure the allocated pool sizes for the event manager.
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;
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
@ -70,6 +72,6 @@ static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 124;
static constexpr size_t FSFW_MAX_TM_PACKET_SIZE = 2048;
}
} // namespace fsfwconfig
#endif /* CONFIG_FSFWCONFIG_H_ */

View File

@ -8,11 +8,25 @@
#include "commonConfig.h"
#define OBSW_ADD_TEST_CODE 1
#define OBSW_PRINT_MISSED_DEADLINES 1
#define OBSW_ADD_TEST_CODE 1
/* These defines should be disabled for mission code but are useful for
debugging. */
#define OBSW_VEBOSE_LEVEL 1
#define OBSW_VEBOSE_LEVEL 1
#define OBSW_ADD_CCSDS_IP_CORES 0
// Set to 1 if all telemetry should be sent to the PTME IP Core
#define OBSW_TM_TO_PTME 0
// Set to 1 if telecommands are received via the PDEC IP Core
#define OBSW_TC_FROM_PDEC 0
#define OBSW_SYRLINKS_SIMULATED 0
#define OBSW_INITIALIZE_SWITCHES 0
#define OBSW_TCP_SERVER_WIRETAPPING 0
#ifdef __cplusplus

View File

@ -1,59 +0,0 @@
#ifndef FSFWCONFIG_DEVICES_GPIOIDS_H_
#define FSFWCONFIG_DEVICES_GPIOIDS_H_
#include <linux/gpio/GpioIF.h>
namespace gpioIds {
enum gpioId_t {
HEATER_0,
HEATER_1,
HEATER_2,
HEATER_3,
HEATER_4,
HEATER_5,
HEATER_6,
HEATER_7,
DEPLSA1,
DEPLSA2,
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_ */

View File

@ -1,58 +0,0 @@
#ifndef FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_
#define FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_
#include <OBSWConfig.h>
namespace pcduSwitches {
/* Switches are uint8_t datatype and go from 0 to 255 */
enum switcherList {
Q7S,
PAYLOAD_PCDU_CH1,
RW,
TCS_BOARD_8V_HEATER_IN,
SUS_REDUNDANT,
DEPLOYMENT_MECHANISM,
PAYLOAD_PCDU_CH6,
ACS_BOARD_SIDE_B,
PAYLOAD_CAMERA,
TCS_BOARD_3V3,
SYRLINKS,
STAR_TRACKER,
MGT,
SUS_NOMINAL,
SOLAR_CELL_EXP,
PLOC,
ACS_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_ */

View File

@ -1,17 +1,16 @@
#ifndef CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_
#define CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_
#include <common/config/commonSubsystemIds.h>
#include <cstdint>
#include "eive/eventSubsystemIds.h"
/**
* These IDs are part of the ID for an event thrown by a subsystem.
* Numbers 0-80 are reserved for FSFW Subsystem IDs (framework/events/)
*/
namespace SUBSYSTEM_ID {
enum: uint8_t {
SUBSYSTEM_ID_START = COMMON_SUBSYSTEM_ID_END
};
enum : uint8_t { SUBSYSTEM_ID_START = COMMON_SUBSYSTEM_ID_END };
}
#endif /* CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
#ifndef FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_
#define FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_
#include <fsfw/events/Event.h>
#include "fsfw/events/Event.h"
const char * translateEvents(Event event);
const char *translateEvents(Event event);
#endif /* FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_ */

View File

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

View File

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

View File

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

View File

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

View File

@ -1,21 +1,122 @@
/**
* @brief Auto-generated object translation file.
/**
* @brief Auto-generated object translation file.
* @details
* Contains 31 translations.
* Generated on: 2021-05-17 19:12:49
* Contains 176 translations.
* Generated on: 2024-05-06 13:47:38
*/
#include "translateObjects.h"
const char *TEST_TASK_STRING = "TEST_TASK";
const char *ACS_CONTROLLER_STRING = "ACS_CONTROLLER";
const char *CORE_CONTROLLER_STRING = "CORE_CONTROLLER";
const char *POWER_CONTROLLER_STRING = "POWER_CONTROLLER";
const char *GLOBAL_JSON_CFG_STRING = "GLOBAL_JSON_CFG";
const char *XIPHOS_WDT_STRING = "XIPHOS_WDT";
const char *THERMAL_CONTROLLER_STRING = "THERMAL_CONTROLLER";
const char *DUMMY_HANDLER_STRING = "DUMMY_HANDLER";
const char *MGM_0_LIS3_HANDLER_STRING = "MGM_0_LIS3_HANDLER";
const char *GYRO_0_ADIS_HANDLER_STRING = "GYRO_0_ADIS_HANDLER";
const char *SUS_0_N_LOC_XFYFZM_PT_XF_STRING = "SUS_0_N_LOC_XFYFZM_PT_XF";
const char *SUS_1_N_LOC_XBYFZM_PT_XB_STRING = "SUS_1_N_LOC_XBYFZM_PT_XB";
const char *SUS_2_N_LOC_XFYBZB_PT_YB_STRING = "SUS_2_N_LOC_XFYBZB_PT_YB";
const char *SUS_3_N_LOC_XFYBZF_PT_YF_STRING = "SUS_3_N_LOC_XFYBZF_PT_YF";
const char *SUS_4_N_LOC_XMYFZF_PT_ZF_STRING = "SUS_4_N_LOC_XMYFZF_PT_ZF";
const char *SUS_5_N_LOC_XFYMZB_PT_ZB_STRING = "SUS_5_N_LOC_XFYMZB_PT_ZB";
const char *SUS_6_R_LOC_XFYBZM_PT_XF_STRING = "SUS_6_R_LOC_XFYBZM_PT_XF";
const char *SUS_7_R_LOC_XBYBZM_PT_XB_STRING = "SUS_7_R_LOC_XBYBZM_PT_XB";
const char *SUS_8_R_LOC_XBYBZB_PT_YB_STRING = "SUS_8_R_LOC_XBYBZB_PT_YB";
const char *SUS_9_R_LOC_XBYBZB_PT_YF_STRING = "SUS_9_R_LOC_XBYBZB_PT_YF";
const char *SUS_10_N_LOC_XMYBZF_PT_ZF_STRING = "SUS_10_N_LOC_XMYBZF_PT_ZF";
const char *SUS_11_R_LOC_XBYMZB_PT_ZB_STRING = "SUS_11_R_LOC_XBYMZB_PT_ZB";
const char *RW1_STRING = "RW1";
const char *MGM_1_RM3100_HANDLER_STRING = "MGM_1_RM3100_HANDLER";
const char *GYRO_1_L3G_HANDLER_STRING = "GYRO_1_L3G_HANDLER";
const char *RW2_STRING = "RW2";
const char *MGM_2_LIS3_HANDLER_STRING = "MGM_2_LIS3_HANDLER";
const char *GYRO_2_ADIS_HANDLER_STRING = "GYRO_2_ADIS_HANDLER";
const char *RW3_STRING = "RW3";
const char *MGM_3_RM3100_HANDLER_STRING = "MGM_3_RM3100_HANDLER";
const char *GYRO_3_L3G_HANDLER_STRING = "GYRO_3_L3G_HANDLER";
const char *RW4_STRING = "RW4";
const char *STAR_TRACKER_STRING = "STAR_TRACKER";
const char *GPS_CONTROLLER_STRING = "GPS_CONTROLLER";
const char *GPS_0_HEALTH_DEV_STRING = "GPS_0_HEALTH_DEV";
const char *GPS_1_HEALTH_DEV_STRING = "GPS_1_HEALTH_DEV";
const char *IMTQ_POLLING_STRING = "IMTQ_POLLING";
const char *IMTQ_HANDLER_STRING = "IMTQ_HANDLER";
const char *PCDU_HANDLER_STRING = "PCDU_HANDLER";
const char *P60DOCK_HANDLER_STRING = "P60DOCK_HANDLER";
const char *PDU1_HANDLER_STRING = "PDU1_HANDLER";
const char *PDU2_HANDLER_STRING = "PDU2_HANDLER";
const char *ACU_HANDLER_STRING = "ACU_HANDLER";
const char *BPX_BATT_HANDLER_STRING = "BPX_BATT_HANDLER";
const char *PLPCDU_HANDLER_STRING = "PLPCDU_HANDLER";
const char *RAD_SENSOR_STRING = "RAD_SENSOR";
const char *PLOC_UPDATER_STRING = "PLOC_UPDATER";
const char *PLOC_MEMORY_DUMPER_STRING = "PLOC_MEMORY_DUMPER";
const char *STR_COM_IF_STRING = "STR_COM_IF";
const char *PLOC_MPSOC_HELPER_STRING = "PLOC_MPSOC_HELPER";
const char *AXI_PTME_CONFIG_STRING = "AXI_PTME_CONFIG";
const char *PTME_CONFIG_STRING = "PTME_CONFIG";
const char *PTME_VC0_LIVE_TM_STRING = "PTME_VC0_LIVE_TM";
const char *PTME_VC1_LOG_TM_STRING = "PTME_VC1_LOG_TM";
const char *PTME_VC2_HK_TM_STRING = "PTME_VC2_HK_TM";
const char *PTME_VC3_CFDP_TM_STRING = "PTME_VC3_CFDP_TM";
const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER";
const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER";
const char *PLOC_SUPERVISOR_HELPER_STRING = "PLOC_SUPERVISOR_HELPER";
const char *PLOC_MPSOC_COMMUNICATION_STRING = "PLOC_MPSOC_COMMUNICATION";
const char *SCEX_STRING = "SCEX";
const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER";
const char *HEATER_HANDLER_STRING = "HEATER_HANDLER";
const char *TMP1075_HANDLER_TCS_0_STRING = "TMP1075_HANDLER_TCS_0";
const char *TMP1075_HANDLER_TCS_1_STRING = "TMP1075_HANDLER_TCS_1";
const char *TMP1075_HANDLER_PLPCDU_0_STRING = "TMP1075_HANDLER_PLPCDU_0";
const char *TMP1075_HANDLER_PLPCDU_1_STRING = "TMP1075_HANDLER_PLPCDU_1";
const char *TMP1075_HANDLER_IF_BOARD_STRING = "TMP1075_HANDLER_IF_BOARD";
const char *RTD_0_IC3_PLOC_HEATSPREADER_STRING = "RTD_0_IC3_PLOC_HEATSPREADER";
const char *RTD_1_IC4_PLOC_MISSIONBOARD_STRING = "RTD_1_IC4_PLOC_MISSIONBOARD";
const char *RTD_2_IC5_4K_CAMERA_STRING = "RTD_2_IC5_4K_CAMERA";
const char *RTD_3_IC6_DAC_HEATSPREADER_STRING = "RTD_3_IC6_DAC_HEATSPREADER";
const char *RTD_4_IC7_STARTRACKER_STRING = "RTD_4_IC7_STARTRACKER";
const char *RTD_5_IC8_RW1_MX_MY_STRING = "RTD_5_IC8_RW1_MX_MY";
const char *RTD_6_IC9_DRO_STRING = "RTD_6_IC9_DRO";
const char *RTD_7_IC10_SCEX_STRING = "RTD_7_IC10_SCEX";
const char *RTD_8_IC11_X8_STRING = "RTD_8_IC11_X8";
const char *RTD_9_IC12_HPA_STRING = "RTD_9_IC12_HPA";
const char *RTD_10_IC13_PL_TX_STRING = "RTD_10_IC13_PL_TX";
const char *RTD_11_IC14_MPA_STRING = "RTD_11_IC14_MPA";
const char *RTD_12_IC15_ACU_STRING = "RTD_12_IC15_ACU";
const char *RTD_13_IC16_PLPCDU_HEATSPREADER_STRING = "RTD_13_IC16_PLPCDU_HEATSPREADER";
const char *RTD_14_IC17_TCS_BOARD_STRING = "RTD_14_IC17_TCS_BOARD";
const char *RTD_15_IC18_IMTQ_STRING = "RTD_15_IC18_IMTQ";
const char *SYRLINKS_HANDLER_STRING = "SYRLINKS_HANDLER";
const char *SYRLINKS_COM_HANDLER_STRING = "SYRLINKS_COM_HANDLER";
const char *ARDUINO_COM_IF_STRING = "ARDUINO_COM_IF";
const char *DUMMY_COM_IF_STRING = "DUMMY_COM_IF";
const char *SCEX_UART_READER_STRING = "SCEX_UART_READER";
const char *UART_COM_IF_STRING = "UART_COM_IF";
const char *ACS_BOARD_POLLING_TASK_STRING = "ACS_BOARD_POLLING_TASK";
const char *RW_POLLING_TASK_STRING = "RW_POLLING_TASK";
const char *SPI_RTD_COM_IF_STRING = "SPI_RTD_COM_IF";
const char *SUS_POLLING_TASK_STRING = "SUS_POLLING_TASK";
const char *CCSDS_PACKET_DISTRIBUTOR_STRING = "CCSDS_PACKET_DISTRIBUTOR";
const char *PUS_PACKET_DISTRIBUTOR_STRING = "PUS_PACKET_DISTRIBUTOR";
const char *TCP_TMTC_SERVER_STRING = "TCP_TMTC_SERVER";
const char *UDP_TMTC_SERVER_STRING = "UDP_TMTC_SERVER";
const char *TCP_TMTC_POLLING_TASK_STRING = "TCP_TMTC_POLLING_TASK";
const char *UDP_TMTC_POLLING_TASK_STRING = "UDP_TMTC_POLLING_TASK";
const char *FILE_SYSTEM_HANDLER_STRING = "FILE_SYSTEM_HANDLER";
const char *SDC_MANAGER_STRING = "SDC_MANAGER";
const char *PTME_STRING = "PTME";
const char *PDEC_HANDLER_STRING = "PDEC_HANDLER";
const char *CCSDS_HANDLER_STRING = "CCSDS_HANDLER";
const char *PUS_SERVICE_3_STRING = "PUS_SERVICE_3";
const char *PUS_SERVICE_5_STRING = "PUS_SERVICE_5";
const char *PUS_SERVICE_6_STRING = "PUS_SERVICE_6";
const char *PUS_SERVICE_8_STRING = "PUS_SERVICE_8";
const char *PUS_SERVICE_23_STRING = "PUS_SERVICE_23";
const char *PUS_SERVICE_201_STRING = "PUS_SERVICE_201";
const char *TM_FUNNEL_STRING = "TM_FUNNEL";
const char *FSFW_OBJECTS_START_STRING = "FSFW_OBJECTS_START";
const char *PUS_SERVICE_1_VERIFICATION_STRING = "PUS_SERVICE_1_VERIFICATION";
const char *PUS_SERVICE_2_DEVICE_ACCESS_STRING = "PUS_SERVICE_2_DEVICE_ACCESS";
@ -23,9 +124,13 @@ const char *PUS_SERVICE_3_HOUSEKEEPING_STRING = "PUS_SERVICE_3_HOUSEKEEPING";
const char *PUS_SERVICE_5_EVENT_REPORTING_STRING = "PUS_SERVICE_5_EVENT_REPORTING";
const char *PUS_SERVICE_8_FUNCTION_MGMT_STRING = "PUS_SERVICE_8_FUNCTION_MGMT";
const char *PUS_SERVICE_9_TIME_MGMT_STRING = "PUS_SERVICE_9_TIME_MGMT";
const char *PUS_SERVICE_11_TC_SCHEDULER_STRING = "PUS_SERVICE_11_TC_SCHEDULER";
const char *PUS_SERVICE_15_TM_STORAGE_STRING = "PUS_SERVICE_15_TM_STORAGE";
const char *PUS_SERVICE_17_TEST_STRING = "PUS_SERVICE_17_TEST";
const char *PUS_SERVICE_20_PARAMETERS_STRING = "PUS_SERVICE_20_PARAMETERS";
const char *PUS_SERVICE_200_MODE_MGMT_STRING = "PUS_SERVICE_200_MODE_MGMT";
const char *PUS_SERVICE_201_HEALTH_STRING = "PUS_SERVICE_201_HEALTH";
const char *CFDP_PACKET_DISTRIBUTOR_STRING = "CFDP_PACKET_DISTRIBUTOR";
const char *HEALTH_TABLE_STRING = "HEALTH_TABLE";
const char *MODE_STORE_STRING = "MODE_STORE";
const char *EVENT_MANAGER_STRING = "EVENT_MANAGER";
@ -34,76 +139,406 @@ const char *TC_STORE_STRING = "TC_STORE";
const char *TM_STORE_STRING = "TM_STORE";
const char *IPC_STORE_STRING = "IPC_STORE";
const char *TIME_STAMPER_STRING = "TIME_STAMPER";
const char *VERIFICATION_REPORTER_STRING = "VERIFICATION_REPORTER";
const char *FSFW_OBJECTS_END_STRING = "FSFW_OBJECTS_END";
const char *HEATER_0_PLOC_PROC_BRD_STRING = "HEATER_0_PLOC_PROC_BRD";
const char *HEATER_1_PCDU_BRD_STRING = "HEATER_1_PCDU_BRD";
const char *HEATER_2_ACS_BRD_STRING = "HEATER_2_ACS_BRD";
const char *HEATER_3_OBC_BRD_STRING = "HEATER_3_OBC_BRD";
const char *HEATER_4_CAMERA_STRING = "HEATER_4_CAMERA";
const char *HEATER_5_STR_STRING = "HEATER_5_STR";
const char *HEATER_6_DRO_STRING = "HEATER_6_DRO";
const char *HEATER_7_SYRLINKS_STRING = "HEATER_7_SYRLINKS";
const char *ACS_BOARD_ASS_STRING = "ACS_BOARD_ASS";
const char *SUS_BOARD_ASS_STRING = "SUS_BOARD_ASS";
const char *TCS_BOARD_ASS_STRING = "TCS_BOARD_ASS";
const char *RW_ASSY_STRING = "RW_ASSY";
const char *CAM_SWITCHER_STRING = "CAM_SWITCHER";
const char *SYRLINKS_ASSY_STRING = "SYRLINKS_ASSY";
const char *IMTQ_ASSY_STRING = "IMTQ_ASSY";
const char *STR_ASSY_STRING = "STR_ASSY";
const char *TM_FUNNEL_STRING = "TM_FUNNEL";
const char *PUS_TM_FUNNEL_STRING = "PUS_TM_FUNNEL";
const char *CFDP_TM_FUNNEL_STRING = "CFDP_TM_FUNNEL";
const char *CFDP_HANDLER_STRING = "CFDP_HANDLER";
const char *CFDP_DISTRIBUTOR_STRING = "CFDP_DISTRIBUTOR";
const char *CFDP_FAULT_HANDLER_STRING = "CFDP_FAULT_HANDLER";
const char *EIVE_SYSTEM_STRING = "EIVE_SYSTEM";
const char *ACS_SUBSYSTEM_STRING = "ACS_SUBSYSTEM";
const char *PL_SUBSYSTEM_STRING = "PL_SUBSYSTEM";
const char *TCS_SUBSYSTEM_STRING = "TCS_SUBSYSTEM";
const char *COM_SUBSYSTEM_STRING = "COM_SUBSYSTEM";
const char *EPS_SUBSYSTEM_STRING = "EPS_SUBSYSTEM";
const char *MISC_TM_STORE_STRING = "MISC_TM_STORE";
const char *OK_TM_STORE_STRING = "OK_TM_STORE";
const char *NOT_OK_TM_STORE_STRING = "NOT_OK_TM_STORE";
const char *HK_TM_STORE_STRING = "HK_TM_STORE";
const char *CFDP_TM_STORE_STRING = "CFDP_TM_STORE";
const char *LIVE_TM_TASK_STRING = "LIVE_TM_TASK";
const char *LOG_STORE_AND_TM_TASK_STRING = "LOG_STORE_AND_TM_TASK";
const char *HK_STORE_AND_TM_TASK_STRING = "HK_STORE_AND_TM_TASK";
const char *CFDP_STORE_AND_TM_TASK_STRING = "CFDP_STORE_AND_TM_TASK";
const char *DOWNLINK_RAM_STORE_STRING = "DOWNLINK_RAM_STORE";
const char *THERMAL_TEMP_INSERTER_STRING = "THERMAL_TEMP_INSERTER";
const char *DUMMY_INTERFACE_STRING = "DUMMY_INTERFACE";
const char *NO_OBJECT_STRING = "NO_OBJECT";
const char* translateObject(object_id_t object) {
switch( (object & 0xFFFFFFFF) ) {
case 0x42694269:
return TEST_TASK_STRING;
case 0x4400AFFE:
return DUMMY_HANDLER_STRING;
case 0x49000001:
return ARDUINO_COM_IF_STRING;
case 0x51000300:
return PUS_SERVICE_3_STRING;
case 0x51000400:
return PUS_SERVICE_5_STRING;
case 0x51000500:
return PUS_SERVICE_6_STRING;
case 0x51000800:
return PUS_SERVICE_8_STRING;
case 0x51002300:
return PUS_SERVICE_23_STRING;
case 0x51020100:
return PUS_SERVICE_201_STRING;
case 0x52000002:
return TM_FUNNEL_STRING;
case 0x53000000:
return FSFW_OBJECTS_START_STRING;
case 0x53000001:
return PUS_SERVICE_1_VERIFICATION_STRING;
case 0x53000002:
return PUS_SERVICE_2_DEVICE_ACCESS_STRING;
case 0x53000003:
return PUS_SERVICE_3_HOUSEKEEPING_STRING;
case 0x53000005:
return PUS_SERVICE_5_EVENT_REPORTING_STRING;
case 0x53000008:
return PUS_SERVICE_8_FUNCTION_MGMT_STRING;
case 0x53000009:
return PUS_SERVICE_9_TIME_MGMT_STRING;
case 0x53000017:
return PUS_SERVICE_17_TEST_STRING;
case 0x53000020:
return PUS_SERVICE_20_PARAMETERS_STRING;
case 0x53000200:
return PUS_SERVICE_200_MODE_MGMT_STRING;
case 0x53010000:
return HEALTH_TABLE_STRING;
case 0x53010100:
return MODE_STORE_STRING;
case 0x53030000:
return EVENT_MANAGER_STRING;
case 0x53040000:
return INTERNAL_ERROR_REPORTER_STRING;
case 0x534f0100:
return TC_STORE_STRING;
case 0x534f0200:
return TM_STORE_STRING;
case 0x534f0300:
return IPC_STORE_STRING;
case 0x53500010:
return TIME_STAMPER_STRING;
case 0x53ffffff:
return FSFW_OBJECTS_END_STRING;
case 0xCAFECAFE:
return DUMMY_INTERFACE_STRING;
case 0xFFFFFFFF:
return NO_OBJECT_STRING;
default:
return "UNKNOWN_OBJECT";
}
return 0;
const char *translateObject(object_id_t object) {
switch ((object & 0xFFFFFFFF)) {
case 0x42694269:
return TEST_TASK_STRING;
case 0x43000002:
return ACS_CONTROLLER_STRING;
case 0x43000003:
return CORE_CONTROLLER_STRING;
case 0x43000004:
return POWER_CONTROLLER_STRING;
case 0x43000006:
return GLOBAL_JSON_CFG_STRING;
case 0x43000007:
return XIPHOS_WDT_STRING;
case 0x43400001:
return THERMAL_CONTROLLER_STRING;
case 0x44000001:
return DUMMY_HANDLER_STRING;
case 0x44120006:
return MGM_0_LIS3_HANDLER_STRING;
case 0x44120010:
return GYRO_0_ADIS_HANDLER_STRING;
case 0x44120032:
return SUS_0_N_LOC_XFYFZM_PT_XF_STRING;
case 0x44120033:
return SUS_1_N_LOC_XBYFZM_PT_XB_STRING;
case 0x44120034:
return SUS_2_N_LOC_XFYBZB_PT_YB_STRING;
case 0x44120035:
return SUS_3_N_LOC_XFYBZF_PT_YF_STRING;
case 0x44120036:
return SUS_4_N_LOC_XMYFZF_PT_ZF_STRING;
case 0x44120037:
return SUS_5_N_LOC_XFYMZB_PT_ZB_STRING;
case 0x44120038:
return SUS_6_R_LOC_XFYBZM_PT_XF_STRING;
case 0x44120039:
return SUS_7_R_LOC_XBYBZM_PT_XB_STRING;
case 0x44120040:
return SUS_8_R_LOC_XBYBZB_PT_YB_STRING;
case 0x44120041:
return SUS_9_R_LOC_XBYBZB_PT_YF_STRING;
case 0x44120042:
return SUS_10_N_LOC_XMYBZF_PT_ZF_STRING;
case 0x44120043:
return SUS_11_R_LOC_XBYMZB_PT_ZB_STRING;
case 0x44120047:
return RW1_STRING;
case 0x44120107:
return MGM_1_RM3100_HANDLER_STRING;
case 0x44120111:
return GYRO_1_L3G_HANDLER_STRING;
case 0x44120148:
return RW2_STRING;
case 0x44120208:
return MGM_2_LIS3_HANDLER_STRING;
case 0x44120212:
return GYRO_2_ADIS_HANDLER_STRING;
case 0x44120249:
return RW3_STRING;
case 0x44120309:
return MGM_3_RM3100_HANDLER_STRING;
case 0x44120313:
return GYRO_3_L3G_HANDLER_STRING;
case 0x44120350:
return RW4_STRING;
case 0x44130001:
return STAR_TRACKER_STRING;
case 0x44130045:
return GPS_CONTROLLER_STRING;
case 0x44130046:
return GPS_0_HEALTH_DEV_STRING;
case 0x44130047:
return GPS_1_HEALTH_DEV_STRING;
case 0x44140013:
return IMTQ_POLLING_STRING;
case 0x44140014:
return IMTQ_HANDLER_STRING;
case 0x442000A1:
return PCDU_HANDLER_STRING;
case 0x44250000:
return P60DOCK_HANDLER_STRING;
case 0x44250001:
return PDU1_HANDLER_STRING;
case 0x44250002:
return PDU2_HANDLER_STRING;
case 0x44250003:
return ACU_HANDLER_STRING;
case 0x44260000:
return BPX_BATT_HANDLER_STRING;
case 0x44300000:
return PLPCDU_HANDLER_STRING;
case 0x443200A5:
return RAD_SENSOR_STRING;
case 0x44330000:
return PLOC_UPDATER_STRING;
case 0x44330001:
return PLOC_MEMORY_DUMPER_STRING;
case 0x44330002:
return STR_COM_IF_STRING;
case 0x44330003:
return PLOC_MPSOC_HELPER_STRING;
case 0x44330004:
return AXI_PTME_CONFIG_STRING;
case 0x44330005:
return PTME_CONFIG_STRING;
case 0x44330006:
return PTME_VC0_LIVE_TM_STRING;
case 0x44330007:
return PTME_VC1_LOG_TM_STRING;
case 0x44330008:
return PTME_VC2_HK_TM_STRING;
case 0x44330009:
return PTME_VC3_CFDP_TM_STRING;
case 0x44330015:
return PLOC_MPSOC_HANDLER_STRING;
case 0x44330016:
return PLOC_SUPERVISOR_HANDLER_STRING;
case 0x44330017:
return PLOC_SUPERVISOR_HELPER_STRING;
case 0x44330018:
return PLOC_MPSOC_COMMUNICATION_STRING;
case 0x44330032:
return SCEX_STRING;
case 0x444100A2:
return SOLAR_ARRAY_DEPL_HANDLER_STRING;
case 0x444100A4:
return HEATER_HANDLER_STRING;
case 0x44420004:
return TMP1075_HANDLER_TCS_0_STRING;
case 0x44420005:
return TMP1075_HANDLER_TCS_1_STRING;
case 0x44420006:
return TMP1075_HANDLER_PLPCDU_0_STRING;
case 0x44420007:
return TMP1075_HANDLER_PLPCDU_1_STRING;
case 0x44420008:
return TMP1075_HANDLER_IF_BOARD_STRING;
case 0x44420016:
return RTD_0_IC3_PLOC_HEATSPREADER_STRING;
case 0x44420017:
return RTD_1_IC4_PLOC_MISSIONBOARD_STRING;
case 0x44420018:
return RTD_2_IC5_4K_CAMERA_STRING;
case 0x44420019:
return RTD_3_IC6_DAC_HEATSPREADER_STRING;
case 0x44420020:
return RTD_4_IC7_STARTRACKER_STRING;
case 0x44420021:
return RTD_5_IC8_RW1_MX_MY_STRING;
case 0x44420022:
return RTD_6_IC9_DRO_STRING;
case 0x44420023:
return RTD_7_IC10_SCEX_STRING;
case 0x44420024:
return RTD_8_IC11_X8_STRING;
case 0x44420025:
return RTD_9_IC12_HPA_STRING;
case 0x44420026:
return RTD_10_IC13_PL_TX_STRING;
case 0x44420027:
return RTD_11_IC14_MPA_STRING;
case 0x44420028:
return RTD_12_IC15_ACU_STRING;
case 0x44420029:
return RTD_13_IC16_PLPCDU_HEATSPREADER_STRING;
case 0x44420030:
return RTD_14_IC17_TCS_BOARD_STRING;
case 0x44420031:
return RTD_15_IC18_IMTQ_STRING;
case 0x445300A3:
return SYRLINKS_HANDLER_STRING;
case 0x445300A4:
return SYRLINKS_COM_HANDLER_STRING;
case 0x49000001:
return ARDUINO_COM_IF_STRING;
case 0x49000002:
return DUMMY_COM_IF_STRING;
case 0x49010006:
return SCEX_UART_READER_STRING;
case 0x49030003:
return UART_COM_IF_STRING;
case 0x49060004:
return ACS_BOARD_POLLING_TASK_STRING;
case 0x49060005:
return RW_POLLING_TASK_STRING;
case 0x49060006:
return SPI_RTD_COM_IF_STRING;
case 0x49060007:
return SUS_POLLING_TASK_STRING;
case 0x50000100:
return CCSDS_PACKET_DISTRIBUTOR_STRING;
case 0x50000200:
return PUS_PACKET_DISTRIBUTOR_STRING;
case 0x50000300:
return TCP_TMTC_SERVER_STRING;
case 0x50000301:
return UDP_TMTC_SERVER_STRING;
case 0x50000400:
return TCP_TMTC_POLLING_TASK_STRING;
case 0x50000401:
return UDP_TMTC_POLLING_TASK_STRING;
case 0x50000500:
return FILE_SYSTEM_HANDLER_STRING;
case 0x50000550:
return SDC_MANAGER_STRING;
case 0x50000600:
return PTME_STRING;
case 0x50000700:
return PDEC_HANDLER_STRING;
case 0x50000800:
return CCSDS_HANDLER_STRING;
case 0x51000300:
return PUS_SERVICE_3_STRING;
case 0x51000400:
return PUS_SERVICE_5_STRING;
case 0x51000500:
return PUS_SERVICE_6_STRING;
case 0x51000800:
return PUS_SERVICE_8_STRING;
case 0x51002300:
return PUS_SERVICE_23_STRING;
case 0x51020100:
return PUS_SERVICE_201_STRING;
case 0x53000000:
return FSFW_OBJECTS_START_STRING;
case 0x53000001:
return PUS_SERVICE_1_VERIFICATION_STRING;
case 0x53000002:
return PUS_SERVICE_2_DEVICE_ACCESS_STRING;
case 0x53000003:
return PUS_SERVICE_3_HOUSEKEEPING_STRING;
case 0x53000005:
return PUS_SERVICE_5_EVENT_REPORTING_STRING;
case 0x53000008:
return PUS_SERVICE_8_FUNCTION_MGMT_STRING;
case 0x53000009:
return PUS_SERVICE_9_TIME_MGMT_STRING;
case 0x53000011:
return PUS_SERVICE_11_TC_SCHEDULER_STRING;
case 0x53000015:
return PUS_SERVICE_15_TM_STORAGE_STRING;
case 0x53000017:
return PUS_SERVICE_17_TEST_STRING;
case 0x53000020:
return PUS_SERVICE_20_PARAMETERS_STRING;
case 0x53000200:
return PUS_SERVICE_200_MODE_MGMT_STRING;
case 0x53000201:
return PUS_SERVICE_201_HEALTH_STRING;
case 0x53001000:
return CFDP_PACKET_DISTRIBUTOR_STRING;
case 0x53010000:
return HEALTH_TABLE_STRING;
case 0x53010100:
return MODE_STORE_STRING;
case 0x53030000:
return EVENT_MANAGER_STRING;
case 0x53040000:
return INTERNAL_ERROR_REPORTER_STRING;
case 0x534f0100:
return TC_STORE_STRING;
case 0x534f0200:
return TM_STORE_STRING;
case 0x534f0300:
return IPC_STORE_STRING;
case 0x53500010:
return TIME_STAMPER_STRING;
case 0x53500020:
return VERIFICATION_REPORTER_STRING;
case 0x53ffffff:
return FSFW_OBJECTS_END_STRING;
case 0x60000000:
return HEATER_0_PLOC_PROC_BRD_STRING;
case 0x60000001:
return HEATER_1_PCDU_BRD_STRING;
case 0x60000002:
return HEATER_2_ACS_BRD_STRING;
case 0x60000003:
return HEATER_3_OBC_BRD_STRING;
case 0x60000004:
return HEATER_4_CAMERA_STRING;
case 0x60000005:
return HEATER_5_STR_STRING;
case 0x60000006:
return HEATER_6_DRO_STRING;
case 0x60000007:
return HEATER_7_SYRLINKS_STRING;
case 0x73000001:
return ACS_BOARD_ASS_STRING;
case 0x73000002:
return SUS_BOARD_ASS_STRING;
case 0x73000003:
return TCS_BOARD_ASS_STRING;
case 0x73000004:
return RW_ASSY_STRING;
case 0x73000006:
return CAM_SWITCHER_STRING;
case 0x73000007:
return SYRLINKS_ASSY_STRING;
case 0x73000008:
return IMTQ_ASSY_STRING;
case 0x73000009:
return STR_ASSY_STRING;
case 0x73000100:
return TM_FUNNEL_STRING;
case 0x73000101:
return PUS_TM_FUNNEL_STRING;
case 0x73000102:
return CFDP_TM_FUNNEL_STRING;
case 0x73000205:
return CFDP_HANDLER_STRING;
case 0x73000206:
return CFDP_DISTRIBUTOR_STRING;
case 0x73000207:
return CFDP_FAULT_HANDLER_STRING;
case 0x73010000:
return EIVE_SYSTEM_STRING;
case 0x73010001:
return ACS_SUBSYSTEM_STRING;
case 0x73010002:
return PL_SUBSYSTEM_STRING;
case 0x73010003:
return TCS_SUBSYSTEM_STRING;
case 0x73010004:
return COM_SUBSYSTEM_STRING;
case 0x73010005:
return EPS_SUBSYSTEM_STRING;
case 0x73020001:
return MISC_TM_STORE_STRING;
case 0x73020002:
return OK_TM_STORE_STRING;
case 0x73020003:
return NOT_OK_TM_STORE_STRING;
case 0x73020004:
return HK_TM_STORE_STRING;
case 0x73030000:
return CFDP_TM_STORE_STRING;
case 0x73040000:
return LIVE_TM_TASK_STRING;
case 0x73040001:
return LOG_STORE_AND_TM_TASK_STRING;
case 0x73040002:
return HK_STORE_AND_TM_TASK_STRING;
case 0x73040003:
return CFDP_STORE_AND_TM_TASK_STRING;
case 0x73040004:
return DOWNLINK_RAM_STORE_STRING;
case 0x90000003:
return THERMAL_TEMP_INSERTER_STRING;
case 0xCAFECAFE:
return DUMMY_INTERFACE_STRING;
case 0xFFFFFFFF:
return NO_OBJECT_STRING;
default:
return "UNKNOWN_OBJECT";
}
return 0;
}

View File

@ -3,6 +3,6 @@
#include <fsfw/objectmanager/SystemObjectIF.h>
const char* translateObject(object_id_t object);
const char *translateObject(object_id_t object);
#endif /* FSFWCONFIG_OBJECTS_TRANSLATEOBJECTS_H_ */

View File

@ -0,0 +1 @@
target_sources(${OBSW_NAME} PRIVATE DummyPst.cpp)

View File

@ -0,0 +1,139 @@
#include "DummyPst.h"
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
#include <objects/systemObjectList.h>
ReturnValue_t dummy_pst::pst(FixedTimeslotTaskIF *thisSequence) {
uint32_t length = thisSequence->getPeriodMs();
thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::RW1, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::RW1, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::RW1, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::RW1, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::RW1, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::RW2, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::RW2, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::RW2, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::RW2, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::RW2, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::RW3, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::RW3, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::RW3, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::RW3, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::RW3, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::RW4, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::RW4, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::RW4, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::RW4, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::RW4, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::STAR_TRACKER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::STAR_TRACKER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::STAR_TRACKER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::STAR_TRACKER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::STAR_TRACKER, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::ACU_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::ACU_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::ACU_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::ACU_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::ACU_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
if (thisSequence->checkSequence() == returnvalue::OK) {
return returnvalue::OK;
} else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "pst::pollingSequenceInitDefault: Sequence invalid!" << std::endl;
#endif
return returnvalue::FAILED;
}
}

View File

@ -0,0 +1,14 @@
#ifndef POLLINGSEQUENCEFACTORY_H_
#define POLLINGSEQUENCEFACTORY_H_
#include <fsfw/returnvalues/returnvalue.h>
class FixedTimeslotTaskIF;
namespace dummy_pst {
ReturnValue_t pst(FixedTimeslotTaskIF *thisSequence);
}
#endif /* POLLINGSEQUENCEINIT_H_ */

View File

@ -1,9 +1,10 @@
#ifndef CONFIG_RETURNVALUES_CLASSIDS_H_
#define CONFIG_RETURNVALUES_CLASSIDS_H_
#include "commonClassIds.h"
#include <fsfw/returnvalues/FwClassIds.h>
#include "eive/resultClassIds.h"
/**
* Source IDs starts at 73 for now
* Framework IDs for ReturnValues run from 0 to 56
@ -11,9 +12,9 @@
*/
namespace CLASS_ID {
enum {
CLASS_ID_START = COMMON_CLASS_ID_END,
CLASS_ID_START = COMMON_CLASS_ID_END,
CLASS_ID_END // [EXPORT] : [END]
};
}
#endif /* CONFIG_RETURNVALUES_CLASSIDS_H_ */

View File

@ -1,19 +0,0 @@
#ifndef FSFWCONFIG_TMTC_APID_H_
#define FSFWCONFIG_TMTC_APID_H_
#include <stdint.h>
/**
* 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_ */

View File

@ -1,23 +0,0 @@
#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_ */

View File

@ -1,9 +1,17 @@
#include "InitMission.h"
#include <objects/systemObjectList.h>
#include <OBSWVersion.h>
#include <fsfw/tasks/TaskFactory.h>
#include <iostream>
#include "commonConfig.h"
#include "fsfw/FSFWVersion.h"
#include "fsfw/controller/ControllerBase.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/modes/ModeMessage.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/tasks/TaskFactory.h"
#include "scheduling.h"
#ifdef WIN32
static const char* COMPILE_PRINTOUT = "Windows";
#elif LINUX
@ -16,20 +24,21 @@ static const char* COMPILE_PRINTOUT = "unknown OS";
* Linux and Windows.
* @return
*/
int main(void)
{
std::cout << "-- EIVE OBSW --" << std::endl;
std::cout << "-- Compiled for " << COMPILE_PRINTOUT << " --" << std::endl;
std::cout << "-- Software version " << SW_NAME << " v" << SW_VERSION << "."
<< SW_SUBVERSION << "." << SW_SUBSUBVERSION << " -- " << std::endl;
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
int main(void) {
std::cout << "-- EIVE OBSW --" << std::endl;
std::cout << "-- Compiled for " << COMPILE_PRINTOUT << " --" << std::endl;
std::cout << "-- OBSW "
<< "v" << common::OBSW_VERSION << " | FSFW v" << fsfw::FSFW_VERSION << " --"
<< std::endl;
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
std::cout << "-- "
<< " BSP HOSTED"
<< " --" << std::endl;
initmission::initMission();
scheduling::initMission();
for(;;) {
// suspend main thread by sleeping it.
TaskFactory::delayTask(5000);
}
for (;;) {
// suspend main thread by sleeping it.
TaskFactory::delayTask(5000);
}
}

View File

@ -0,0 +1,124 @@
#include "objectFactory.h"
#include <fsfw/power/DummyPowerSwitcher.h>
#include <fsfw/tmtcservices/CommandingServiceBase.h>
#include <fsfw/tmtcservices/PusServiceBase.h>
#include <mission/controller/ThermalController.h>
#include <mission/genericFactory.h>
#include <mission/tmtc/TmFunnelHandler.h>
#include <objects/systemObjectList.h>
#include "../mission/utility/DummySdCardManager.h"
#include "OBSWConfig.h"
#include "fsfw/platform.h"
#include "fsfw/power/PowerSwitchIF.h"
#include "fsfw_tests/integration/task/TestTask.h"
#if OBSW_ADD_TMTC_UDP_SERVER == 1
#include "fsfw/osal/common/UdpTcPollingTask.h"
#include "fsfw/osal/common/UdpTmTcBridge.h"
#endif
#if OBSW_ADD_TMTC_TCP_SERVER == 1
#include "fsfw/osal/common/TcpTmTcBridge.h"
#include "fsfw/osal/common/TcpTmTcServer.h"
#endif
#if OBSW_ADD_TEST_CODE == 1
#include <test/testtasks/TestTask.h>
#endif
#include <dummies/AcuDummy.h>
#include <dummies/CoreControllerDummy.h>
#include "dummies/helperFactory.h"
#ifdef PLATFORM_UNIX
#include <fsfw_hal/linux/serial/SerialComIF.h>
#include <fsfw_hal/linux/serial/SerialCookie.h>
#include "devices/gpioIds.h"
#include "fsfw_hal/linux/gpio/Gpio.h"
#include "linux/payload/FreshSupvHandler.h"
#include "linux/payload/PlocSupvUartMan.h"
#include "test/gpio/DummyGpioIF.h"
#endif
void Factory::setStaticFrameworkObjectIds() {
PusServiceBase::PUS_DISTRIBUTOR = objects::PUS_PACKET_DISTRIBUTOR;
PusServiceBase::PACKET_DESTINATION = objects::PUS_TM_FUNNEL;
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::PUS_TM_FUNNEL;
VerificationReporter::DEFAULT_RECEIVER = objects::PUS_SERVICE_1_VERIFICATION;
}
void ObjectFactory::produce(void* args) {
Factory::setStaticFrameworkObjectIds();
PusTmFunnel* pusFunnel;
CfdpTmFunnel* cfdpFunnel;
StorageManagerIF* tmStore;
StorageManagerIF* ipcStore;
PersistentTmStores persistentStores{};
bool enableHkSets = false;
#if OBSW_ENABLE_PERIODIC_HK == 1
enableHkSets = true;
#endif
auto sdcMan = new DummySdCardManager("/tmp");
ObjectFactory::produceGenericObjects(nullptr, &pusFunnel, &cfdpFunnel, *sdcMan, &ipcStore,
&tmStore, persistentStores, 120, enableHkSets, false);
new TmFunnelHandler(objects::LIVE_TM_TASK, *pusFunnel, *cfdpFunnel);
auto* dummyGpioIF = new DummyGpioIF();
auto* dummySwitcher = new DummyPowerSwitcher(objects::PCDU_HANDLER, 18, 0);
std::vector<ReturnValue_t> switcherList;
auto initVal = PowerSwitchIF::SWITCH_OFF;
for (unsigned i = 0; i < 18; i++) {
switcherList.emplace_back(initVal);
}
dummySwitcher->setInitialSwitcherList(switcherList);
#ifdef PLATFORM_UNIX
// Obsolete dev handler..
/*
new SerialComIF(objects::UART_COM_IF);
#if OBSW_ADD_PLOC_MPSOC == 1
std::string mpscoDev = "";
auto mpsocCookie = new UartCookie(objects::PLOC_MPSOC_HANDLER, mpscoDev, uart::PLOC_MPSOC_BAUD,
mpsoc::MAX_REPLY_SIZE, UartModes::NON_CANONICAL);
mpsocCookie->setNoFixedSizeReply();
auto plocMpsocHelper = new PlocMpsocSpecialComHelper(objects::PLOC_MPSOC_HELPER);
new PlocMpsocHandler(objects::PLOC_MPSOC_HANDLER, objects::UART_COM_IF, mpsocCookie,
plocMpsocHelper, Gpio(gpioIds::ENABLE_MPSOC_UART, dummyGpioIF),
objects::PLOC_SUPERVISOR_HANDLER);
#endif // OBSW_ADD_PLOC_MPSOC == 1
*/
#if OBSW_ADD_PLOC_SUPERVISOR == 1
std::string plocSupvString = "/dev/ploc_supv";
auto supervisorCookie =
new SerialCookie(objects::PLOC_SUPERVISOR_HANDLER, plocSupvString, uart::PLOC_SUPV_BAUD,
supv::MAX_PACKET_SIZE * 20, UartModes::NON_CANONICAL);
supervisorCookie->setNoFixedSizeReply();
new PlocSupvUartManager(objects::PLOC_SUPERVISOR_HELPER);
DhbConfig dhbConf(objects::PLOC_SUPERVISOR_HANDLER);
auto* supvHandler =
new FreshSupvHandler(dhbConf, supervisorCookie, Gpio(gpioIds::ENABLE_SUPV_UART, dummyGpioIF),
dummySwitcher, power::PDU1_CH6_PLOC_12V);
#endif /* OBSW_ADD_PLOC_SUPERVISOR == 1 */
#endif
dummy::DummyCfg cfg;
cfg.addPlPcduDummy = true;
cfg.addCamSwitcherDummy = true;
dummy::createDummies(cfg, *dummySwitcher, dummyGpioIF, enableHkSets);
HeaterHandler* heaterHandler = nullptr;
// new ThermalController(objects::THERMAL_CONTROLLER);
ObjectFactory::createGenericHeaterComponents(*dummyGpioIF, *dummySwitcher, heaterHandler);
if (heaterHandler == nullptr) {
sif::error << "HeaterHandler could not be created" << std::endl;
} else {
ObjectFactory::createThermalController(*heaterHandler, true);
}
new TestTask(objects::TEST_TASK);
}

View File

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

280
bsp_hosted/scheduling.cpp Normal file
View File

@ -0,0 +1,280 @@
#include "linux/scheduling.h"
#include <bsp_hosted/fsfwconfig/pollingsequence/DummyPst.h>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/objectmanager/ObjectManagerIF.h>
#include <fsfw/returnvalues/returnvalue.h>
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
#include <fsfw/tasks/PeriodicTaskIF.h>
#include <fsfw/tasks/TaskFactory.h>
#include <mission/utility/InitMission.h>
#include <iostream>
#include "OBSWConfig.h"
#include "mission/scheduling.h"
#include "objectFactory.h"
#include "scheduling.h"
#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 scheduling::initMission() {
sif::info << "Building global objects.." << std::endl;
/* Instantiate global object manager and also create all objects */
ObjectManager::instance()->setObjectFactoryFunction(ObjectFactory::produce, nullptr);
sif::info << "Initializing all objects.." << std::endl;
ObjectManager::instance()->initialize();
/* This function creates and starts all tasks */
initTasks();
}
void scheduling::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", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
ReturnValue_t result = tmtcDistributor->addComponent(objects::CCSDS_PACKET_DISTRIBUTOR);
if (result != returnvalue::OK) {
sif::error << "Adding CCSDS distributor failed" << std::endl;
}
result = tmtcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR);
if (result != returnvalue::OK) {
sif::error << "Adding PUS distributor failed" << std::endl;
}
result = tmtcDistributor->addComponent(objects::CFDP_DISTRIBUTOR);
if (result != returnvalue::OK) {
sif::error << "Adding CFDP distributor failed" << std::endl;
}
#if OBSW_ADD_TMTC_UDP_SERVER == 1
result = tmtcDistributor->addComponent(objects::UDP_TMTC_SERVER);
if (result != returnvalue::OK) {
sif::error << "adding UDP server failed" << std::endl;
}
#endif
result = tmtcDistributor->addComponent(objects::TCP_TMTC_SERVER);
if (result != returnvalue::OK) {
sif::error << "adding TCP server failed" << std::endl;
}
#if OBSW_ADD_TMTC_UDP_SERVER == 1
PeriodicTaskIF* udpPollingTask = factory->createPeriodicTask(
"UDP_POLLING", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = udpPollingTask->addComponent(objects::UDP_TMTC_POLLING_TASK);
if (result != returnvalue::OK) {
sif::error << "Add component UDP Polling failed" << std::endl;
}
#endif
PeriodicTaskIF* tcpPollingTask = factory->createPeriodicTask(
"TCP_POLLING", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = tcpPollingTask->addComponent(objects::TCP_TMTC_POLLING_TASK);
if (result != returnvalue::OK) {
sif::error << "Add component UDP Polling failed" << std::endl;
}
PeriodicTaskIF* liveTmTask = factory->createPeriodicTask(
"LIVE_TM", 55, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, nullptr, &RR_SCHEDULING);
result = liveTmTask->addComponent(objects::LIVE_TM_TASK);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("LIVE_TM", objects::LIVE_TM_TASK);
}
PeriodicTaskIF* pusHighPrio = factory->createPeriodicTask(
"PUS_HIGH_PRIO", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
if (result != returnvalue::OK) {
sif::error << "Object add component failed" << std::endl;
}
result = pusHighPrio->addComponent(objects::EVENT_MANAGER);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("EVENT_MGMT", objects::EVENT_MANAGER);
}
result = pusHighPrio->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS5", objects::PUS_SERVICE_5_EVENT_REPORTING);
}
result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS9", objects::PUS_SERVICE_9_TIME_MGMT);
}
PeriodicTaskIF* pusMedPrio = factory->createPeriodicTask(
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
}
result = pusHighPrio->addComponent(objects::PUS_SERVICE_3_HOUSEKEEPING);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS3", objects::PUS_SERVICE_3_HOUSEKEEPING);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS8", objects::PUS_SERVICE_8_FUNCTION_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_15_TM_STORAGE);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS15", objects::PUS_SERVICE_15_TM_STORAGE);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS200", objects::PUS_SERVICE_200_MODE_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_20_PARAMETERS);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS20", objects::PUS_SERVICE_20_PARAMETERS);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_17_TEST);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS17", objects::PUS_SERVICE_17_TEST);
}
PeriodicTaskIF* thermalTask = factory->createPeriodicTask(
"THERMAL_CTL_TASK", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, missedDeadlineFunc);
result = thermalTask->addComponent(objects::CORE_CONTROLLER);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("CORE_CTRL", objects::CORE_CONTROLLER);
}
result = thermalTask->addComponent(objects::THERMAL_CONTROLLER);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("THERMAL_CONTROLLER", objects::THERMAL_CONTROLLER);
}
result = thermalTask->addComponent(objects::HEATER_HANDLER);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
}
FixedTimeslotTaskIF* pstTask = factory->createFixedTimeslotTask(
"DUMMY_PST", 75, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.5, missedDeadlineFunc);
result = dummy_pst::pst(pstTask);
if (result != returnvalue::OK) {
sif::error << "Failed to add dummy pst to fixed timeslot task" << std::endl;
}
#if OBSW_ADD_CFDP_COMPONENTS == 1
PeriodicTaskIF* cfdpTask = factory->createPeriodicTask(
"CFDP Handler", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc);
result = cfdpTask->addComponent(objects::CFDP_HANDLER);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("CFDP Handler", objects::CFDP_HANDLER);
}
#endif
// If those are added at a later stage..
/*
PeriodicTaskIF* logTmTask = factory->createPeriodicTask(
"LOG_PSTORE", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr);
result = logTmTask->addComponent(objects::LOG_STORE_AND_TM_TASK);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("LOG_STORE_AND_TM", objects::LOG_STORE_AND_TM_TASK);
}
PeriodicTaskIF* hkTmTask =
factory->createPeriodicTask("HK_PSTORE", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr);
result = hkTmTask->addComponent(objects::HK_STORE_AND_TM_TASK);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("HK_STORE_AND_TM", objects::HK_STORE_AND_TM_TASK);
}
PeriodicTaskIF* cfdpTmTask = factory->createPeriodicTask(
"CFDP_PSTORE", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr);
result = cfdpTmTask->addComponent(objects::CFDP_STORE_AND_TM_TASK);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("CFDP_STORE_AND_TM", objects::CFDP_STORE_AND_TM_TASK);
}
*/
#if OBSW_ADD_PLOC_SUPERVISOR == 1
PeriodicTaskIF* supvHelperTask = factory->createPeriodicTask(
"PLOC_SUPV_HELPER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, missedDeadlineFunc);
result = supvHelperTask->addComponent(objects::PLOC_SUPERVISOR_HELPER);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PLOC_SUPV_HELPER", objects::PLOC_SUPERVISOR_HELPER);
}
#endif /* OBSW_ADD_PLOC_SUPERVISOR */
PeriodicTaskIF* plTask = factory->createPeriodicTask(
"PL_TASK", 25, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, missedDeadlineFunc);
scheduling::addMpsocSupvHandlers(plTask);
#if OBSW_ADD_TEST_CODE == 1
result = testTask->addComponent(objects::TEST_TASK);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("TEST_TASK", objects::TEST_TASK);
}
#endif /* OBSW_ADD_TEST_CODE == 1 */
PeriodicTaskIF* dummyTask = factory->createPeriodicTask(
"DUMMY_TASK", 35, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
dummyTask->addComponent(objects::THERMAL_TEMP_INSERTER);
scheduling::scheduleTmpTempSensors(dummyTask, true);
scheduling::scheduleRtdSensors(dummyTask);
dummyTask->addComponent(objects::SUS_0_N_LOC_XFYFZM_PT_XF);
dummyTask->addComponent(objects::SUS_1_N_LOC_XBYFZM_PT_XB);
dummyTask->addComponent(objects::SUS_2_N_LOC_XFYBZB_PT_YB);
dummyTask->addComponent(objects::SUS_3_N_LOC_XFYBZF_PT_YF);
dummyTask->addComponent(objects::SUS_4_N_LOC_XMYFZF_PT_ZF);
dummyTask->addComponent(objects::SUS_5_N_LOC_XFYMZB_PT_ZB);
dummyTask->addComponent(objects::SUS_6_R_LOC_XFYBZM_PT_XF);
dummyTask->addComponent(objects::SUS_7_R_LOC_XBYBZM_PT_XB);
dummyTask->addComponent(objects::SUS_8_R_LOC_XBYBZB_PT_YB);
dummyTask->addComponent(objects::SUS_9_R_LOC_XBYBZB_PT_YF);
dummyTask->addComponent(objects::SUS_10_N_LOC_XMYBZF_PT_ZF);
dummyTask->addComponent(objects::SUS_11_R_LOC_XBYMZB_PT_ZB);
sif::info << "Starting tasks.." << std::endl;
tmtcDistributor->startTask();
#if OBSW_ADD_TMTC_UDP_SERVER == 1
udpPollingTask->startTask();
#endif
tcpPollingTask->startTask();
liveTmTask->startTask();
pusHighPrio->startTask();
pusMedPrio->startTask();
pstTask->startTask();
thermalTask->startTask();
dummyTask->startTask();
// If those are added at a later stage..
// logTmTask->startTask();
// cfdpTmTask->startTask();
// hkTmTask->startTask();
#if OBSW_ADD_PLOC_SUPERVISOR == 1
supvHelperTask->startTask();
#endif
#if OBSW_ADD_PLOC_SUPERVISOR == 1 || OBSW_ADD_PLOC_MPSOC == 1
plTask->startTask();
#endif
#if OBSW_ADD_CFDP_COMPONENTS == 1
cfdpTask->startTask();
#endif
#if OBSW_ADD_TEST_CODE == 1
testTask->startTask();
#endif /* OBSW_ADD_TEST_CODE == 1 */
sif::info << "Tasks started.." << std::endl;
}

6
bsp_hosted/scheduling.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
namespace scheduling {
void initMission();
void initTasks();
}; // namespace scheduling

View File

@ -1,8 +1,6 @@
target_sources(${TARGET_NAME} PUBLIC
InitMission.cpp
main.cpp
ObjectFactory.cpp
)
target_sources(${OBSW_NAME} PUBLIC InitMission.cpp main.cpp gpioInit.cpp
ObjectFactory.cpp)
add_subdirectory(boardconfig)
add_subdirectory(boardtest)
add_subdirectory(fsfwconfig)

View File

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

View File

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

View File

@ -0,0 +1,129 @@
/**
* @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 FSFWCONFIG_OBSWCONFIG_H_
#define FSFWCONFIG_OBSWCONFIG_H_
#include "commonConfig.h"
#include "OBSWVersion.h"
/*******************************************************************/
/** All of the following flags should be enabled for mission code */
/*******************************************************************/
#define OBSW_ENABLE_TIMERS 1
#define OBSW_ADD_STAR_TRACKER 0
#define OBSW_ADD_PLOC_SUPERVISOR 0
#define OBSW_ADD_PLOC_MPSOC 0
#define OBSW_ADD_SUN_SENSORS 0
#define OBSW_ADD_MGT 0
#define OBSW_ADD_ACS_BOARD 0
#define OBSW_ADD_ACS_HANDLERS 0
#define OBSW_ADD_GPS_0 0
#define OBSW_ADD_GPS_1 0
#define OBSW_ADD_RW 0
#define OBSW_ADD_BPX_BATTERY_HANDLER 0
#define OBSW_ADD_RTD_DEVICES 0
#define OBSW_ADD_PL_PCDU 0
#define OBSW_ADD_TMP_DEVICES 0
#define OBSW_ADD_SCEX_DEVICE 1
#define OBSW_ADD_RAD_SENSORS 0
#define OBSW_ADD_SYRLINKS 0
#define OBSW_STAR_TRACKER_GROUND_CONFIG 1
// This is a really tricky switch.. It initializes the PCDU switches to their default states
// at powerup. I think it would be better
// to leave it off for now. It makes testing a lot more difficult and it might mess with
// something the operators might want to do by giving the software too much intelligence
// at the wrong place. The system component might command all the Switches accordingly anyway
#define OBSW_INITIALIZE_SWITCHES 0
#define OBSW_ENABLE_PERIODIC_HK 0
/*******************************************************************/
/** All of the following flags should be disabled for mission code */
/*******************************************************************/
// Can be used to switch device to NORMAL mode immediately
#define OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP 1
#define OBSW_PRINT_MISSED_DEADLINES 1
#define OBSW_SYRLINKS_SIMULATED 1
#define OBSW_ADD_TEST_CODE 0
#define OBSW_ADD_TEST_TASK 0
#define OBSW_ADD_TEST_PST 0
// If this is enabled, all other SPI code should be disabled
#define OBSW_ADD_SPI_TEST_CODE 0
// If this is enabled, all other I2C code should be disabled
#define OBSW_ADD_I2C_TEST_CODE 0
#define OBSW_ADD_UART_TEST_CODE 0
#define OBSW_TEST_ACS 0
#define OBSW_DEBUG_ACS 0
#define OBSW_TEST_SUS 0
#define OBSW_DEBUG_SUS 0
#define OBSW_TEST_RTD 0
#define OBSW_DEBUG_RTD 0
#define OBSW_TEST_RAD_SENSOR 0
#define OBSW_DEBUG_RAD_SENSOR 0
#define OBSW_TEST_PL_PCDU 0
#define OBSW_DEBUG_PL_PCDU 0
#define OBSW_TEST_BPX_BATT 0
#define OBSW_DEBUG_BPX_BATT 0
#define OBSW_TEST_IMTQ 0
#define OBSW_DEBUG_IMTQ 0
#define OBSW_TEST_RW 0
#define OBSW_DEBUG_RW 0
#define OBSW_TEST_LIBGPIOD 0
#define OBSW_TEST_PLOC_HANDLER 0
#define OBSW_TEST_CCSDS_BRIDGE 0
#define OBSW_TEST_CCSDS_PTME 0
#define OBSW_TEST_TE7020_HEATER 0
#define OBSW_TEST_GPIO_OPEN_BY_LABEL 0
#define OBSW_TEST_GPIO_OPEN_BY_LINE_NAME 0
#define OBSW_DEBUG_P60DOCK 0
#define OBSW_PRINT_CORE_HK 0
#define OBSW_DEBUG_PDU1 0
#define OBSW_DEBUG_PDU2 0
#define OBSW_DEBUG_GPS 0
#define OBSW_DEBUG_ACU 0
#define OBSW_DEBUG_SYRLINKS 0
#define OBSW_DEBUG_PDEC_HANDLER 0
#define OBSW_DEBUG_PLOC_SUPERVISOR 0
#define OBSW_DEBUG_PLOC_MPSOC 0
#define OBSW_DEBUG_STARTRACKER 0
#define OBSW_TCP_SERVER_WIRETAPPING 0
/*******************************************************************/
/** CMake Defines */
/*******************************************************************/
#cmakedefine EIVE_BUILD_GPSD_GPS_HANDLER
#define OBSW_ADD_CCSDS_IP_CORES 0
// Set to 1 if all telemetry should be sent to the PTME IP Core
#define OBSW_TM_TO_PTME 0
// Set to 1 if telecommands are received via the PDEC IP Core
#define OBSW_TC_FROM_PDEC 0
#cmakedefine LIBGPS_VERSION_MAJOR @LIBGPS_VERSION_MAJOR@
#cmakedefine LIBGPS_VERSION_MINOR @LIBGPS_VERSION_MINOR@
#ifdef RASPBERRY_PI
#include "rpiConfig.h"
#elif defined(XIPHOS_Q7S)
#include "q7sConfig.h"
#endif
#ifdef __cplusplus
#include "objects/systemObjectList.h"
#include "events/subsystemIdRanges.h"
#include "returnvalues/classIds.h"
#endif
#endif /* FSFWCONFIG_OBSWCONFIG_H_ */

View File

@ -1,149 +1,248 @@
#include "ObjectFactory.h"
#include "objects/systemObjectList.h"
#include <bsp_linux_board/RPiSdCardManager.h>
#include <linux/devices/ScexUartReader.h>
#include "OBSWConfig.h"
#include "devConf.h"
#include "devices/addresses.h"
#include "devices/gpioIds.h"
#include "OBSWConfig.h"
#include "tmtc/apid.h"
#include "tmtc/pusIds.h"
#include "spiConf.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/power/DummyPowerSwitcher.h"
#include "fsfw/tasks/TaskFactory.h"
#include "fsfw/tmtcpacket/pus/tm.h"
#include "fsfw/tmtcservices/CommandingServiceBase.h"
#include "fsfw/tmtcservices/PusServiceBase.h"
#include "gpioInit.h"
#include "linux/ObjectFactory.h"
#include "linux/boardtest/LibgpiodTest.h"
#include "linux/boardtest/SpiTestClass.h"
#include "linux/boardtest/UartTestClass.h"
#include "mission/core/GenericFactory.h"
#include "mission/utility/TmFunnel.h"
#include "mission/devices/MGMHandlerLIS3MDL.h"
#include "mission/devices/MGMHandlerRM3100.h"
#include "mission/devices/GyroADIS16507Handler.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/tmtcservices/CommandingServiceBase.h"
#include "fsfw/tmtcservices/PusServiceBase.h"
#include "fsfw/tmtcpacket/pus/tm.h"
#include "fsfw/tasks/TaskFactory.h"
#include "mission/devices/GPSHyperionHandler.h"
#include "mission/devices/GyroADIS1650XHandler.h"
#include "mission/tmtc/TmFunnel.h"
#include "objects/systemObjectList.h"
#include "tmtc/pusIds.h"
/* UDP server includes */
#include "fsfw/osal/common/UdpTmTcBridge.h"
#if OBSW_USE_TMTC_TCP_BRIDGE == 1
#include <fsfw/src/fsfw/osal/common/TcpTmTcBridge.h>
#include <fsfw/src/fsfw/osal/common/TcpTmTcServer.h>
#else
#include "fsfw/osal/common/UdpTcPollingTask.h"
#include "fsfw_hal/devicehandlers/GyroL3GD20Handler.h"
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
#include "fsfw_hal/linux/rpi/GpioRPi.h"
#include "fsfw_hal/common/gpio/GpioCookie.h"
#include "fsfw_hal/linux/spi/SpiCookie.h"
#include "fsfw_hal/linux/spi/SpiComIF.h"
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;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
}
void ObjectFactory::produce(void* args){
Factory::setStaticFrameworkObjectIds();
ObjectFactory::produceGenericObjects();
new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR);
new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
GpioIF* gpioIF = new LinuxLibgpioIF(objects::GPIO_IF);
GpioCookie* gpioCookie = nullptr;
static_cast<void>(gpioCookie);
#if RPI_ADD_SPI_TEST == 1
new SpiTestClass(objects::SPI_TEST, gpioIF);
#include "fsfw/osal/common/UdpTmTcBridge.h"
#endif
#if RPI_ADD_UART_TEST == 1
new UartTestClass(objects::UART_TEST);
#include <fsfw_hal/linux/serial/SerialComIF.h>
#include <fsfw_hal/linux/serial/SerialCookie.h>
#include "fsfw_hal/common/gpio/GpioCookie.h"
#include "fsfw_hal/devicehandlers/GyroL3GD20Handler.h"
#include "fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h"
#include "fsfw_hal/devicehandlers/MgmRM3100Handler.h"
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
#include "fsfw_hal/linux/rpi/GpioRPi.h"
#include "fsfw_hal/linux/spi/SpiComIF.h"
#include "fsfw_hal/linux/spi/SpiCookie.h"
void Factory::setStaticFrameworkObjectIds() {
PusServiceBase::PUS_DISTRIBUTOR = objects::PUS_PACKET_DISTRIBUTOR;
PusServiceBase::PACKET_DESTINATION = objects::TM_FUNNEL;
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
// No storage object for now.
TmFunnel::storageDestination = objects::NO_OBJECT;
}
void ObjectFactory::produce(void* args) {
Factory::setStaticFrameworkObjectIds();
ObjectFactory::produceGenericObjects();
GpioIF* gpioIF = new LinuxLibgpioIF(objects::GPIO_IF);
GpioCookie* gpioCookie = nullptr;
static_cast<void>(gpioCookie);
SpiComIF* spiComIF = new SpiComIF(objects::SPI_MAIN_COM_IF, spi::DEV, gpioIF);
static_cast<void>(spiComIF);
auto pwrSwitcher = new DummyPowerSwitcher(objects::PCDU_HANDLER, 18, 0);
static_cast<void>(pwrSwitcher);
#if OBSW_ADD_ACS_BOARD == 1 && defined(RASPBERRY_PI)
createRpiAcsBoard(gpioIF, spiDev);
#endif
#if OBSW_ADD_SUN_SENSORS == 1 || OBSW_ADD_RTD_DEVICES == 1
#ifdef RASPBERRY_PI
rpi::gpio::initSpiCsDecoder(gpioIF);
#endif
#endif
#if OBSW_ADD_SCEX_DEVICE == 1
auto* sdcMan = new DummySdCardManager("/tmp");
createScexComponents(uart::DEV, pwrSwitcher, *sdcMan, true, std::nullopt);
#endif
#if OBSW_ADD_SUN_SENSORS == 1
createSunSensorComponents(gpioIF, spiComIF, pwrSwitcher, spi::DEV);
#endif
#if OBSW_ADD_RTD_DEVICES == 1
createRtdComponents(spi::DEV, gpioIF, pwrSwitcher);
#endif
#if OBSW_ADD_TEST_CODE == 1
createTestTasks();
#endif /* OBSW_ADD_TEST_CODE == 1 */
}
void ObjectFactory::createRpiAcsBoard(GpioIF* gpioIF, std::string spiDev) {
GpioCookie* gpioCookie = new GpioCookie();
// TODO: Missing pin for Gyro 2
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_0_LIS3_CS, gpio::MGM_0_BCM_PIN, "MGM_0_LIS3",
gpio::Direction::OUT, gpio::Levels::HIGH);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_1_RM3100_CS, gpio::MGM_1_BCM_PIN,
"MGM_1_RM3100", gpio::Direction::OUT, gpio::Levels::HIGH);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_2_LIS3_CS, gpio::MGM_2_BCM_PIN, "MGM_2_LIS3",
gpio::Direction::OUT, gpio::Levels::HIGH);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_3_RM3100_CS, gpio::MGM_3_BCM_PIN,
"MGM_3_RM3100", gpio::Direction::OUT, gpio::Levels::HIGH);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_0_ADIS_CS, gpio::GYRO_0_BCM_PIN,
"GYRO_0_ADIS", gpio::Direction::OUT, gpio::Levels::HIGH);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_1_L3G_CS, gpio::GYRO_1_BCM_PIN, "GYRO_1_L3G",
gpio::Direction::OUT, gpio::Levels::HIGH);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_2_ADIS_CS, gpio::GYRO_2_BCM_PIN,
"GYRO_2_ADIS", gpio::Direction::OUT, gpio::Levels::HIGH);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_3_L3G_CS, gpio::GYRO_3_BCM_PIN, "GYRO_3_L3G",
gpio::Direction::OUT, gpio::Levels::HIGH);
gpioIF->addGpios(gpioCookie);
SpiCookie* spiCookie =
new SpiCookie(addresses::MGM_0_LIS3, gpioIds::MGM_0_LIS3_CS, MGMLIS3MDL::MAX_BUFFER_SIZE,
spi::DEFAULT_LIS3_MODE, spi::DEFAULT_LIS3_SPEED);
auto mgmLis3Handler =
new MgmLIS3MDLHandler(objects::MGM_0_LIS3_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie, 0);
mgmLis3Handler->setStartUpImmediately();
#if OBSW_TEST_ACS == 1
mgmLis3Handler->setToGoToNormalMode(true);
#endif
spiCookie =
new SpiCookie(addresses::MGM_1_RM3100, gpioIds::MGM_1_RM3100_CS, RM3100::MAX_BUFFER_SIZE,
spi::DEFAULT_RM3100_MODE, spi::DEFAULT_RM3100_SPEED);
auto mgmRm3100Handler =
new MgmRM3100Handler(objects::MGM_1_RM3100_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie, 0);
mgmRm3100Handler->setStartUpImmediately();
#if OBSW_TEST_ACS == 1
mgmRm3100Handler->setToGoToNormalMode(true);
#endif
spiCookie =
new SpiCookie(addresses::MGM_2_LIS3, gpioIds::MGM_2_LIS3_CS, MGMLIS3MDL::MAX_BUFFER_SIZE,
spi::DEFAULT_LIS3_MODE, spi::DEFAULT_LIS3_SPEED);
mgmLis3Handler =
new MgmLIS3MDLHandler(objects::MGM_2_LIS3_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie, 0);
mgmLis3Handler->setStartUpImmediately();
#if OBSW_TEST_ACS == 1
mgmLis3Handler->setToGoToNormalMode(true);
#endif
spiCookie =
new SpiCookie(addresses::MGM_3_RM3100, gpioIds::MGM_3_RM3100_CS, RM3100::MAX_BUFFER_SIZE,
spi::DEFAULT_RM3100_MODE, spi::DEFAULT_RM3100_SPEED);
mgmRm3100Handler =
new MgmRM3100Handler(objects::MGM_3_RM3100_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie, 0);
mgmRm3100Handler->setStartUpImmediately();
#if OBSW_TEST_ACS == 1
mgmRm3100Handler->setToGoToNormalMode(true);
#endif
spiCookie =
new SpiCookie(addresses::GYRO_0_ADIS, gpioIds::GYRO_0_ADIS_CS, ADIS1650X::MAXIMUM_REPLY_SIZE,
spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
auto adisHandler =
new GyroADIS1650XHandler(objects::GYRO_0_ADIS_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie,
ADIS1650X::Type::ADIS16505);
adisHandler->setStartUpImmediately();
spiCookie = new SpiCookie(addresses::GYRO_1_L3G, gpioIds::GYRO_1_L3G_CS, L3GD20H::MAX_BUFFER_SIZE,
spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
auto gyroL3gHandler =
new GyroHandlerL3GD20H(objects::GYRO_1_L3G_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie, 0);
gyroL3gHandler->setStartUpImmediately();
#if OBSW_TEST_ACS == 1
gyroL3gHandler->setToGoToNormalMode(true);
#endif
spiCookie =
new SpiCookie(addresses::GYRO_2_ADIS, gpioIds::GYRO_2_ADIS_CS, ADIS1650X::MAXIMUM_REPLY_SIZE,
spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
adisHandler = new GyroADIS1650XHandler(objects::GYRO_2_ADIS_HANDLER, objects::SPI_MAIN_COM_IF,
spiCookie, ADIS1650X::Type::ADIS16505);
adisHandler->setStartUpImmediately();
spiCookie = new SpiCookie(addresses::GYRO_3_L3G, gpioIds::GYRO_3_L3G_CS, L3GD20H::MAX_BUFFER_SIZE,
spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
gyroL3gHandler =
new GyroHandlerL3GD20H(objects::GYRO_3_L3G_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie, 0);
gyroL3gHandler->setStartUpImmediately();
#if OBSW_TEST_ACS == 1
gyroL3gHandler->setToGoToNormalMode(true);
#endif
}
void ObjectFactory::createTestTasks() {
new TestTask(objects::TEST_TASK);
#if OBSW_ADD_SPI_TEST_CODE == 1
new SpiTestClass(objects::SPI_TEST, gpioIF);
#endif
#if OBSW_ADD_UART_TEST_CODE == 1
new UartTestClass(objects::UART_TEST);
#else
newSerialComIF(objects::UART_COM_IF);
#endif
#if RPI_LOOPBACK_TEST_GPIO == 1
GpioCookie* gpioCookieLoopback = new GpioCookie();
/* Loopback pins. Adapt according to setup */
gpioId_t gpioIdSender = gpioIds::TEST_ID_0;
int bcmPinSender = 26;
gpioId_t gpioIdReader = gpioIds::TEST_ID_1;
int bcmPinReader = 16;
gpio::createRpiGpioConfig(gpioCookieLoopback, gpioIdSender, bcmPinSender, "GPIO_LB_SENDER",
gpio::Direction::OUT, 0);
gpio::createRpiGpioConfig(gpioCookieLoopback, gpioIdReader, bcmPinReader, "GPIO_LB_READER",
gpio::Direction::IN, 0);
new LibgpiodTest(objects::LIBGPIOD_TEST, objects::GPIO_IF, gpioCookieLoopback);
GpioCookie* gpioCookieLoopback = new GpioCookie();
/* Loopback pins. Adapt according to setup */
gpioId_t gpioIdSender = gpioIds::TEST_ID_0;
int bcmPinSender = 26;
gpioId_t gpioIdReader = gpioIds::TEST_ID_1;
int bcmPinReader = 16;
gpio::createRpiGpioConfig(gpioCookieLoopback, gpioIdSender, bcmPinSender, "GPIO_LB_SENDER",
gpio::Direction::OUT, 0);
gpio::createRpiGpioConfig(gpioCookieLoopback, gpioIdReader, bcmPinReader, "GPIO_LB_READER",
gpio::Direction::IN, 0);
new LibgpiodTest(objects::LIBGPIOD_TEST, objects::GPIO_IF, gpioCookieLoopback);
#endif /* RPI_LOOPBACK_TEST_GPIO == 1 */
new SpiComIF(objects::SPI_COM_IF, gpioIF);
std::string spiDev;
SpiCookie* spiCookie = nullptr;
static_cast<void>(spiCookie);
#if RPI_TEST_ACS_BOARD == 1
if(gpioCookie == nullptr) {
gpioCookie = new GpioCookie();
}
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_0_LIS3_CS, gpio::MGM_0_BCM_PIN,
"MGM_0_LIS3", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_1_RM3100_CS, gpio::MGM_1_BCM_PIN,
"MGM_1_RM3100", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_2_LIS3_CS, gpio::MGM_2_BCM_PIN,
"MGM_2_LIS3", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::MGM_3_RM3100_CS, gpio::MGM_3_BCM_PIN,
"MGM_3_RM3100", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_0_ADIS_CS, gpio::GYRO_0_BCM_PIN,
"GYRO_0_ADIS", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_1_L3G_CS, gpio::GYRO_1_BCM_PIN,
"GYRO_1_L3G", gpio::Direction::OUT, 1);
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_2_L3G_CS, gpio::GYRO_2_BCM_PIN,
"GYRO_2_L3G", gpio::Direction::OUT, 1);
gpioIF->addGpios(gpioCookie);
spiDev = "/dev/spidev0.0";
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 */
#if RPI_TEST_ADIS16507 == 1
if(gpioCookie == nullptr) {
gpioCookie = new GpioCookie();
}
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_0_ADIS_CS, gpio::GYRO_0_BCM_PIN,
"GYRO_0_ADIS", gpio::Direction::OUT, 1);
gpioIF->addGpios(gpioCookie);
if (gpioCookie == nullptr) {
gpioCookie = new GpioCookie();
}
gpio::createRpiGpioConfig(gpioCookie, gpioIds::GYRO_0_ADIS_CS, gpio::GYRO_0_BCM_PIN,
"GYRO_0_ADIS", gpio::Direction::OUT, 1);
gpioIF->addGpios(gpioCookie);
spiDev = "/dev/spidev0.0";
spiCookie = new SpiCookie(addresses::GYRO_0_ADIS, gpioIds::GYRO_0_ADIS_CS, spiDev,
ADIS16507::MAXIMUM_REPLY_SIZE, spi::DEFAULT_ADIS16507_MODE, spi::DEFAULT_ADIS16507_SPEED,
nullptr, nullptr);
auto adisGyroHandler = new GyroADIS16507Handler(objects::GYRO_0_ADIS_HANDLER, objects::SPI_COM_IF, spiCookie);
adisGyroHandler->setStartUpImmediately();
spiDev = "/dev/spidev0.1";
spiCookie = new SpiCookie(addresses::GYRO_0_ADIS, gpioIds::GYRO_0_ADIS_CS, spiDev,
ADIS16507::MAXIMUM_REPLY_SIZE, spi::DEFAULT_ADIS16507_MODE,
spi::DEFAULT_ADIS16507_SPEED, nullptr, nullptr);
auto adisGyroHandler =
new GyroADIS16507Handler(objects::GYRO_0_ADIS_HANDLER, objects::SPI_COM_IF, spiCookie);
adisGyroHandler->setStartUpImmediately();
#endif /* RPI_TEST_ADIS16507 == 1 */
#if RPI_TEST_GPS_HANDLER == 1
UartCookie* uartCookie =
new UartCookie(objects::GPS0_HANDLER, "/dev/serial0", UartModes::CANONICAL, 9600, 1024);
uartCookie->setToFlushInput(true);
uartCookie->setReadCycles(6);
GPSHyperionHandler* gpsHandler =
new GPSHyperionHandler(objects::GPS0_HANDLER, objects::UART_COM_IF, uartCookie, false);
gpsHandler->setStartUpImmediately();
#endif
}

View File

@ -1,10 +1,16 @@
#ifndef BSP_LINUX_OBJECTFACTORY_H_
#define BSP_LINUX_OBJECTFACTORY_H_
#include <string>
class GpioIF;
namespace ObjectFactory {
void setStatics();
void produce(void* args);
};
void setStatics();
void produce(void* args);
void createRpiAcsBoard(GpioIF* gpioIF, std::string spiDev);
void createTestTasks();
}; // namespace ObjectFactory
#endif /* BSP_LINUX_OBJECTFACTORY_H_ */

View File

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

View File

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

View File

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

View File

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

View File

@ -7,6 +7,7 @@
#define RPI_LOOPBACK_TEST_GPIO 0
#define RPI_TEST_ADIS16507 0
#define RPI_TEST_GPS_HANDLER 0
// Only one of those 2 should be enabled!
#define RPI_ADD_SPI_TEST 0
@ -14,20 +15,6 @@
#define RPI_TEST_ACS_BOARD 0
#endif
#define RPI_ADD_UART_TEST 1
#if RPI_ADD_UART_TEST == 1
#define RPI_TEST_GPS_DEVICE 0
#endif
/* 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;
}
#define RPI_ADD_UART_TEST 0
#endif /* BSP_RPI_BOARDCONFIG_RPI_CONFIG_H_ */

View File

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

View File

@ -0,0 +1,43 @@
#ifndef BSP_LINUX_BOARD_DEFINITIONS_H_
#define BSP_LINUX_BOARD_DEFINITIONS_H_
#include <cstdint>
#include "OBSWConfig.h"
#ifdef RASPBERRY_PI
namespace spi {
static constexpr char DEV[] = "/dev/spidev0.1";
}
namespace uart {
static constexpr char DEV[] = "/dev/serial0";
}
/* Adapt these values accordingly */
namespace gpio {
static constexpr uint8_t MGM_0_BCM_PIN = 17;
static constexpr uint8_t MGM_1_BCM_PIN = 27;
static constexpr uint8_t MGM_2_BCM_PIN = 22;
static constexpr uint8_t MGM_3_BCM_PIN = 23;
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 = 13;
static constexpr uint8_t GYRO_3_BCM_PIN = 19;
static constexpr uint8_t SPI_MUX_0_BCM = 17;
static constexpr uint8_t SPI_MUX_1_BCM = 27;
static constexpr uint8_t SPI_MUX_2_BCM = 22;
static constexpr uint8_t SPI_MUX_3_BCM = 23;
static constexpr uint8_t SPI_MUX_4_BCM = 5;
static constexpr uint8_t SPI_MUX_5_BCM = 6;
} // namespace gpio
#endif
#endif /* BSP_LINUX_BOARD_DEFINITIONS_H_ */

View File

@ -0,0 +1,56 @@
#include "gpioInit.h"
#include <devices/gpioIds.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw_hal/common/gpio/GpioCookie.h>
#include <fsfw_hal/common/gpio/GpioIF.h>
#include "definitions.h"
#include "fsfw_hal/linux/rpi/GpioRPi.h"
#ifdef RASPBERRY_PI
struct MuxInfo {
MuxInfo(gpioId_t gpioId, int bcmNum, std::string consumer)
: gpioId(gpioId), bcmNum(bcmNum), consumer(consumer) {}
gpioId_t gpioId;
int bcmNum;
std::string consumer;
};
void rpi::gpio::initSpiCsDecoder(GpioIF* gpioComIF) {
using namespace ::gpio;
ReturnValue_t result;
if (gpioComIF == nullptr) {
sif::debug << "initSpiCsDecoder: Invalid gpioComIF" << std::endl;
return;
}
std::array<::MuxInfo, 6> muxInfo{
MuxInfo(gpioIds::SPI_MUX_BIT_0, SPI_MUX_0_BCM, "SPI_MUX_0"),
MuxInfo(gpioIds::SPI_MUX_BIT_1, SPI_MUX_1_BCM, "SPI_MUX_1"),
MuxInfo(gpioIds::SPI_MUX_BIT_2, SPI_MUX_2_BCM, "SPI_MUX_2"),
MuxInfo(gpioIds::SPI_MUX_BIT_3, SPI_MUX_3_BCM, "SPI_MUX_3"),
MuxInfo(gpioIds::SPI_MUX_BIT_4, SPI_MUX_4_BCM, "SPI_MUX_4"),
MuxInfo(gpioIds::SPI_MUX_BIT_5, SPI_MUX_5_BCM, "SPI_MUX_5"),
};
GpioCookie* spiMuxGpios = new GpioCookie;
for (const auto& info : muxInfo) {
result = createRpiGpioConfig(spiMuxGpios, info.gpioId, info.bcmNum, info.consumer,
Direction::OUT, Levels::LOW);
if (result != returnvalue::OK) {
sif::error << "Creating Raspberry Pi SPI Mux GPIO failed with code " << result << std::endl;
return;
}
}
result = gpioComIF->addGpios(spiMuxGpios);
if (result != returnvalue::OK) {
sif::error << "initSpiCsDecoder: Failed to add mux bit gpios to gpioComIF" << std::endl;
return;
}
}
#endif

View File

@ -0,0 +1,20 @@
#pragma once
#include "OBSWConfig.h"
class GpioIF;
#ifdef RASPBERRY_PI
namespace rpi {
namespace gpio {
/**
* @brief This function initializes the GPIOs used to control the SN74LVC138APWR decoders on
* the TCS Board and the interface board.
*/
void initSpiCsDecoder(GpioIF* gpioComIF);
} // namespace gpio
} // namespace rpi
#endif

View File

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

View File

@ -1,11 +1,28 @@
target_sources(${TARGET_NAME} PUBLIC
InitMission.cpp
main.cpp
ObjectFactory.cpp
)
# simple mode
add_executable(${SIMPLE_OBSW_NAME} EXCLUDE_FROM_ALL)
target_compile_definitions(${SIMPLE_OBSW_NAME} PRIVATE "Q7S_SIMPLE_MODE")
target_sources(${SIMPLE_OBSW_NAME} PUBLIC main.cpp)
# I think this is unintentional? (produces linker errors for stuff in /linux)
target_link_libraries(${SIMPLE_OBSW_NAME} PUBLIC ${LIB_FSFW_NAME})
target_compile_definitions(${SIMPLE_OBSW_NAME} PRIVATE "Q7S_SIMPLE_MODE")
add_subdirectory(simple)
target_sources(${OBSW_NAME} PUBLIC main.cpp obsw.cpp scheduling.cpp
objectFactory.cpp)
add_subdirectory(boardtest)
add_subdirectory(boardconfig)
add_subdirectory(comIF)
add_subdirectory(boardtest)
add_subdirectory(gpio)
add_subdirectory(core)
if(EIVE_Q7S_EM)
add_subdirectory(em)
else()
target_sources(${OBSW_NAME} PUBLIC fmObjectFactory.cpp)
endif()
add_subdirectory(memory)
add_subdirectory(callbacks)
add_subdirectory(xadc)
add_subdirectory(fs)
add_subdirectory(acs)

View File

@ -1,35 +0,0 @@
FROM ubuntu:latest
# FROM alpine:latest
ENV TZ=Europe/Berlin
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt-get update && apt-get install -y curl cmake g++
# Q7S root filesystem, required for cross-compilation. Use IPv6 for curl
RUN mkdir -p /usr/rootfs; \
curl -6 https://eive-cloud.irs.uni-stuttgart.de/index.php/s/dnfMy9kGpgynN6J/download/cortexa9hf-neon-xiphos-linux-gnueabi.tar.gz \
| tar xvz -C /usr/rootfs
# Q7S C++ cross-compiler. Use IPv6 for curl
RUN mkdir -p /usr/tools; \
curl -6 https://eive-cloud.irs.uni-stuttgart.de/index.php/s/RMsbHydJc6PSqcz/download/gcc-arm-linux-gnueabi.tar.gz \
| tar xvz -C /usr/tools
# RUN apk add cmake make g++
# Required for cmake build
ENV Q7S_SYSROOT="/usr/rootfs/cortexa9hf-neon-xiphos-linux-gnueabi"
ENV PATH=$PATH:"/usr/tools/gcc-arm-linux-gnueabi/bin"
WORKDIR /usr/src/app
COPY . .
RUN set -ex; \
rm -rf build-q7s; \
mkdir build-q7s; \
cd build-q7s; \
cmake -DCMAKE_BUILD_TYPE=Release -DOS_FSFW=linux -DTGT_BSP="arm/q7s" ..;
ENTRYPOINT ["cmake", "--build", "build-q7s"]
CMD ["-j"]
# CMD ["bash"]

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