added cmake support

This commit is contained in:
Robin Müller 2020-12-29 01:09:59 +01:00
parent 5fe0ea5fc9
commit c1e9604977
46 changed files with 1235 additions and 20 deletions

9
.gitignore vendored
View File

@ -2,6 +2,15 @@ _obj
_bin _bin
_dep _dep
Debug
Debug*
Release
Release*
MinSizeRel
MinSizeRel*
RelWithDebInfo
RelWithDebInfo*
.settings .settings
.metadata .metadata
.project .project

153
CMakeLists.txt Normal file
View File

@ -0,0 +1,153 @@
################################################################################
# CMake support for the EIVE OBSW
#
# Developed in an effort to replace Make with a modern build system.
#
# Author: R. Mueller
################################################################################
################################################################################
# Pre-Project preparation
################################################################################
cmake_minimum_required(VERSION 3.13)
# set(CMAKE_VERBOSE TRUE)
set(CMAKE_SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/buildsystem/cmake")
if(NOT OS_FSFW)
set(OS_FSFW host CACHE STRING "OS for the FSFW.")
endif()
# Perform steps like loading toolchain files where applicable.
include(${CMAKE_SCRIPT_PATH}/PreProjectConfig.cmake)
pre_project_config()
# Project Name
project(fsfw_example ASM C CXX)
################################################################################
# Pre-Sources preparation
################################################################################
# Specify the C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# Set names and variables
set(TARGET_NAME ${CMAKE_PROJECT_NAME})
set(LIB_FSFW_NAME fsfw)
# Set path names
set(FSFW_PATH fsfw)
set(MISSION_PATH mission)
# 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()
set(FSFW_CONFIG_PATH "${BSP_PATH}/fsfwconfig")
################################################################################
# Executable and Sources
################################################################################
# Add executable
add_executable(${TARGET_NAME})
# Add subdirectories
if(LIB_OS_NAME)
add_subdirectory(${LIB_OS_NAME})
endif()
add_subdirectory(${BSP_PATH})
add_subdirectory(${FSFW_PATH})
add_subdirectory(${MISSION_PATH})
################################################################################
# Post-Sources preparation
################################################################################
# Add libraries for all sources.
target_link_libraries(${TARGET_NAME} PRIVATE
${LIB_FSFW_NAME}
${LIB_OS_NAME}
)
# Add include paths for all sources.
target_include_directories(${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${FSFW_CONFIG_PATH}
)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(WARNING_FLAGS
-Wall
-Wextra
-Wshadow=local
-Wimplicit-fallthrough=1
-Wno-unused-parameter
-Wno-psabi
)
# Remove unused sections.
target_compile_options(${TARGET_NAME} PRIVATE
"-ffunction-sections"
"-fdata-sections"
)
# Removed unused sections.
target_link_options(${TARGET_NAME} PRIVATE
"-Wl,--gc-sections"
)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(COMPILER_FLAGS "/permissive-")
endif()
if(CMAKE_VERBOSE)
message(STATUS "Warning flags: ${WARNING_FLAGS}")
endif()
# Compile options for all sources.
target_compile_options(${TARGET_NAME} PRIVATE
${WARNING_FLAGS}
)
if(${CMAKE_CROSSCOMPILING})
include (${CMAKE_SCRIPT_PATH}/HardwareOsPostConfig.cmake)
post_source_hw_os_config()
endif()
if(NOT CMAKE_SIZE)
set(CMAKE_SIZE size)
if(WIN32)
set(FILE_SUFFIX ".exe")
endif()
endif()
if(TGT_BSP)
set(TARGET_STRING "Target BSP: ${TGT_BSP}")
else()
set(TARGET_STRING "Target BSP: Hosted")
endif()
add_custom_command(
TARGET ${TARGET_NAME}
POST_BUILD
COMMAND echo "Build directory: ${CMAKE_BINARY_DIR}"
COMMAND echo "Target OSAL: ${OS_FSFW}"
COMMAND echo "Target Build Type: ${CMAKE_BUILD_TYPE}"
COMMAND echo "${TARGET_STRING}"
COMMAND ${CMAKE_SIZE} ${TARGET_NAME}${FILE_SUFFIX}
)
include (${CMAKE_SCRIPT_PATH}/BuildType.cmake)
set_build_type()

10
bsp_hosted/CMakeLists.txt Normal file
View File

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

View File

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

View File

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

View File

@ -0,0 +1,10 @@
target_sources(${TARGET_NAME} PRIVATE
ipc/MissionMessageTypes.cpp
)
target_include_directories(${TARGET_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@ -15,12 +15,6 @@
//! Can be used to enable debugging printouts for developing the FSFW //! Can be used to enable debugging printouts for developing the FSFW
#define FSFW_DEBUGGING 0 #define FSFW_DEBUGGING 0
//! Defines the FIFO depth of each commanding service base which
//! also determines how many commands a CSB service can handle in one cycle
//! simulataneously. This will increase the required RAM for
//! each CSB service !
#define FSFW_CSB_FIFO_DEPTH 6
//! If FSFW_OBJ_EVENT_TRANSLATION is set to one, //! If FSFW_OBJ_EVENT_TRANSLATION is set to one,
//! additional output which requires the translation files translateObjects //! additional output which requires the translation files translateObjects
//! and translateEvents (and their compiled source files) //! and translateEvents (and their compiled source files)
@ -49,6 +43,12 @@ static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 8;
static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240; static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240;
static constexpr size_t FSFW_EVENTMGMT_EVENTIDMATCHERS = 120; 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
//! simulataneously. This will increase the required RAM for
//! each CSB service !
static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 6;
} }
#endif /* CONFIG_FSFWCONFIG_H_ */ #endif /* CONFIG_FSFWCONFIG_H_ */

View File

@ -6,13 +6,25 @@
#ifndef CONFIG_OBSWCONFIG_H_ #ifndef CONFIG_OBSWCONFIG_H_
#define CONFIG_OBSWCONFIG_H_ #define CONFIG_OBSWCONFIG_H_
#include "returnvalues/classIds.h"
#include "events/subsystemIdRanges.h"
#define OBSW_ADD_TEST_CODE 0 #define OBSW_ADD_TEST_CODE 0
// These defines should be disabled for mission code but are useful for // These defines should be disabled for mission code but are useful for
// debugging. // debugging.
#define OBSW_ENHANCED_PRINTOUT 1 #define OBSW_ENHANCED_PRINTOUT 1
#ifdef __cplusplus
#include "objects/systemObjectList.h"
#include "events/subsystemIdRanges.h"
#include "returnvalues/classIds.h"
namespace config {
#endif
/* Add mission configuration flags here */
#ifdef __cplusplus
}
#endif
#endif /* CONFIG_OBSWCONFIG_H_ */ #endif /* CONFIG_OBSWCONFIG_H_ */

View File

@ -11,7 +11,7 @@ class CommandMessage;
* <fsfw/ipc/FwMessageTypes.h> * <fsfw/ipc/FwMessageTypes.h>
* @param message Generic Command Message * @param message Generic Command Message
*/ */
namespace messagetypes{ namespace messagetypes {
enum MESSAGE_TYPE { enum MESSAGE_TYPE {
MISSION_MESSAGE_TYPE_START = FW_MESSAGES_COUNT, MISSION_MESSAGE_TYPE_START = FW_MESSAGES_COUNT,
}; };

View File

@ -19,7 +19,6 @@ namespace objects {
PUS_SERVICE_23 = 0x51002300, PUS_SERVICE_23 = 0x51002300,
PUS_SERVICE_201 = 0x51020100, PUS_SERVICE_201 = 0x51020100,
TIME_STAMPER = 0x52000001,
TM_FUNNEL = 0x52000002, TM_FUNNEL = 0x52000002,
/* Test Task */ /* Test Task */

10
bsp_linux/CMakeLists.txt Normal file
View File

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

View File

@ -0,0 +1,6 @@
target_include_directories(${TARGET_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@ -0,0 +1,45 @@
function(set_build_type)
message(STATUS "Used build generator: ${CMAKE_GENERATOR}")
# Set a default build type if none was specified
set(DEFAULT_BUILD_TYPE "RelWithDebInfo")
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
set(DEFAULT_BUILD_TYPE "Debug")
endif()
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS
"Setting build type to '${DEFAULT_BUILD_TYPE}' as none was specified."
)
set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE
STRING "Choose the type of build." FORCE
)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Release" "MinSizeRel" "RelWithDebInfo"
)
endif()
if(${CMAKE_BUILD_TYPE} MATCHES "Debug")
message(STATUS
"Building Debug application with flags: ${CMAKE_C_FLAGS_DEBUG}"
)
elseif(${CMAKE_BUILD_TYPE} MATCHES "RelWithDebInfo")
message(STATUS
"Building Release (Debug) application with "
"flags: ${CMAKE_C_FLAGS_RELWITHDEBINFO}"
)
elseif(${CMAKE_BUILD_TYPE} MATCHES "MinSizeRel")
message(STATUS
"Building Release (Size) application with "
"flags: ${CMAKE_C_FLAGS_MINSIZEREL}"
)
else()
message(STATUS
"Building Release (Speed) application with "
"flags: ${CMAKE_C_FLAGS_RELEASE}"
)
endif()
endfunction()

View File

@ -0,0 +1,62 @@
function(post_source_hw_os_config)
if(LINK_LWIP)
message(STATUS "Linking against ${LIB_LWIP_NAME} lwIP library")
if(LIB_LWIP_NAME)
target_link_libraries(${TARGET_NAME} PUBLIC
${LIB_LWIP_NAME}
)
else()
message(WARNING "lwIP library name not set!")
endif()
endif()
if(LINK_HAL)
message(STATUS "Linking against ${LIB_HAL_NAME} HAL library")
if(LIB_HAL_NAME)
target_link_libraries(${TARGET_NAME} PUBLIC
${LIB_HAL_NAME}
)
else()
message(WARNING "HAL library name not set!")
endif()
endif()
if(LINKER_SCRIPT)
target_link_options(${TARGET_NAME} PRIVATE
-T${LINKER_SCRIPT}
)
endif()
set(C_FLAGS "" CACHE INTERNAL "C flags")
set(C_DEFS ""
CACHE INTERNAL
"C Defines"
)
set(CXX_FLAGS ${C_FLAGS})
set(CXX_DEFS ${C_DEFS})
if(CMAKE_VERBOSE)
message(STATUS "C Flags: ${C_FLAGS}")
message(STATUS "CXX Flags: ${CXX_FLAGS}")
message(STATUS "C Defs: ${C_DEFS}")
message(STATUS "CXX Defs: ${CXX_DEFS}")
endif()
# Generator expression. Can be used to set different C, CXX and ASM flags.
target_compile_options(${TARGET_NAME} PRIVATE
$<$<COMPILE_LANGUAGE:C>:${C_DEFS} ${C_FLAGS}>
$<$<COMPILE_LANGUAGE:CXX>:${CXX_DEFS} ${CXX_FLAGS}>
$<$<COMPILE_LANGUAGE:ASM>:${ASM_FLAGS}>
)
add_custom_command(
TARGET ${TARGET_NAME}
POST_BUILD
COMMAND echo Generating binary file ${CMAKE_PROJECT_NAME}.bin..
COMMAND ${CMAKE_OBJCOPY} -O binary ${TARGET_NAME} ${TARGET_NAME}.bin
)
endfunction()

View File

@ -0,0 +1,68 @@
function(pre_source_hw_os_config)
# FreeRTOS
if(${OS_FSFW} MATCHES freertos)
message(FATAL_ERROR "No FreeRTOS support implemented yet.")
# RTEMS
elseif(${OS_FSFW} STREQUAL rtems)
add_definitions(-DRTEMS)
message(FATAL_ERROR "No RTEMS support implemented yet.")
elseif(${OS_FSFW} STREQUAL linux)
add_definitions(-DUNIX -DLINUX)
find_package(Threads REQUIRED)
set(BSP_PATH "bsp_linux")
# Hosted
else()
set(BSP_PATH "bsp_hosted")
if(WIN32)
add_definitions(-DWIN32)
elseif(UNIX)
find_package(Threads REQUIRED)
add_definitions(-DUNIX -DLINUX)
endif()
endif()
# Cross-compile information
if(CMAKE_CROSSCOMPILING)
# set(CMAKE_VERBOSE TRUE)
message(STATUS "Cross-compiling for ${TGT_BSP} target")
message(STATUS "Cross-compile gcc: ${CMAKE_C_COMPILER}")
message(STATUS "Cross-compile g++: ${CMAKE_CXX_COMPILER}")
if(CMAKE_VERBOSE)
message(STATUS "Cross-compile linker: ${CMAKE_LINKER}")
message(STATUS "Cross-compile size utility: ${CMAKE_SIZE}")
message(STATUS "Cross-compile objcopy utility: ${CMAKE_OBJCOPY}")
message(STATUS "Cross-compile ranlib utility: ${CMAKE_RANLIB}")
message(STATUS "Cross-compile ar utility: ${CMAKE_AR}")
message(STATUS "Cross-compile nm utility: ${CMAKE_NM}")
message(STATUS "Cross-compile strip utility: ${CMAKE_STRIP}")
message(STATUS
"Cross-compile assembler: ${CMAKE_ASM_COMPILER} "
"-x assembler-with-cpp"
)
message(STATUS "ABI flags: ${ABI_FLAGS}")
message(STATUS "Custom linker script: ${LINKER_SCRIPT}")
endif()
set_property(CACHE TGT_BSP
PROPERTY STRINGS
"arm/raspberrypi"
)
endif()
if(${TGT_BSP} MATCHES "arm/raspberrypi")
else()
if(TGT_BSP)
message(WARNING "CMake not configured for this target!")
message(FATAL_ERROR "Target: ${TGT_BSP}!")
endif()
endif()
set(BSP_PATH ${BSP_PATH} PARENT_SCOPE)
endfunction()

View File

@ -0,0 +1,58 @@
function(pre_project_config)
# Basic input sanitization
if(DEFINED TGT_BSP)
if(${TGT_BSP} MATCHES "arm/raspberrypi" AND NOT ${OS_FSFW} MATCHES linux)
message(STATUS "FSFW OSAL invalid for specified target BSP ${TGT_BSP}!")
message(STATUS "Setting valid OS_FSFW: linux")
set(OS_FSFW "linux")
endif()
endif()
# Disable compiler checks for cross-compiling.
if(${OS_FSFW} STREQUAL linux AND TGT_BSP)
if(${TGT_BSP} MATCHES "arm/raspberrypi")
if(NOT DEFINED ENV{RASPBIAN_ROOTFS})
if(NOT RASPBIAN_ROOTFS)
set(ENV{RASPBIAN_ROOTFS} "$ENV{HOME}/raspberrypi/rootfs")
else()
set(ENV{RASPBIAN_ROOTFS} "${RASPBIAN_ROOTFS}")
endif()
else()
message(STATUS
"RASPBIAN_ROOTFS from environmental variables used: "
"$ENV{RASPBIAN_ROOTFS}"
)
endif()
if(NOT DEFINED ENV{RASPBERRY_VERSION})
if(NOT RASPBERRY_VERSION)
message(STATUS "No RASPBERRY_VERSION specified, setting to 4")
set(RASPBERRY_VERSION "4" CACHE STRING "Raspberry Pi version")
else()
message(STATUS
"Setting RASPBERRY_VERSION to ${RASPBERRY_VERSION}"
)
set(RASPBERRY_VERSION
${RASPBERRY_VERSION} CACHE STRING "Raspberry Pi version"
)
set(ENV{RASPBERRY_VERSION} ${RASPBERRY_VERSION})
endif()
else()
message(STATUS
"RASPBERRY_VERSION from environmental variables used: "
"$ENV{RASPBERRY_VERSION}"
)
endif()
set(CMAKE_TOOLCHAIN_FILE
"${CMAKE_SCRIPT_PATH}/RPiCrossCompileConfig.cmake"
PARENT_SCOPE
)
else()
message(WARNING "Target BSP (TGT_BSP) ${TGT_BSP} unknown!")
endif()
endif()
endfunction()

View File

@ -0,0 +1,146 @@
# Based on https://github.com/Pro/raspi-toolchain but rewritten completely.
# Adapted for the FSFW Example
if(NOT $ENV{RASPBERRY_VERSION})
message(STATUS "Raspberry Pi version not specified, setting version 4!")
set(RASPBERRY_VERSION 4)
else()
set(RASPBERRY_VERSION $ENV{RASPBERRY_VERSION})
endif()
# RASPBIAN_ROOTFS should point to the local directory which contains all the
# libraries and includes from the target raspi.
# The following command can be used to do this, replace <ip-address> and the
# local <rootfs-path> accordingly:
# rsync -vR --progress -rl --delete-after --safe-links pi@<ip-address>:/{lib,usr,opt/vc/lib} <rootfs-path>
# RASPBIAN_ROOTFS needs to be passed to the CMake command or defined in the
# application CMakeLists.txt before loading the toolchain file.
# CROSS_COMPILE also needs to be set accordingly or passed to the CMake command
if(NOT DEFINED ENV{RASPBIAN_ROOTFS})
message(FATAL_ERROR
"Define the RASPBIAN_ROOTFS variable to "
"point to the raspbian rootfs."
)
else()
set(SYSROOT_PATH "$ENV{RASPBIAN_ROOTFS}")
endif()
if(NOT DEFINED ENV{CROSS_COMPILE})
set(CROSS_COMPILE "arm-linux-gnueabihf")
message(STATUS
"No CROSS_COMPILE environmental variable set, using default ARM linux "
"cross compiler name ${CROSS_COMPILE}"
)
else()
set(CROSS_COMPILE "$ENV{CROSS_COMPILE}")
message(STATUS
"Using environmental variable CROSS_COMPILE as cross-compiler: "
"$ENV{CROSS_COMPILE}"
)
endif()
message(STATUS "Using sysroot path: ${SYSROOT_PATH}")
set(CROSS_COMPILE_CC "${CROSS_COMPILE}-gcc")
set(CROSS_COMPILE_CXX "${CROSS_COMPILE}-g++")
set(CROSS_COMPILE_LD "${CROSS_COMPILE}-ld")
set(CROSS_COMPILE_AR "${CROSS_COMPILE}-ar")
set(CROSS_COMPILE_RANLIB "${CROSS_COMPILE}-ranlib")
set(CROSS_COMPILE_STRIP "${CROSS_COMPILE}-strip")
set(CROSS_COMPILE_NM "${CROSS_COMPILE}-nm")
set(CROSS_COMPILE_OBJCOPY "${CROSS_COMPILE}-objcopy")
set(CROSS_COMPILE_SIZE "${CROSS_COMPILE}-size")
# At the very least, cross compile gcc and g++ have to be set!
find_program (CROSS_COMPILE_CC_FOUND ${CROSS_COMPILE_CC} REQUIRED)
find_program (CROSS_COMPILE_CXX_FOUND ${CROSS_COMPILE_CXX} REQUIRED)
set(CMAKE_CROSSCOMPILING TRUE)
set(CMAKE_SYSROOT "${SYSROOT_PATH}")
# Define name of the target system
set(CMAKE_SYSTEM_NAME "Linux")
if(RASPBERRY_VERSION VERSION_GREATER 1)
set(CMAKE_SYSTEM_PROCESSOR "armv7")
else()
set(CMAKE_SYSTEM_PROCESSOR "arm")
endif()
# Define the compiler
set(CMAKE_C_COMPILER ${CROSS_COMPILE_CC})
set(CMAKE_CXX_COMPILER ${CROSS_COMPILE_CXX})
# List of library dirs where LD has to look. Pass them directly through gcc.
# LD_LIBRARY_PATH is not evaluated by arm-*-ld
set(LIB_DIRS
"/opt/cross-pi-gcc/arm-linux-gnueabihf/lib"
"/opt/cross-pi-gcc/lib"
"${SYSROOT_PATH}/opt/vc/lib"
"${SYSROOT_PATH}/lib/${CROSS_COMPILE}"
"${SYSROOT_PATH}/usr/local/lib"
"${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}"
"${SYSROOT_PATH}/usr/lib"
"${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}/blas"
"${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}/lapack"
)
# You can additionally check the linker paths if you add the
# flags ' -Xlinker --verbose'
set(COMMON_FLAGS "-I${SYSROOT_PATH}/usr/include")
foreach(LIB ${LIB_DIRS})
set(COMMON_FLAGS "${COMMON_FLAGS} -L${LIB} -Wl,-rpath-link,${LIB}")
endforeach()
set(CMAKE_PREFIX_PATH
"${CMAKE_PREFIX_PATH}"
"${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}"
)
if(RASPBERRY_VERSION VERSION_GREATER 3)
set(CMAKE_C_FLAGS
"-mcpu=cortex-a72 -mfpu=neon-vfpv4 -mfloat-abi=hard ${COMMON_FLAGS}"
CACHE STRING "Flags for Raspberry PI 4"
)
set(CMAKE_CXX_FLAGS
"${CMAKE_C_FLAGS}"
CACHE STRING "Flags for Raspberry PI 4"
)
elseif(RASPBERRY_VERSION VERSION_GREATER 2)
set(CMAKE_C_FLAGS
"-mcpu=cortex-a53 -mfpu=neon-vfpv4 -mfloat-abi=hard ${COMMON_FLAGS}"
CACHE STRING "Flags for Raspberry PI 3"
)
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}"
CACHE STRING "Flags for Raspberry PI 3"
)
elseif(RASPBERRY_VERSION VERSION_GREATER 1)
set(CMAKE_C_FLAGS
"-mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard ${COMMON_FLAGS}"
CACHE STRING "Flags for Raspberry PI 2"
)
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}"
CACHE STRING "Flags for Raspberry PI 2"
)
else()
set(CMAKE_C_FLAGS
"-mcpu=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard ${COMMON_FLAGS}"
CACHE STRING "Flags for Raspberry PI 1 B+ Zero"
)
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}"
CACHE STRING "Flags for Raspberry PI 1 B+ Zero"
)
endif()
set(CMAKE_FIND_ROOT_PATH
"${CMAKE_INSTALL_PREFIX};${CMAKE_PREFIX_PATH};${CMAKE_SYSROOT}"
)
# search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9" project-jdk-type="Python SDK" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/scripts.iml" filepath="$PROJECT_DIR$/.idea/scripts.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
buildsystem/cmake/scripts/.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../.." vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="b7804b00-6384-4363-ae17-406610449420" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/../../.." />
</component>
<component name="ProjectId" id="1mFLMh77EFiQ6e8GGJM4DSy44LC" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.tslint" value="true" />
<property name="node.js.path.for.package.eslint" value="project" />
<property name="node.js.path.for.package.tslint" value="project" />
<property name="node.js.selected.package.eslint" value="(autodetect)" />
<property name="node.js.selected.package.tslint" value="(autodetect)" />
</component>
<component name="RunManager">
<configuration name="cmake_build_config" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="scripts" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/cmake_build_config.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="Python.cmake_build_config" />
</list>
</recent_temporary>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="b7804b00-6384-4363-ae17-406610449420" name="Default Changelist" comment="" />
<created>1609084345199</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1609084345199</updated>
<workItem from="1609084346343" duration="6791000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
</component>
<component name="com.intellij.coverage.CoverageDataManagerImpl">
<SUITE FILE_PATH="coverage/scripts$cmake_build_config.coverage" NAME="cmake_build_config Coverage Results" MODIFIED="1609089450693" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
</component>
</project>

View File

@ -0,0 +1,26 @@
#!/bin/sh
counter=0
while [ ${counter} -lt 5 ]
do
cd ..
if [ -f "cmake_build_config.py" ];then
break
fi
counter=$((counter=counter + 1))
done
if [ "${counter}" -ge 5 ];then
echo "create_cmake_cfg.sh not found in upper directories!"
exit 1
fi
build_generator=""
os_fsfw="host"
if [ "${OS}" = "Windows_NT" ]; then
build_generator="MinGW Makefiles"
# Could be other OS but this works for now.
else
build_generator="Unix Makefiles"
fi
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug"

View File

@ -0,0 +1,26 @@
#!/bin/sh
counter=0
while [ ${counter} -lt 5 ]
do
cd ..
if [ -f "cmake_build_config.py" ];then
break
fi
counter=$((counter=counter + 1))
done
if [ "${counter}" -ge 5 ];then
echo "create_cmake_cfg.sh not found in upper directories!"
exit 1
fi
build_generator=""
os_fsfw="host"
if [ "${OS}" = "Windows_NT" ]; then
build_generator="MinGW Makefiles"
# Could be other OS but this works for now.
else
build_generator="Unix Makefiles"
fi
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "release"

View File

@ -0,0 +1,26 @@
#!/bin/sh
counter=0
while [ ${counter} -lt 5 ]
do
cd ..
if [ -f "cmake_build_config.py" ];then
break
fi
counter=$((counter=counter + 1))
done
if [ "${counter}" -ge 5 ];then
echo "create_cmake_cfg.sh not found in upper directories!"
exit 1
fi
build_generator=""
os_fsfw="host"
if [ "${OS}" = "Windows_NT" ]; then
build_generator="MinGW Makefiles"
# Could be other OS but this works for now.
else
build_generator="Unix Makefiles"
fi
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "reldeb"

View File

@ -0,0 +1,26 @@
#!/bin/sh
counter=0
while [ ${counter} -lt 5 ]
do
cd ..
if [ -f "cmake_build_config.py" ];then
break
fi
counter=$((counter=counter + 1))
done
if [ "${counter}" -ge 5 ];then
echo "create_cmake_cfg.sh not found in upper directories!"
exit 1
fi
build_generator=""
os_fsfw="host"
if [ "${OS}" = "Windows_NT" ]; then
build_generator="MinGW Makefiles"
# Could be other OS but this works for now.
else
build_generator="Unix Makefiles"
fi
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "size"

View File

@ -0,0 +1,20 @@
#!/bin/sh
counter=0
while [ ${counter} -lt 5 ]
do
cd ..
if [ -f "cmake_build_config.py" ];then
break
fi
counter=$((counter=counter + 1))
done
if [ "${counter}" -ge 5 ];then
echo "create_cmake_cfg.sh not found in upper directories!"
exit 1
fi
build_generator="Unix Makefiles"
os_fsfw="linux"
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug"

View File

@ -0,0 +1,20 @@
#!/bin/sh
counter=0
while [ ${counter} -lt 5 ]
do
cd ..
if [ -f "cmake_build_config.py" ];then
break
fi
counter=$((counter=counter + 1))
done
if [ "${counter}" -ge 5 ];then
echo "create_cmake_cfg.sh not found in upper directories!"
exit 1
fi
build_generator="Unix Makefiles"
os_fsfw="linux"
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "release"

View File

@ -0,0 +1,20 @@
#!/bin/sh
counter=0
while [ ${counter} -lt 5 ]
do
cd ..
if [ -f "cmake_build_config.py" ];then
break
fi
counter=$((counter=counter + 1))
done
if [ "${counter}" -ge 5 ];then
echo "create_cmake_cfg.sh not found in upper directories!"
exit 1
fi
build_generator="Unix Makefiles"
os_fsfw="linux"
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "reldeb"

View File

@ -0,0 +1,20 @@
#!/bin/sh
counter=0
while [ ${counter} -lt 5 ]
do
cd ..
if [ -f "cmake_build_config.py" ];then
break
fi
counter=$((counter=counter + 1))
done
if [ "${counter}" -ge 5 ];then
echo "create_cmake_cfg.sh not found in upper directories!"
exit 1
fi
build_generator="Unix Makefiles"
os_fsfw="linux"
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "size"

View File

@ -0,0 +1,27 @@
#!/bin/sh
counter=0
while [ ${counter} -lt 5 ]
do
cd ..
if [ -f "cmake_build_config.py" ];then
break
fi
counter=$((counter=counter + 1))
done
if [ "${counter}" -ge 5 ];then
echo "cmake_build_config.py not found in upper directories!"
exit 1
fi
os_fsfw="linux"
tgt_bsp="arm/raspberrypi"
build_generator=""
if [ "${OS}" = "Windows_NT" ]; then
build_generator="MinGW Makefiles"
# Could be other OS but this works for now.
else
build_generator="Unix Makefiles"
fi
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug" -t "${tgt_bsp}"

View File

@ -0,0 +1,27 @@
#!/bin/sh
counter=0
while [ ${counter} -lt 5 ]
do
cd ..
if [ -f "cmake_build_config.py" ];then
break
fi
counter=$((counter=counter + 1))
done
if [ "${counter}" -ge 5 ];then
echo "cmake_build_config.py not found in upper directories!"
exit 1
fi
os_fsfw="linux"
tgt_bsp="arm/raspberrypi"
build_generator=""
if [ "${OS}" = "Windows_NT" ]; then
build_generator="MinGW Makefiles"
# Could be other OS but this works for now.
else
build_generator="Unix Makefiles"
fi
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "release" -t "${tgt_bsp}"

View File

@ -0,0 +1,27 @@
#!/bin/sh
counter=0
while [ ${counter} -lt 5 ]
do
cd ..
if [ -f "cmake_build_config.py" ];then
break
fi
counter=$((counter=counter + 1))
done
if [ "${counter}" -ge 5 ];then
echo "cmake_build_config.py not found in upper directories!"
exit 1
fi
os_fsfw="linux"
tgt_bsp="arm/raspberrypi"
build_generator=""
if [ "${OS}" = "Windows_NT" ]; then
build_generator="MinGW Makefiles"
# Could be other OS but this works for now.
else
build_generator="Unix Makefiles"
fi
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "reldeb" -t "${tgt_bsp}"

View File

@ -0,0 +1,27 @@
#!/bin/sh
counter=0
while [ ${counter} -lt 5 ]
do
cd ..
if [ -f "cmake_build_config.py" ];then
break
fi
counter=$((counter=counter + 1))
done
if [ "${counter}" -ge 5 ];then
echo "cmake_build_config.py not found in upper directories!"
exit 1
fi
os_fsfw="linux"
tgt_bsp="arm/raspberrypi"
build_generator=""
if [ "${OS}" = "Windows_NT" ]; then
build_generator="MinGW Makefiles"
# Could be other OS but this works for now.
else
build_generator="Unix Makefiles"
fi
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "size" -t "${tgt_bsp}"

View File

@ -0,0 +1,24 @@
#!/bin/sh
# This script can be used to set the path to the cross-compile toolchain
# A default path is set if the path is not supplied via command line
if [ $# -eq 1 ];then
export PATH=$PATH:"$1"
else
# TODO: make version configurable via shell argument
export PATH=$PATH:"/opt/cross-pi-gcc/bin"
export CROSS_COMPILE="arm-linux-gnueabihf"
export RASPBERRY_VERSION="4"
export RASPBIAN_ROOTFS="${HOME}/raspberrypi/rootfs"
fi
# It is also recommended to set up a custom shell script to perform the
# sysroot synchronization so that any software is built with the library and
# headers of the Raspberry Pi. This can for example be dome with the rsync
# command.
# The following command can be used, <ip-address> and the local
# <rootfs-path> need to be set accordingly.
# rsync -vR --progress -rl --delete-after --safe-links pi@<ip-address>:/{lib,usr,opt/vc/lib} <rootfs-path>
# It is recommended to use $HOME/raspberrypi/rootfs as the rootfs path,
# so the default RASPBIAN_ROOTFS variable set in the CMakeLists.txt is correct.

View File

@ -0,0 +1,22 @@
#!/bin/sh
# This script can be used to set the path to the cross-compile toolchain
# A default path is set if the path is not supplied via command line
if [ $# -eq 1 ];then
export PATH=$PATH:"$1"
else
# TODO: make version configurable via shell argument
export PATH=$PATH:"/c/SysGCC/raspberry/bin"
export CROSS_COMPILE="arm-linux-gnueabihf"
export RASPBERRY_VERSION="4"
export RASPBIAN_ROOTFS="/c/Users/<UserName>/raspberrypi/rootfs"
fi
# It is also recommended to set up a custom shell script to perform the
# sysroot synchronization so that any software is built with the library and
# headers of the Raspberry Pi. This can for example be dome with the rsync
# command.
# The following command can be used, <ip-address> and the local
# <rootfs-path> need to be set accordingly.
# rsync -vR --progress -rl --delete-after --safe-links pi@<ip-address>:/{lib,usr,opt/vc/lib} <rootfs-path>

View File

@ -0,0 +1,115 @@
#!/usr/bin/env python3
"""
@brief CMake configuration helper
@details
This script was written to have a portable way to perform the CMake configuration with various parameters on
different OSes. It was first written for the FSFW Example, but could be adapted to be more generic
in the future.
Run cmake_build_config.py --help to get more information.
"""
import os
import sys
import argparse
import shutil
def main():
print("-- Python CMake build configurator utility --")
print("Parsing command line arguments..")
parser = argparse.ArgumentParser(description="Processing arguments for CMake build configuration.")
parser.add_argument("-o", "--osal", type=str, choices=["freertos", "linux", "rtems", "host"],
help="FSFW OSAL. Valid arguments: host, linux, rtems, freertos")
parser.add_argument("-b", "--buildtype", type=str, choices=["debug", "release", "size", "reldeb"],
help="CMake build type. Valid arguments: debug, release, size, reldeb (Release with Debug "
"Information)", default="debug")
parser.add_argument("-l", "--builddir", type=str, help="Specify build directory.")
parser.add_argument("-g", "--generator", type=str, help="CMake Generator")
parser.add_argument("-t", "--target-bsp", type=str, help="Target BSP, combination of architecture and machine")
args = parser.parse_args()
print("Determining source location..")
source_location = determine_source_location()
print(f"Determined source location: {source_location}")
print("Building cmake configuration command..")
if args.osal is None:
print("No FSFW OSAL specified, setting to default (host)..")
osal = "host"
else:
osal = args.osal
if args.generator is None:
generator_cmake_arg = ""
else:
generator_cmake_arg = f"-G \"{args.generator}\""
if args.buildtype == "debug":
cmake_build_type = "Debug"
elif args.buildtype == "release":
cmake_build_type = "Release"
elif args.buildtype == "size":
cmake_build_type = "MinSizeRel"
else:
cmake_build_type = "RelWithDebInfo"
if args.target_bsp is not None:
cmake_target_cfg_cmd = f"-DTGT_BSP=\"{args.target_bsp}\""
else:
cmake_target_cfg_cmd = ""
# TODO: Use builddir if given (need to check whether path is relative or absolute)
build_folder = cmake_build_type
build_path = source_location + os.path.sep + build_folder
if os.path.isdir(build_path):
remove_old_dir = input(f"{build_folder} folder already exists. Remove old directory? [y/n]: ")
if str(remove_old_dir).lower() in ["yes", "y", 1]:
remove_old_dir = True
else:
build_folder = determine_new_folder()
build_path = source_location + os.path.sep + build_folder
remove_old_dir = False
if remove_old_dir:
shutil.rmtree(build_path)
os.chdir(source_location)
os.mkdir(build_folder)
print(f"Navigating into build directory: {build_path}")
os.chdir(build_folder)
cmake_command = f"cmake {generator_cmake_arg} -DOS_FSFW=\"{osal}\" " \
f"-DCMAKE_BUILD_TYPE=\"{cmake_build_type}\" {cmake_target_cfg_cmd} {source_location}"
# Remove redundant spaces
cmake_command = ' '.join(cmake_command.split())
print("Running CMake command: ")
print(f"\" {cmake_command} \"")
os.system(cmake_command)
print("-- CMake configuration done. --")
def determine_source_location() -> str:
index = 0
while not os.path.isdir("fsfw"):
index += 1
os.chdir("..")
if index >= 5:
print("Error: Could not find source directory (determined by looking for fsfw folder!)")
sys.exit(1)
return os.getcwd()
def determine_new_folder() -> str:
new_folder = input(f"Use different folder name? [y/n]: ")
if str(new_folder).lower() in ["yes", "y", 1]:
new_folder_name = input("New folder name: ")
return new_folder_name
else:
print("Aborting configuration.")
sys.exit(0)
if __name__ == "__main__":
main()

2
fsfw

@ -1 +1 @@
Subproject commit dcc111e4facf39137fe52d8234361b7d99bdde06 Subproject commit 5b9c0e013e35ab1353d402c6fa2cd75866e3afa5

View File

@ -6,13 +6,27 @@
#ifndef FSFWCONFIG_OBSWCONFIG_H_ #ifndef FSFWCONFIG_OBSWCONFIG_H_
#define FSFWCONFIG_OBSWCONFIG_H_ #define FSFWCONFIG_OBSWCONFIG_H_
#include "returnvalues/classIds.h"
#include "events/subsystemIdRanges.h"
#define OBSW_ADD_TEST_CODE 0 #define OBSW_ADD_TEST_CODE 0
// These defines should be disabled for mission code but are useful for // These defines should be disabled for mission code but are useful for
// debugging. // debugging.
#define OBSW_ENHANCED_PRINTOUT 1 #define OBSW_ENHANCED_PRINTOUT 1
#include "OBSWVersion.h"
#ifdef __cplusplus
#include "objects/systemObjectList.h"
#include "events/subsystemIdRanges.h"
#include "returnvalues/classIds.h"
namespace config {
#endif
/* Add mission configuration flags here */
#ifdef __cplusplus
}
#endif
#endif /* FSFWCONFIG_OBSWCONFIG_H_ */ #endif /* FSFWCONFIG_OBSWCONFIG_H_ */

3
mission/CMakeLists.txt Normal file
View File

@ -0,0 +1,3 @@
add_subdirectory(core)
add_subdirectory(devices)
add_subdirectory(utility)

View File

@ -0,0 +1,5 @@
target_sources(${TARGET_NAME} PUBLIC
GenericFactory.cpp
)

View File

@ -0,0 +1,8 @@
target_sources(${TARGET_NAME} PUBLIC
GPSHandler.cpp
GyroL3GD20Handler.cpp
MGMHandlerLIS3MDL.cpp
MGMHandlerRM3100.cpp
)

View File

@ -12,7 +12,7 @@ namespace RM3100 {
static constexpr uint8_t READ_MASK = 0b1000'0000; static constexpr uint8_t READ_MASK = 0b1000'0000;
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/* CMM Register /* CMM Register */
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
static constexpr uint8_t SET_CMM_CMZ = 1 << 6; static constexpr uint8_t SET_CMM_CMZ = 1 << 6;
static constexpr uint8_t SET_CMM_CMY = 1 << 5; static constexpr uint8_t SET_CMM_CMY = 1 << 5;
@ -25,7 +25,7 @@ static constexpr uint8_t CMM_VALUE = SET_CMM_CMZ | SET_CMM_CMY | SET_CMM_CMX |
SET_CMM_DRDM | SET_CMM_START; SET_CMM_DRDM | SET_CMM_START;
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/* Cycle count register /* Cycle count register */
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
// Default value (200) // Default value (200)
static constexpr uint8_t CYCLE_COUNT_VALUE = 0xC8; static constexpr uint8_t CYCLE_COUNT_VALUE = 0xC8;
@ -35,7 +35,7 @@ static constexpr float DEFAULT_GAIN = static_cast<float>(CYCLE_COUNT_VALUE) /
static constexpr uint8_t CYCLE_COUNT_START_REGISTER = 0x04; static constexpr uint8_t CYCLE_COUNT_START_REGISTER = 0x04;
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/* TMRC register /* TMRC register */
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
static constexpr uint8_t TMRC_150HZ_VALUE = 0x94; static constexpr uint8_t TMRC_150HZ_VALUE = 0x94;
static constexpr uint8_t TMRC_75HZ_VALUE = 0x95; static constexpr uint8_t TMRC_75HZ_VALUE = 0x95;

View File

@ -0,0 +1,5 @@
target_sources(${TARGET_NAME} PUBLIC
TmFunnel.cpp
)

2
tmtc

@ -1 +1 @@
Subproject commit 9be8713fa0cc6128e9469da2e635365b03146de3 Subproject commit 07b6a9df18baff999ca52c2f2781f8f77f8dcb65