diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dfe22fc..4713ed17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/). PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572 - HAL Devicehandlers: Periodic printout is run-time configurable now - `oneShotAction` flag in the `TestTask` class is not static anymore +- Major update for version handling, using `git describe` to fetch version information with git. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/601 + - Add helper functions provided by [`cmake-modules`](https://github.com/bilke/cmake-modules) + manually now. Those should not change too often and only a small subset is needed + - Separate folder for easier update and for distinction + - LICENSE file included + - use `int` for version numbers to allow unset or uninitialized version + - Initialize Version object with numbers set to -1 + - Instead of hardcoding the git hash, it is now retrieved from git + - `Version` now allows specifying additional version information like the git SHA1 hash and the + versions since the last tag + - Additional information is set to the last part of the git describe output for `FSFW_VERSION` now. + - Version still need to be hand-updated if the FSFW is not included as a submodule for now. - IPC Message Queue Handling: Allow passing an optional `MqArgs` argument into the MessageQueue creation call. It allows passing context information and an arbitrary user argument into the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs @@ -32,6 +45,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### HAL +- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585 - HAL Linux SPI: Set the Clock Default State when setting new SPI speed and mode PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573 @@ -87,6 +102,9 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593 - Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information inside `fsfw/version.h` PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559 +- Added generic PUS TC Scheduler Service 11. It depends on the new added Emebeded Template Library + (ETL) dependency. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/594 - Added ETL dependency and improved library dependency management PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592 - Add a `DummyPowerSwitcher` module which can be useful for test setups when no PCDU is available diff --git a/CMakeLists.txt b/CMakeLists.txt index db606b83..40c0b879 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,21 +1,70 @@ cmake_minimum_required(VERSION 3.13) +set(MSG_PREFIX "fsfw |") + +# Add the cmake folder so the FindSphinx module is found +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +list(APPEND CMAKE_MODULE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake-modules/bilke") +list(APPEND CMAKE_MODULE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake-modules/rpavlik") + +# ############################################################################## +# Version file handling # +# ############################################################################## + +set(FSFW_VERSION_IF_GIT_FAILS 4) +set(FSFW_SUBVERSION_IF_GIT_FAILS 0) +set(FSFW_REVISION_IF_GIT_FAILS 0) + +set(FSFW_GIT_VER_HANDLING_OK FALSE) +# Version handling +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git) + message(STATUS "${MSG_PREFIX} Determining version information with git") + include(FsfwHelpers) + determine_version_with_git("--exclude" "docker_*") + if(GIT_INFO) + set(FSFW_GIT_INFO + ${GIT_INFO} + CACHE STRING "Version information retrieved with git describe") + list(GET FSFW_GIT_INFO 1 FSFW_VERSION) + list(GET FSFW_GIT_INFO 2 FSFW_SUBVERSION) + list(GET FSFW_GIT_INFO 3 FSFW_REVISION) + list(GET FSFW_GIT_INFO 4 FSFW_VCS_INFO) + if(NOT FSFW_VERSION) + set(FSFW_VERSION ${FSFW_VERSION_IF_GIT_FAILS}) + endif() + if(NOT FSFW_SUBVERSION) + set(FSFW_SUBVERSION ${FSFW_SUBVERSION_IF_GIT_FAILS}) + endif() + if(NOT FSFW_REVISION) + set(FSFW_REVISION ${FSFW_REVISION_IF_GIT_FAILS}) + endif() + set(FSFW_GIT_VER_HANDLING_OK TRUE) + else() + set(FSFW_GIT_VER_HANDLING_OK FALSE) + endif() +endif() +if(NOT FSFW_GIT_VER_HANDLING_OK) + set(FSFW_VERSION ${FSFW_VERSION_IF_GIT_FAILS}) + set(FSFW_SUBVERSION ${FSFW_SUBVERSION_IF_GIT_FAILS}) + set(FSFW_REVISION ${FSFW_REVISION_IF_GIT_FAILS}) +endif() + set(LIB_FSFW_NAME fsfw) -project(${LIB_FSFW_NAME}) +project(${LIB_FSFW_NAME} + VERSION ${FSFW_VERSION}.${FSFW_SUBVERSION}.${FSFW_REVISION}) if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) elseif(${CMAKE_CXX_STANDARD} LESS 17) - message(FATAL_ERROR "Compiling the FSFW requires a minimum of C++17 support") + message( + FATAL_ERROR + "${MSG_PREFIX} Compiling the FSFW requires a minimum of C++17 support") endif() -set(FSFW_VERSION 4) -set(FSFW_SUBVERSION 0) -set(FSFW_REVISION 0) - -# Add the cmake folder so the FindSphinx module is found -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) +set(FSFW_SOURCES_DIR "${CMAKE_SOURCE_DIR}/src/fsfw") set(FSFW_ETL_LIB_NAME etl) set(FSFW_ETL_LIB_MAJOR_VERSION @@ -91,14 +140,16 @@ endif() if(FSFW_BUILD_UNITTESTS) message( - STATUS "Building the FSFW unittests in addition to the static library") + STATUS + "${MSG_PREFIX} Building the FSFW unittests in addition to the static library" + ) # Check whether the user has already installed Catch2 first find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION}) # Not installed, so use FetchContent to download and provide Catch2 if(NOT Catch2_FOUND) message( STATUS - "Catch2 installation not found. Downloading Catch2 library with FetchContent" + "${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent" ) include(FetchContent) @@ -123,20 +174,15 @@ if(FSFW_BUILD_UNITTESTS) endif() if(FSFW_TESTS_GEN_COV) - message(STATUS "Generating coverage data for the library") - message(STATUS "Targets linking against ${LIB_FSFW_NAME} " + message(STATUS "${MSG_PREFIX} Generating coverage data for the library") + message(STATUS "${MSG_PREFIX} Targets linking against ${LIB_FSFW_NAME} " "will be compiled with coverage data as well") - include(FetchContent) - FetchContent_Declare( - cmake-modules GIT_REPOSITORY https://github.com/bilke/cmake-modules.git) - FetchContent_MakeAvailable(cmake-modules) set(CMAKE_BUILD_TYPE "Debug") - list(APPEND CMAKE_MODULE_PATH ${cmake-modules_SOURCE_DIR}) include(CodeCoverage) endif() endif() -message(STATUS "Finding and/or providing ETL library") +message(STATUS "${MSG_PREFIX} Finding and/or providing ETL library") # Check whether the user has already installed ETL first find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET) @@ -182,7 +228,9 @@ target_include_directories(${LIB_FSFW_NAME} # Backwards comptability if(OS_FSFW AND NOT FSFW_OSAL) - message(WARNING "Please pass the FSFW OSAL as FSFW_OSAL instead of OS_FSFW") + message( + WARNING + "${MSG_PREFIX} Please pass the FSFW OSAL as FSFW_OSAL instead of OS_FSFW") set(FSFW_OSAL OS_FSFW) endif() @@ -198,7 +246,6 @@ if(NOT FSFW_OSAL) "host" CACHE STRING "OS abstraction layer used in the FSFW") endif() - endif() set(FSFW_OSAL_DEFINITION FSFW_OSAL_HOST) @@ -218,7 +265,9 @@ elseif(FSFW_OSAL STREQUAL rtems) set(FSFW_OSAL_RTEMS ON) else() message( - WARNING "Invalid operating system for FSFW specified! Setting to host..") + WARNING + "${MSG_PREFIX} Invalid operating system for FSFW specified! Setting to host.." + ) set(FSFW_OS_NAME "Host") set(OS_FSFW "host") endif() @@ -226,7 +275,9 @@ endif() configure_file(src/fsfw/FSFW.h.in fsfw/FSFW.h) configure_file(src/fsfw/FSFWVersion.h.in fsfw/FSFWVersion.h) -message(STATUS "Compiling FSFW for the ${FSFW_OS_NAME} operating system.") +message( + STATUS "${MSG_PREFIX} Compiling FSFW for the ${FSFW_OS_NAME} operating system" +) add_subdirectory(src) add_subdirectory(tests) @@ -298,8 +349,12 @@ endif() if(NOT FSFW_CONFIG_PATH) set(DEF_CONF_PATH misc/defaultcfg/fsfwconfig) if(NOT FSFW_BUILD_DOCS) - message(WARNING "Flight Software Framework configuration path not set!") - message(WARNING "Setting default configuration from ${DEF_CONF_PATH} ..") + message( + WARNING + "${MSG_PREFIX} Flight Software Framework configuration path not set") + message( + WARNING + "${MSG_PREFIX} Setting default configuration from ${DEF_CONF_PATH} ..") endif() add_subdirectory(${DEF_CONF_PATH}) set(FSFW_CONFIG_PATH ${DEF_CONF_PATH}) diff --git a/FSFWVersion.h.in b/FSFWVersion.h.in new file mode 100644 index 00000000..e69de29b diff --git a/cmake/FsfwHelpers.cmake b/cmake/FsfwHelpers.cmake new file mode 100644 index 00000000..3f22ebde --- /dev/null +++ b/cmake/FsfwHelpers.cmake @@ -0,0 +1,28 @@ +# Determines the git version with git describe and returns it by setting +# the GIT_INFO list in the parent scope. The list has the following entries +# 1. Full version string +# 2. Major version +# 3. Minor version +# 4. Revision +# 5. git SHA hash and commits since tag +function(determine_version_with_git) + include(GetGitRevisionDescription) + git_describe(VERSION ${ARGN}) + string(FIND ${VERSION} "." VALID_VERSION) + if(VALID_VERSION EQUAL -1) + message(WARNING "Version string ${VERSION} retrieved with git describe is invalid") + return() + endif() + # Parse the version information into pieces. + string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" _VERSION_MAJOR "${VERSION}") + string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" _VERSION_MINOR "${VERSION}") + string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" _VERSION_PATCH "${VERSION}") + string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+-(.*)" "\\1" VERSION_SHA1 "${VERSION}") + set(GIT_INFO ${VERSION}) + list(APPEND GIT_INFO ${_VERSION_MAJOR}) + list(APPEND GIT_INFO ${_VERSION_MINOR}) + list(APPEND GIT_INFO ${_VERSION_PATCH}) + list(APPEND GIT_INFO ${VERSION_SHA1}) + set(GIT_INFO ${GIT_INFO} PARENT_SCOPE) + message(STATUS "${MSG_PREFIX} Set git version info into GIT_INFO from the git tag ${VERSION}") +endfunction() diff --git a/cmake/cmake-modules/README.md b/cmake/cmake-modules/README.md new file mode 100644 index 00000000..b6355c3f --- /dev/null +++ b/cmake/cmake-modules/README.md @@ -0,0 +1,7 @@ +The files in the `bilke` folder were manually copy and pasted from the +[cmake-modules repository](https://github.com/bilke/cmake-modules). It was decided to do +this because only a small subset of its provided functions are needed. + +The files in the `rpavlik` folder were manually copy and pasted from the +[cmake-modules repository](https://github.com/rpavlik/cmake-modules). It was decided to do +this because only a small subset of its provided functions are needed. diff --git a/cmake/cmake-modules/bilke/CodeCoverage.cmake b/cmake/cmake-modules/bilke/CodeCoverage.cmake new file mode 100644 index 00000000..aef3d943 --- /dev/null +++ b/cmake/cmake-modules/bilke/CodeCoverage.cmake @@ -0,0 +1,719 @@ +# Copyright (c) 2012 - 2017, Lars Bilke +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# CHANGES: +# +# 2012-01-31, Lars Bilke +# - Enable Code Coverage +# +# 2013-09-17, Joakim Söderberg +# - Added support for Clang. +# - Some additional usage instructions. +# +# 2016-02-03, Lars Bilke +# - Refactored functions to use named parameters +# +# 2017-06-02, Lars Bilke +# - Merged with modified version from github.com/ufz/ogs +# +# 2019-05-06, Anatolii Kurotych +# - Remove unnecessary --coverage flag +# +# 2019-12-13, FeRD (Frank Dana) +# - Deprecate COVERAGE_LCOVR_EXCLUDES and COVERAGE_GCOVR_EXCLUDES lists in favor +# of tool-agnostic COVERAGE_EXCLUDES variable, or EXCLUDE setup arguments. +# - CMake 3.4+: All excludes can be specified relative to BASE_DIRECTORY +# - All setup functions: accept BASE_DIRECTORY, EXCLUDE list +# - Set lcov basedir with -b argument +# - Add automatic --demangle-cpp in lcovr, if 'c++filt' is available (can be +# overridden with NO_DEMANGLE option in setup_target_for_coverage_lcovr().) +# - Delete output dir, .info file on 'make clean' +# - Remove Python detection, since version mismatches will break gcovr +# - Minor cleanup (lowercase function names, update examples...) +# +# 2019-12-19, FeRD (Frank Dana) +# - Rename Lcov outputs, make filtered file canonical, fix cleanup for targets +# +# 2020-01-19, Bob Apthorpe +# - Added gfortran support +# +# 2020-02-17, FeRD (Frank Dana) +# - Make all add_custom_target()s VERBATIM to auto-escape wildcard characters +# in EXCLUDEs, and remove manual escaping from gcovr targets +# +# 2021-01-19, Robin Mueller +# - Add CODE_COVERAGE_VERBOSE option which will allow to print out commands which are run +# - Added the option for users to set the GCOVR_ADDITIONAL_ARGS variable to supply additional +# flags to the gcovr command +# +# 2020-05-04, Mihchael Davis +# - Add -fprofile-abs-path to make gcno files contain absolute paths +# - Fix BASE_DIRECTORY not working when defined +# - Change BYPRODUCT from folder to index.html to stop ninja from complaining about double defines +# +# 2021-05-10, Martin Stump +# - Check if the generator is multi-config before warning about non-Debug builds +# +# 2022-02-22, Marko Wehle +# - Change gcovr output from -o for --xml and --html output respectively. +# This will allow for Multiple Output Formats at the same time by making use of GCOVR_ADDITIONAL_ARGS, e.g. GCOVR_ADDITIONAL_ARGS "--txt". +# +# USAGE: +# +# 1. Copy this file into your cmake modules path. +# +# 2. Add the following line to your CMakeLists.txt (best inside an if-condition +# using a CMake option() to enable it just optionally): +# include(CodeCoverage) +# +# 3. Append necessary compiler flags for all supported source files: +# append_coverage_compiler_flags() +# Or for specific target: +# append_coverage_compiler_flags_to_target(YOUR_TARGET_NAME) +# +# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og +# +# 4. If you need to exclude additional directories from the report, specify them +# using full paths in the COVERAGE_EXCLUDES variable before calling +# setup_target_for_coverage_*(). +# Example: +# set(COVERAGE_EXCLUDES +# '${PROJECT_SOURCE_DIR}/src/dir1/*' +# '/path/to/my/src/dir2/*') +# Or, use the EXCLUDE argument to setup_target_for_coverage_*(). +# Example: +# setup_target_for_coverage_lcov( +# NAME coverage +# EXECUTABLE testrunner +# EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*") +# +# 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set +# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR) +# Example: +# set(COVERAGE_EXCLUDES "dir1/*") +# setup_target_for_coverage_gcovr_html( +# NAME coverage +# EXECUTABLE testrunner +# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src" +# EXCLUDE "dir2/*") +# +# 5. Use the functions described below to create a custom make target which +# runs your test executable and produces a code coverage report. +# +# 6. Build a Debug build: +# cmake -DCMAKE_BUILD_TYPE=Debug .. +# make +# make my_coverage_target +# + +include(CMakeParseArguments) + +option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE) + +# Check prereqs +find_program( GCOV_PATH gcov ) +find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl) +find_program( FASTCOV_PATH NAMES fastcov fastcov.py ) +find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat ) +find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test) +find_program( CPPFILT_PATH NAMES c++filt ) + +if(NOT GCOV_PATH) + message(FATAL_ERROR "gcov not found! Aborting...") +endif() # NOT GCOV_PATH + +get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) +list(GET LANGUAGES 0 LANG) + +if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3) + message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") + endif() +elseif(NOT CMAKE_COMPILER_IS_GNUCXX) + if("${CMAKE_Fortran_COMPILER_ID}" MATCHES "[Ff]lang") + # Do nothing; exit conditional without error if true + elseif("${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU") + # Do nothing; exit conditional without error if true + else() + message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") + endif() +endif() + +set(COVERAGE_COMPILER_FLAGS "-g -fprofile-arcs -ftest-coverage" + CACHE INTERNAL "") +if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag(-fprofile-abs-path HAVE_fprofile_abs_path) + if(HAVE_fprofile_abs_path) + set(COVERAGE_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path") + endif() +endif() + +set(CMAKE_Fortran_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the Fortran compiler during coverage builds." + FORCE ) +set(CMAKE_CXX_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the C++ compiler during coverage builds." + FORCE ) +set(CMAKE_C_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the C compiler during coverage builds." + FORCE ) +set(CMAKE_EXE_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used for linking binaries during coverage builds." + FORCE ) +set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used by the shared libraries linker during coverage builds." + FORCE ) +mark_as_advanced( + CMAKE_Fortran_FLAGS_COVERAGE + CMAKE_CXX_FLAGS_COVERAGE + CMAKE_C_FLAGS_COVERAGE + CMAKE_EXE_LINKER_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) + +get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)) + message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading") +endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG) + +if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") + link_libraries(gcov) +endif() + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# setup_target_for_coverage_lcov( +# NAME testrunner_coverage # New target name +# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES testrunner # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative +# # to BASE_DIRECTORY, with CMake 3.4+) +# NO_DEMANGLE # Don't demangle C++ symbols +# # even if c++filt is found +# ) +function(setup_target_for_coverage_lcov) + + set(options NO_DEMANGLE) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT LCOV_PATH) + message(FATAL_ERROR "lcov not found! Aborting...") + endif() # NOT LCOV_PATH + + if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Aborting...") + endif() # NOT GENHTML_PATH + + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(DEFINED Coverage_BASE_DIRECTORY) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (CMake 3.4+: Also compute absolute paths) + set(LCOV_EXCLUDES "") + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_LCOV_EXCLUDES}) + if(CMAKE_VERSION VERSION_GREATER 3.4) + get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR}) + endif() + list(APPEND LCOV_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES LCOV_EXCLUDES) + + # Conditional arguments + if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE}) + set(GENHTML_EXTRA_ARGS "--demangle-cpp") + endif() + + # Setting up commands which will be run to generate coverage data. + # Cleanup lcov + set(LCOV_CLEAN_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory . + -b ${BASEDIR} --zerocounters + ) + # Create baseline to make sure untouched files show up in the report + set(LCOV_BASELINE_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -b + ${BASEDIR} -o ${Coverage_NAME}.base + ) + # Run tests + set(LCOV_EXEC_TESTS_CMD + ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} + ) + # Capturing lcov counters and generating report + set(LCOV_CAPTURE_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b + ${BASEDIR} --capture --output-file ${Coverage_NAME}.capture + ) + # add baseline counters + set(LCOV_BASELINE_COUNT_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base + -a ${Coverage_NAME}.capture --output-file ${Coverage_NAME}.total + ) + # filter collected data to final coverage report + set(LCOV_FILTER_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove + ${Coverage_NAME}.total ${LCOV_EXCLUDES} --output-file ${Coverage_NAME}.info + ) + # Generate HTML output + set(LCOV_GEN_HTML_CMD + ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o + ${Coverage_NAME} ${Coverage_NAME}.info + ) + + + if(CODE_COVERAGE_VERBOSE) + message(STATUS "Executed command report") + message(STATUS "Command to clean up lcov: ") + string(REPLACE ";" " " LCOV_CLEAN_CMD_SPACED "${LCOV_CLEAN_CMD}") + message(STATUS "${LCOV_CLEAN_CMD_SPACED}") + + message(STATUS "Command to create baseline: ") + string(REPLACE ";" " " LCOV_BASELINE_CMD_SPACED "${LCOV_BASELINE_CMD}") + message(STATUS "${LCOV_BASELINE_CMD_SPACED}") + + message(STATUS "Command to run the tests: ") + string(REPLACE ";" " " LCOV_EXEC_TESTS_CMD_SPACED "${LCOV_EXEC_TESTS_CMD}") + message(STATUS "${LCOV_EXEC_TESTS_CMD_SPACED}") + + message(STATUS "Command to capture counters and generate report: ") + string(REPLACE ";" " " LCOV_CAPTURE_CMD_SPACED "${LCOV_CAPTURE_CMD}") + message(STATUS "${LCOV_CAPTURE_CMD_SPACED}") + + message(STATUS "Command to add baseline counters: ") + string(REPLACE ";" " " LCOV_BASELINE_COUNT_CMD_SPACED "${LCOV_BASELINE_COUNT_CMD}") + message(STATUS "${LCOV_BASELINE_COUNT_CMD_SPACED}") + + message(STATUS "Command to filter collected data: ") + string(REPLACE ";" " " LCOV_FILTER_CMD_SPACED "${LCOV_FILTER_CMD}") + message(STATUS "${LCOV_FILTER_CMD_SPACED}") + + message(STATUS "Command to generate lcov HTML output: ") + string(REPLACE ";" " " LCOV_GEN_HTML_CMD_SPACED "${LCOV_GEN_HTML_CMD}") + message(STATUS "${LCOV_GEN_HTML_CMD_SPACED}") + endif() + + # Setup target + add_custom_target(${Coverage_NAME} + COMMAND ${LCOV_CLEAN_CMD} + COMMAND ${LCOV_BASELINE_CMD} + COMMAND ${LCOV_EXEC_TESTS_CMD} + COMMAND ${LCOV_CAPTURE_CMD} + COMMAND ${LCOV_BASELINE_COUNT_CMD} + COMMAND ${LCOV_FILTER_CMD} + COMMAND ${LCOV_GEN_HTML_CMD} + + # Set output files as GENERATED (will be removed on 'make clean') + BYPRODUCTS + ${Coverage_NAME}.base + ${Coverage_NAME}.capture + ${Coverage_NAME}.total + ${Coverage_NAME}.info + ${Coverage_NAME}/index.html + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + VERBATIM # Protect arguments to commands + COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." + ) + + # Show where to find the lcov info report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." + ) + +endfunction() # setup_target_for_coverage_lcov + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# setup_target_for_coverage_gcovr_xml( +# NAME ctest_coverage # New target name +# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES executable_target # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative +# # to BASE_DIRECTORY, with CMake 3.4+) +# ) +# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the +# GCVOR command. +function(setup_target_for_coverage_gcovr_xml) + + set(options NONE) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT GCOVR_PATH) + message(FATAL_ERROR "gcovr not found! Aborting...") + endif() # NOT GCOVR_PATH + + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(DEFINED Coverage_BASE_DIRECTORY) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (CMake 3.4+: Also compute absolute paths) + set(GCOVR_EXCLUDES "") + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES}) + if(CMAKE_VERSION VERSION_GREATER 3.4) + get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR}) + endif() + list(APPEND GCOVR_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES GCOVR_EXCLUDES) + + # Combine excludes to several -e arguments + set(GCOVR_EXCLUDE_ARGS "") + foreach(EXCLUDE ${GCOVR_EXCLUDES}) + list(APPEND GCOVR_EXCLUDE_ARGS "-e") + list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}") + endforeach() + + # Set up commands which will be run to generate coverage data + # Run tests + set(GCOVR_XML_EXEC_TESTS_CMD + ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} + ) + # Running gcovr + set(GCOVR_XML_CMD + ${GCOVR_PATH} --xml ${Coverage_NAME}.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS} + ${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR} + ) + + if(CODE_COVERAGE_VERBOSE) + message(STATUS "Executed command report") + + message(STATUS "Command to run tests: ") + string(REPLACE ";" " " GCOVR_XML_EXEC_TESTS_CMD_SPACED "${GCOVR_XML_EXEC_TESTS_CMD}") + message(STATUS "${GCOVR_XML_EXEC_TESTS_CMD_SPACED}") + + message(STATUS "Command to generate gcovr XML coverage data: ") + string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}") + message(STATUS "${GCOVR_XML_CMD_SPACED}") + endif() + + add_custom_target(${Coverage_NAME} + COMMAND ${GCOVR_XML_EXEC_TESTS_CMD} + COMMAND ${GCOVR_XML_CMD} + + BYPRODUCTS ${Coverage_NAME}.xml + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + VERBATIM # Protect arguments to commands + COMMENT "Running gcovr to produce Cobertura code coverage report." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml." + ) +endfunction() # setup_target_for_coverage_gcovr_xml + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# setup_target_for_coverage_gcovr_html( +# NAME ctest_coverage # New target name +# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES executable_target # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative +# # to BASE_DIRECTORY, with CMake 3.4+) +# ) +# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the +# GCVOR command. +function(setup_target_for_coverage_gcovr_html) + + set(options NONE) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT GCOVR_PATH) + message(FATAL_ERROR "gcovr not found! Aborting...") + endif() # NOT GCOVR_PATH + + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(DEFINED Coverage_BASE_DIRECTORY) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (CMake 3.4+: Also compute absolute paths) + set(GCOVR_EXCLUDES "") + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES}) + if(CMAKE_VERSION VERSION_GREATER 3.4) + get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR}) + endif() + list(APPEND GCOVR_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES GCOVR_EXCLUDES) + + # Combine excludes to several -e arguments + set(GCOVR_EXCLUDE_ARGS "") + foreach(EXCLUDE ${GCOVR_EXCLUDES}) + list(APPEND GCOVR_EXCLUDE_ARGS "-e") + list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}") + endforeach() + + # Set up commands which will be run to generate coverage data + # Run tests + set(GCOVR_HTML_EXEC_TESTS_CMD + ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} + ) + # Create folder + set(GCOVR_HTML_FOLDER_CMD + ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME} + ) + # Running gcovr + set(GCOVR_HTML_CMD + ${GCOVR_PATH} --html ${Coverage_NAME}/index.html --html-details -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS} + ${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR} + ) + + if(CODE_COVERAGE_VERBOSE) + message(STATUS "Executed command report") + + message(STATUS "Command to run tests: ") + string(REPLACE ";" " " GCOVR_HTML_EXEC_TESTS_CMD_SPACED "${GCOVR_HTML_EXEC_TESTS_CMD}") + message(STATUS "${GCOVR_HTML_EXEC_TESTS_CMD_SPACED}") + + message(STATUS "Command to create a folder: ") + string(REPLACE ";" " " GCOVR_HTML_FOLDER_CMD_SPACED "${GCOVR_HTML_FOLDER_CMD}") + message(STATUS "${GCOVR_HTML_FOLDER_CMD_SPACED}") + + message(STATUS "Command to generate gcovr HTML coverage data: ") + string(REPLACE ";" " " GCOVR_HTML_CMD_SPACED "${GCOVR_HTML_CMD}") + message(STATUS "${GCOVR_HTML_CMD_SPACED}") + endif() + + add_custom_target(${Coverage_NAME} + COMMAND ${GCOVR_HTML_EXEC_TESTS_CMD} + COMMAND ${GCOVR_HTML_FOLDER_CMD} + COMMAND ${GCOVR_HTML_CMD} + + BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html # report directory + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + VERBATIM # Protect arguments to commands + COMMENT "Running gcovr to produce HTML code coverage report." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." + ) + +endfunction() # setup_target_for_coverage_gcovr_html + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# setup_target_for_coverage_fastcov( +# NAME testrunner_coverage # New target name +# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES testrunner # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/" "src/dir2/" # Patterns to exclude. +# NO_DEMANGLE # Don't demangle C++ symbols +# # even if c++filt is found +# SKIP_HTML # Don't create html report +# POST_CMD perl -i -pe s!${PROJECT_SOURCE_DIR}/!!g ctest_coverage.json # E.g. for stripping source dir from file paths +# ) +function(setup_target_for_coverage_fastcov) + + set(options NO_DEMANGLE SKIP_HTML) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES FASTCOV_ARGS GENHTML_ARGS POST_CMD) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT FASTCOV_PATH) + message(FATAL_ERROR "fastcov not found! Aborting...") + endif() + + if(NOT Coverage_SKIP_HTML AND NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Aborting...") + endif() + + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(Coverage_BASE_DIRECTORY) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (Patterns, not paths, for fastcov) + set(FASTCOV_EXCLUDES "") + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_FASTCOV_EXCLUDES}) + list(APPEND FASTCOV_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES FASTCOV_EXCLUDES) + + # Conditional arguments + if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE}) + set(GENHTML_EXTRA_ARGS "--demangle-cpp") + endif() + + # Set up commands which will be run to generate coverage data + set(FASTCOV_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}) + + set(FASTCOV_CAPTURE_CMD ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH} + --search-directory ${BASEDIR} + --process-gcno + --output ${Coverage_NAME}.json + --exclude ${FASTCOV_EXCLUDES} + --exclude ${FASTCOV_EXCLUDES} + ) + + set(FASTCOV_CONVERT_CMD ${FASTCOV_PATH} + -C ${Coverage_NAME}.json --lcov --output ${Coverage_NAME}.info + ) + + if(Coverage_SKIP_HTML) + set(FASTCOV_HTML_CMD ";") + else() + set(FASTCOV_HTML_CMD ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} + -o ${Coverage_NAME} ${Coverage_NAME}.info + ) + endif() + + set(FASTCOV_POST_CMD ";") + if(Coverage_POST_CMD) + set(FASTCOV_POST_CMD ${Coverage_POST_CMD}) + endif() + + if(CODE_COVERAGE_VERBOSE) + message(STATUS "Code coverage commands for target ${Coverage_NAME} (fastcov):") + + message(" Running tests:") + string(REPLACE ";" " " FASTCOV_EXEC_TESTS_CMD_SPACED "${FASTCOV_EXEC_TESTS_CMD}") + message(" ${FASTCOV_EXEC_TESTS_CMD_SPACED}") + + message(" Capturing fastcov counters and generating report:") + string(REPLACE ";" " " FASTCOV_CAPTURE_CMD_SPACED "${FASTCOV_CAPTURE_CMD}") + message(" ${FASTCOV_CAPTURE_CMD_SPACED}") + + message(" Converting fastcov .json to lcov .info:") + string(REPLACE ";" " " FASTCOV_CONVERT_CMD_SPACED "${FASTCOV_CONVERT_CMD}") + message(" ${FASTCOV_CONVERT_CMD_SPACED}") + + if(NOT Coverage_SKIP_HTML) + message(" Generating HTML report: ") + string(REPLACE ";" " " FASTCOV_HTML_CMD_SPACED "${FASTCOV_HTML_CMD}") + message(" ${FASTCOV_HTML_CMD_SPACED}") + endif() + if(Coverage_POST_CMD) + message(" Running post command: ") + string(REPLACE ";" " " FASTCOV_POST_CMD_SPACED "${FASTCOV_POST_CMD}") + message(" ${FASTCOV_POST_CMD_SPACED}") + endif() + endif() + + # Setup target + add_custom_target(${Coverage_NAME} + + # Cleanup fastcov + COMMAND ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH} + --search-directory ${BASEDIR} + --zerocounters + + COMMAND ${FASTCOV_EXEC_TESTS_CMD} + COMMAND ${FASTCOV_CAPTURE_CMD} + COMMAND ${FASTCOV_CONVERT_CMD} + COMMAND ${FASTCOV_HTML_CMD} + COMMAND ${FASTCOV_POST_CMD} + + # Set output files as GENERATED (will be removed on 'make clean') + BYPRODUCTS + ${Coverage_NAME}.info + ${Coverage_NAME}.json + ${Coverage_NAME}/index.html # report directory + + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + VERBATIM # Protect arguments to commands + COMMENT "Resetting code coverage counters to zero. Processing code coverage counters and generating report." + ) + + set(INFO_MSG "fastcov code coverage info report saved in ${Coverage_NAME}.info and ${Coverage_NAME}.json.") + if(NOT Coverage_SKIP_HTML) + string(APPEND INFO_MSG " Open ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html in your browser to view the coverage report.") + endif() + # Show where to find the fastcov info report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo ${INFO_MSG} + ) + +endfunction() # setup_target_for_coverage_fastcov + +function(append_coverage_compiler_flags) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}") +endfunction() # append_coverage_compiler_flags + +# Setup coverage for specific library +function(append_coverage_compiler_flags_to_target name) + target_compile_options(${name} + PRIVATE ${COVERAGE_COMPILER_FLAGS}) +endfunction() diff --git a/cmake/cmake-modules/bilke/LICENSE_1_0.txt b/cmake/cmake-modules/bilke/LICENSE_1_0.txt new file mode 100644 index 00000000..36b7cd93 --- /dev/null +++ b/cmake/cmake-modules/bilke/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/cmake/cmake-modules/rpavlik/GetGitRevisionDescription.cmake b/cmake/cmake-modules/rpavlik/GetGitRevisionDescription.cmake new file mode 100644 index 00000000..69ef78b2 --- /dev/null +++ b/cmake/cmake-modules/rpavlik/GetGitRevisionDescription.cmake @@ -0,0 +1,284 @@ +# - Returns a version string from Git +# +# These functions force a re-configure on each git commit so that you can +# trust the values of the variables in your build system. +# +# get_git_head_revision( [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR]) +# +# Returns the refspec and sha hash of the current head revision +# +# git_describe( [ ...]) +# +# Returns the results of git describe on the source tree, and adjusting +# the output so that it tests false if an error occurs. +# +# git_describe_working_tree( [ ...]) +# +# Returns the results of git describe on the working tree (--dirty option), +# and adjusting the output so that it tests false if an error occurs. +# +# git_get_exact_tag( [ ...]) +# +# Returns the results of git describe --exact-match on the source tree, +# and adjusting the output so that it tests false if there was no exact +# matching tag. +# +# git_local_changes() +# +# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes. +# Uses the return code of "git diff-index --quiet HEAD --". +# Does not regard untracked files. +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2020 Ryan Pavlik +# http://academic.cleardefinition.com +# +# Copyright 2009-2013, Iowa State University. +# Copyright 2013-2020, Ryan Pavlik +# Copyright 2013-2020, Contributors +# SPDX-License-Identifier: BSL-1.0 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if(__get_git_revision_description) + return() +endif() +set(__get_git_revision_description YES) + +# We must run the following at "include" time, not at function call time, +# to find the path to this module rather than the path to a calling list file +get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) + +# Function _git_find_closest_git_dir finds the next closest .git directory +# that is part of any directory in the path defined by _start_dir. +# The result is returned in the parent scope variable whose name is passed +# as variable _git_dir_var. If no .git directory can be found, the +# function returns an empty string via _git_dir_var. +# +# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and +# neither foo nor bar contain a file/directory .git. This wil return +# C:/bla/.git +# +function(_git_find_closest_git_dir _start_dir _git_dir_var) + set(cur_dir "${_start_dir}") + set(git_dir "${_start_dir}/.git") + while(NOT EXISTS "${git_dir}") + # .git dir not found, search parent directories + set(git_previous_parent "${cur_dir}") + get_filename_component(cur_dir "${cur_dir}" DIRECTORY) + if(cur_dir STREQUAL git_previous_parent) + # We have reached the root directory, we are not in git + set(${_git_dir_var} + "" + PARENT_SCOPE) + return() + endif() + set(git_dir "${cur_dir}/.git") + endwhile() + set(${_git_dir_var} + "${git_dir}" + PARENT_SCOPE) +endfunction() + +function(get_git_head_revision _refspecvar _hashvar) + _git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR) + + if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR") + set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE) + else() + set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE) + endif() + if(NOT "${GIT_DIR}" STREQUAL "") + file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}" + "${GIT_DIR}") + if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR) + # We've gone above the CMake root dir. + set(GIT_DIR "") + endif() + endif() + if("${GIT_DIR}" STREQUAL "") + set(${_refspecvar} + "GITDIR-NOTFOUND" + PARENT_SCOPE) + set(${_hashvar} + "GITDIR-NOTFOUND" + PARENT_SCOPE) + return() + endif() + + # Check if the current source dir is a git submodule or a worktree. + # In both cases .git is a file instead of a directory. + # + if(NOT IS_DIRECTORY ${GIT_DIR}) + # The following git command will return a non empty string that + # points to the super project working tree if the current + # source dir is inside a git submodule. + # Otherwise the command will return an empty string. + # + execute_process( + COMMAND "${GIT_EXECUTABLE}" rev-parse + --show-superproject-working-tree + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + OUTPUT_VARIABLE out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT "${out}" STREQUAL "") + # If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule + file(READ ${GIT_DIR} submodule) + string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE + ${submodule}) + string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE) + get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) + get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} + ABSOLUTE) + set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD") + else() + # GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree + file(READ ${GIT_DIR} worktree_ref) + # The .git directory contains a path to the worktree information directory + # inside the parent git repo of the worktree. + # + string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir + ${worktree_ref}) + string(STRIP ${git_worktree_dir} git_worktree_dir) + _git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR) + set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD") + endif() + else() + set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD") + endif() + set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") + if(NOT EXISTS "${GIT_DATA}") + file(MAKE_DIRECTORY "${GIT_DATA}") + endif() + + if(NOT EXISTS "${HEAD_SOURCE_FILE}") + return() + endif() + set(HEAD_FILE "${GIT_DATA}/HEAD") + configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY) + + configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" + "${GIT_DATA}/grabRef.cmake" @ONLY) + include("${GIT_DATA}/grabRef.cmake") + + set(${_refspecvar} + "${HEAD_REF}" + PARENT_SCOPE) + set(${_hashvar} + "${HEAD_HASH}" + PARENT_SCOPE) +endfunction() + +function(git_describe _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} + "GIT-NOTFOUND" + PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} + "HEAD-HASH-NOTFOUND" + PARENT_SCOPE) + return() + endif() + + # TODO sanitize + #if((${ARGN}" MATCHES "&&") OR + # (ARGN MATCHES "||") OR + # (ARGN MATCHES "\\;")) + # message("Please report the following error to the project!") + # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") + #endif() + + #message(STATUS "Arguments to execute_process: ${ARGN}") + + execute_process( + COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE res + OUTPUT_VARIABLE out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${_var} + "${out}" + PARENT_SCOPE) +endfunction() + +function(git_describe_working_tree _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + if(NOT GIT_FOUND) + set(${_var} + "GIT-NOTFOUND" + PARENT_SCOPE) + return() + endif() + + execute_process( + COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE res + OUTPUT_VARIABLE out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${_var} + "${out}" + PARENT_SCOPE) +endfunction() + +function(git_get_exact_tag _var) + git_describe(out --exact-match ${ARGN}) + set(${_var} + "${out}" + PARENT_SCOPE) +endfunction() + +function(git_local_changes _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} + "GIT-NOTFOUND" + PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} + "HEAD-HASH-NOTFOUND" + PARENT_SCOPE) + return() + endif() + + execute_process( + COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD -- + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE res + OUTPUT_VARIABLE out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(res EQUAL 0) + set(${_var} + "CLEAN" + PARENT_SCOPE) + else() + set(${_var} + "DIRTY" + PARENT_SCOPE) + endif() +endfunction() diff --git a/cmake/cmake-modules/rpavlik/GetGitRevisionDescription.cmake.in b/cmake/cmake-modules/rpavlik/GetGitRevisionDescription.cmake.in new file mode 100644 index 00000000..66eee637 --- /dev/null +++ b/cmake/cmake-modules/rpavlik/GetGitRevisionDescription.cmake.in @@ -0,0 +1,43 @@ +# +# Internal file for GetGitRevisionDescription.cmake +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright 2009-2012, Iowa State University +# Copyright 2011-2015, Contributors +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# SPDX-License-Identifier: BSL-1.0 + +set(HEAD_HASH) + +file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) + +string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) +if(HEAD_CONTENTS MATCHES "ref") + # named branch + string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") + if(EXISTS "@GIT_DIR@/${HEAD_REF}") + configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) + else() + configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) + file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) + if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") + set(HEAD_HASH "${CMAKE_MATCH_1}") + endif() + endif() +else() + # detached HEAD + configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) +endif() + +if(NOT HEAD_HASH) + file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) + string(STRIP "${HEAD_HASH}" HEAD_HASH) +endif() diff --git a/cmake/cmake-modules/rpavlik/LICENSES/BSD-3-Clause.txt b/cmake/cmake-modules/rpavlik/LICENSES/BSD-3-Clause.txt new file mode 100644 index 00000000..0741db78 --- /dev/null +++ b/cmake/cmake-modules/rpavlik/LICENSES/BSD-3-Clause.txt @@ -0,0 +1,26 @@ +Copyright (c) . All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/cmake/cmake-modules/rpavlik/LICENSES/BSL-1.0.txt b/cmake/cmake-modules/rpavlik/LICENSES/BSL-1.0.txt new file mode 100644 index 00000000..cff35365 --- /dev/null +++ b/cmake/cmake-modules/rpavlik/LICENSES/BSL-1.0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, execute, +and transmit the Software, and to prepare derivative works of the Software, +and to permit third-parties to whom the Software is furnished to do so, all +subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, must +be included in all copies of the Software, in whole or in part, and all derivative +works of the Software, unless such copies or derivative works are solely in +the form of machine-executable object code generated by a source language +processor. + +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES +OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/cmake/cmake-modules/rpavlik/LICENSE_1_0.txt b/cmake/cmake-modules/rpavlik/LICENSE_1_0.txt new file mode 100644 index 00000000..36b7cd93 --- /dev/null +++ b/cmake/cmake-modules/rpavlik/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/hal/src/fsfw_hal/linux/uart/UartComIF.cpp b/hal/src/fsfw_hal/linux/uart/UartComIF.cpp index 72c79df6..f77bdeae 100644 --- a/hal/src/fsfw_hal/linux/uart/UartComIF.cpp +++ b/hal/src/fsfw_hal/linux/uart/UartComIF.cpp @@ -314,7 +314,7 @@ void UartComIF::configureBaudrate(struct termios* options, UartCookie* uartCooki cfsetispeed(options, B4000000); cfsetospeed(options, B4000000); break; -#endif // ! __APPLE__ +#endif // ! __APPLE__ default: #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl; diff --git a/scripts/auto-formatter.sh b/scripts/auto-formatter.sh index 7b67ee9d..405d1268 100755 --- a/scripts/auto-formatter.sh +++ b/scripts/auto-formatter.sh @@ -4,9 +4,10 @@ if [[ ! -f README.md ]]; then fi cmake_fmt="cmake-format" +file_selectors="-iname CMakeLists.txt" if command -v ${cmake_fmt} &> /dev/null; then - cmake_fmt_cmd="${cmake_fmt} -i CMakeLists.txt" - eval ${cmake_fmt_cmd} + ${cmake_fmt} -i CMakeLists.txt + find ./src ${file_selectors} | xargs ${cmake_fmt} -i else echo "No ${cmake_fmt} tool found, not formatting CMake files" fi @@ -14,9 +15,9 @@ fi cpp_format="clang-format" file_selectors="-iname *.h -o -iname *.cpp -o -iname *.c -o -iname *.tpp" if command -v ${cpp_format} &> /dev/null; then - find ./src ${file_selectors} | xargs clang-format --style=file -i - find ./hal ${file_selectors} | xargs clang-format --style=file -i - find ./tests ${file_selectors} | xargs clang-format --style=file -i + find ./src ${file_selectors} | xargs ${cpp_format} --style=file -i + find ./hal ${file_selectors} | xargs ${cpp_format} --style=file -i + find ./tests ${file_selectors} | xargs ${cpp_format} --style=file -i else echo "No ${cpp_format} tool found, not formatting C++/C files" fi diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ed2f2522..34f21c2f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,9 +1,6 @@ -target_include_directories(${LIB_FSFW_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} -) +target_include_directories(${LIB_FSFW_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(${LIB_FSFW_NAME} INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR} -) +target_include_directories(${LIB_FSFW_NAME} + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(fsfw) diff --git a/src/fsfw/CMakeLists.txt b/src/fsfw/CMakeLists.txt index efb9f6c7..1daad714 100644 --- a/src/fsfw/CMakeLists.txt +++ b/src/fsfw/CMakeLists.txt @@ -1,6 +1,4 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - version.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE version.cpp) # Core @@ -37,22 +35,22 @@ add_subdirectory(tmtcservices) # Optional if(FSFW_ADD_MONITORING) -add_subdirectory(monitoring) + add_subdirectory(monitoring) endif() if(FSFW_ADD_PUS) - add_subdirectory(pus) + add_subdirectory(pus) endif() if(FSFW_ADD_TMSTORAGE) - add_subdirectory(tmstorage) + add_subdirectory(tmstorage) endif() if(FSFW_ADD_COORDINATES) - add_subdirectory(coordinates) + add_subdirectory(coordinates) endif() if(FSFW_ADD_RMAP) - add_subdirectory(rmap) + add_subdirectory(rmap) endif() if(FSFW_ADD_DATALINKLAYER) - add_subdirectory(datalinklayer) + add_subdirectory(datalinklayer) endif() # OSAL diff --git a/src/fsfw/FSFWVersion.h.in b/src/fsfw/FSFWVersion.h.in index 19a56214..caff1efb 100644 --- a/src/fsfw/FSFWVersion.h.in +++ b/src/fsfw/FSFWVersion.h.in @@ -1,9 +1,11 @@ #ifndef FSFW_VERSION_H_ #define FSFW_VERSION_H_ -// Versioning is kept in project CMakeLists.txt file -#define FSFW_VERSION_MAJOR @FSFW_VERSION@ -#define FSFW_VERSION_MINOR @FSFW_SUBVERSION@ -#define FSFW_VERSION_REVISION @FSFW_REVISION@ +// Versioning is managed in project CMakeLists.txt file +static constexpr int FSFW_VERSION_MAJOR = @FSFW_VERSION@; +static constexpr int FSFW_VERSION_MINOR = @FSFW_SUBVERSION@; +static constexpr int FSFW_VERSION_REVISION = @FSFW_REVISION@; +// Also contains CST (Commits since tag) information +static const char FSFW_VCS_INFO[] = "@FSFW_VCS_INFO@"; #endif /* FSFW_VERSION_H_ */ diff --git a/src/fsfw/action/CMakeLists.txt b/src/fsfw/action/CMakeLists.txt index f9ac451d..7fb397af 100644 --- a/src/fsfw/action/CMakeLists.txt +++ b/src/fsfw/action/CMakeLists.txt @@ -1,7 +1,3 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - ActionHelper.cpp - ActionMessage.cpp - CommandActionHelper.cpp - SimpleActionHelper.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} PRIVATE ActionHelper.cpp ActionMessage.cpp + CommandActionHelper.cpp SimpleActionHelper.cpp) diff --git a/src/fsfw/cfdp/CMakeLists.txt b/src/fsfw/cfdp/CMakeLists.txt index 908dc32a..0b926a9a 100644 --- a/src/fsfw/cfdp/CMakeLists.txt +++ b/src/fsfw/cfdp/CMakeLists.txt @@ -1,7 +1,4 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - CFDPHandler.cpp - CFDPMessage.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE CFDPHandler.cpp CFDPMessage.cpp) add_subdirectory(pdu) add_subdirectory(tlv) diff --git a/src/fsfw/cfdp/pdu/CMakeLists.txt b/src/fsfw/cfdp/pdu/CMakeLists.txt index 931db306..4f345bdc 100644 --- a/src/fsfw/cfdp/pdu/CMakeLists.txt +++ b/src/fsfw/cfdp/pdu/CMakeLists.txt @@ -1,32 +1,30 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - PduConfig.cpp - VarLenField.cpp - HeaderSerializer.cpp - HeaderDeserializer.cpp - FileDirectiveDeserializer.cpp - FileDirectiveSerializer.cpp - - AckInfo.cpp - AckPduSerializer.cpp - AckPduDeserializer.cpp - EofInfo.cpp - EofPduSerializer.cpp - EofPduDeserializer.cpp - NakInfo.cpp - NakPduSerializer.cpp - NakPduDeserializer.cpp - FinishedInfo.cpp - FinishedPduSerializer.cpp - FinishedPduDeserializer.cpp - MetadataInfo.cpp - MetadataPduSerializer.cpp - MetadataPduDeserializer.cpp - KeepAlivePduSerializer.cpp - KeepAlivePduDeserializer.cpp - PromptPduSerializer.cpp - PromptPduDeserializer.cpp - - FileDataSerializer.cpp - FileDataDeserializer.cpp - FileDataInfo.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE PduConfig.cpp + VarLenField.cpp + HeaderSerializer.cpp + HeaderDeserializer.cpp + FileDirectiveDeserializer.cpp + FileDirectiveSerializer.cpp + AckInfo.cpp + AckPduSerializer.cpp + AckPduDeserializer.cpp + EofInfo.cpp + EofPduSerializer.cpp + EofPduDeserializer.cpp + NakInfo.cpp + NakPduSerializer.cpp + NakPduDeserializer.cpp + FinishedInfo.cpp + FinishedPduSerializer.cpp + FinishedPduDeserializer.cpp + MetadataInfo.cpp + MetadataPduSerializer.cpp + MetadataPduDeserializer.cpp + KeepAlivePduSerializer.cpp + KeepAlivePduDeserializer.cpp + PromptPduSerializer.cpp + PromptPduDeserializer.cpp + FileDataSerializer.cpp + FileDataDeserializer.cpp + FileDataInfo.cpp) diff --git a/src/fsfw/cfdp/tlv/CMakeLists.txt b/src/fsfw/cfdp/tlv/CMakeLists.txt index 24459cf8..cdf7b44a 100644 --- a/src/fsfw/cfdp/tlv/CMakeLists.txt +++ b/src/fsfw/cfdp/tlv/CMakeLists.txt @@ -1,10 +1,10 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - EntityIdTlv.cpp - FilestoreRequestTlv.cpp - FilestoreResponseTlv.cpp - Lv.cpp - Tlv.cpp - FlowLabelTlv.cpp - MessageToUserTlv.cpp - FaultHandlerOverrideTlv.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE EntityIdTlv.cpp + FilestoreRequestTlv.cpp + FilestoreResponseTlv.cpp + Lv.cpp + Tlv.cpp + FlowLabelTlv.cpp + MessageToUserTlv.cpp + FaultHandlerOverrideTlv.cpp) diff --git a/src/fsfw/container/CMakeLists.txt b/src/fsfw/container/CMakeLists.txt index 13eced1d..52087ff0 100644 --- a/src/fsfw/container/CMakeLists.txt +++ b/src/fsfw/container/CMakeLists.txt @@ -1,5 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - SharedRingBuffer.cpp - SimpleRingBuffer.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE SharedRingBuffer.cpp + SimpleRingBuffer.cpp) diff --git a/src/fsfw/container/FIFOBase.tpp b/src/fsfw/container/FIFOBase.tpp index 2e6a3829..91804b6c 100644 --- a/src/fsfw/container/FIFOBase.tpp +++ b/src/fsfw/container/FIFOBase.tpp @@ -5,89 +5,88 @@ #error Include FIFOBase.h before FIFOBase.tpp! #endif -template -inline FIFOBase::FIFOBase(T* values, const size_t maxCapacity): - maxCapacity(maxCapacity), values(values){}; +template +inline FIFOBase::FIFOBase(T* values, const size_t maxCapacity) + : maxCapacity(maxCapacity), values(values){}; -template +template inline ReturnValue_t FIFOBase::insert(T value) { - if (full()) { - return FULL; - } else { - values[writeIndex] = value; - writeIndex = next(writeIndex); - ++currentSize; - return HasReturnvaluesIF::RETURN_OK; - } + if (full()) { + return FULL; + } else { + values[writeIndex] = value; + writeIndex = next(writeIndex); + ++currentSize; + return HasReturnvaluesIF::RETURN_OK; + } }; -template +template inline ReturnValue_t FIFOBase::retrieve(T* value) { - if (empty()) { - return EMPTY; - } else { - if (value == nullptr){ - return HasReturnvaluesIF::RETURN_FAILED; - } - *value = values[readIndex]; - readIndex = next(readIndex); - --currentSize; - return HasReturnvaluesIF::RETURN_OK; + if (empty()) { + return EMPTY; + } else { + if (value == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; } + *value = values[readIndex]; + readIndex = next(readIndex); + --currentSize; + return HasReturnvaluesIF::RETURN_OK; + } }; -template +template inline ReturnValue_t FIFOBase::peek(T* value) { - if(empty()) { - return EMPTY; - } else { - if (value == nullptr){ - return HasReturnvaluesIF::RETURN_FAILED; - } - *value = values[readIndex]; - return HasReturnvaluesIF::RETURN_OK; + if (empty()) { + return EMPTY; + } else { + if (value == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; } + *value = values[readIndex]; + return HasReturnvaluesIF::RETURN_OK; + } }; -template +template inline ReturnValue_t FIFOBase::pop() { - T value; - return this->retrieve(&value); + T value; + return this->retrieve(&value); }; -template +template inline bool FIFOBase::empty() { - return (currentSize == 0); + return (currentSize == 0); }; -template +template inline bool FIFOBase::full() { - return (currentSize == maxCapacity); + return (currentSize == maxCapacity); } -template +template inline size_t FIFOBase::size() { - return currentSize; + return currentSize; } -template +template inline size_t FIFOBase::next(size_t current) { - ++current; - if (current == maxCapacity) { - current = 0; - } - return current; + ++current; + if (current == maxCapacity) { + current = 0; + } + return current; } -template +template inline size_t FIFOBase::getMaxCapacity() const { - return maxCapacity; + return maxCapacity; } - -template -inline void FIFOBase::setContainer(T *data) { - this->values = data; +template +inline void FIFOBase::setContainer(T* data) { + this->values = data; } #endif diff --git a/src/fsfw/container/FixedArrayList.h b/src/fsfw/container/FixedArrayList.h index 11882537..fc8be393 100644 --- a/src/fsfw/container/FixedArrayList.h +++ b/src/fsfw/container/FixedArrayList.h @@ -12,6 +12,7 @@ template class FixedArrayList : public ArrayList { static_assert(MAX_SIZE <= std::numeric_limits::max(), "count_t is not large enough to hold MAX_SIZE"); + private: T data[MAX_SIZE]; diff --git a/src/fsfw/container/FixedOrderedMultimap.tpp b/src/fsfw/container/FixedOrderedMultimap.tpp index 294a161f..fd58bc44 100644 --- a/src/fsfw/container/FixedOrderedMultimap.tpp +++ b/src/fsfw/container/FixedOrderedMultimap.tpp @@ -1,109 +1,109 @@ #ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ #define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ - -template -inline ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue) { - if (_size == theMap.maxSize()) { - return MAP_FULL; - } - size_t position = findNicePlace(key); - memmove(static_cast(&theMap[position + 1]),static_cast(&theMap[position]), - (_size - position) * sizeof(std::pair)); - theMap[position].first = key; - theMap[position].second = value; - ++_size; - if (storedValue != nullptr) { - *storedValue = Iterator(&theMap[position]); - } - return HasReturnvaluesIF::RETURN_OK; +template +inline ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, + Iterator *storedValue) { + if (_size == theMap.maxSize()) { + return MAP_FULL; + } + size_t position = findNicePlace(key); + memmove(static_cast(&theMap[position + 1]), static_cast(&theMap[position]), + (_size - position) * sizeof(std::pair)); + theMap[position].first = key; + theMap[position].second = value; + ++_size; + if (storedValue != nullptr) { + *storedValue = Iterator(&theMap[position]); + } + return HasReturnvaluesIF::RETURN_OK; } -template +template inline ReturnValue_t FixedOrderedMultimap::insert(std::pair pair) { - return insert(pair.first, pair.second); + return insert(pair.first, pair.second); } -template +template inline ReturnValue_t FixedOrderedMultimap::exists(key_t key) const { - ReturnValue_t result = KEY_DOES_NOT_EXIST; - if (findFirstIndex(key) < _size) { - result = HasReturnvaluesIF::RETURN_OK; - } - return result; + ReturnValue_t result = KEY_DOES_NOT_EXIST; + if (findFirstIndex(key) < _size) { + result = HasReturnvaluesIF::RETURN_OK; + } + return result; } -template +template inline ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) { - size_t i; - if ((i = findFirstIndex((*iter).value->first)) >= _size) { - return KEY_DOES_NOT_EXIST; - } - removeFromPosition(i); - if (*iter != begin()) { - (*iter)--; - } else { - *iter = begin(); - } - return HasReturnvaluesIF::RETURN_OK; + size_t i; + if ((i = findFirstIndex((*iter).value->first)) >= _size) { + return KEY_DOES_NOT_EXIST; + } + removeFromPosition(i); + if (*iter != begin()) { + (*iter)--; + } else { + *iter = begin(); + } + return HasReturnvaluesIF::RETURN_OK; } -template +template inline ReturnValue_t FixedOrderedMultimap::erase(key_t key) { - size_t i; - if ((i = findFirstIndex(key)) >= _size) { - return KEY_DOES_NOT_EXIST; - } - do { - removeFromPosition(i); - i = findFirstIndex(key, i); - } while (i < _size); - return HasReturnvaluesIF::RETURN_OK; + size_t i; + if ((i = findFirstIndex(key)) >= _size) { + return KEY_DOES_NOT_EXIST; + } + do { + removeFromPosition(i); + i = findFirstIndex(key, i); + } while (i < _size); + return HasReturnvaluesIF::RETURN_OK; } -template +template inline ReturnValue_t FixedOrderedMultimap::find(key_t key, T **value) const { - ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - *value = &theMap[findFirstIndex(key)].second; - return HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = exists(key); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + *value = &theMap[findFirstIndex(key)].second; + return HasReturnvaluesIF::RETURN_OK; } -template -inline size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt) const { - if (startAt >= _size) { - return startAt + 1; +template +inline size_t FixedOrderedMultimap::findFirstIndex(key_t key, + size_t startAt) const { + if (startAt >= _size) { + return startAt + 1; + } + size_t i = startAt; + for (i = startAt; i < _size; ++i) { + if (theMap[i].first == key) { + return i; } - size_t i = startAt; - for (i = startAt; i < _size; ++i) { - if (theMap[i].first == key) { - return i; - } - } - return i; + } + return i; } -template +template inline size_t FixedOrderedMultimap::findNicePlace(key_t key) const { - size_t i = 0; - for (i = 0; i < _size; ++i) { - if (myComp(key, theMap[i].first)) { - return i; - } + size_t i = 0; + for (i = 0; i < _size; ++i) { + if (myComp(key, theMap[i].first)) { + return i; } - return i; + } + return i; } -template +template inline void FixedOrderedMultimap::removeFromPosition(size_t position) { - if (_size <= position) { - return; - } - memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), - (_size - position - 1) * sizeof(std::pair)); - --_size; + if (_size <= position) { + return; + } + memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), + (_size - position - 1) * sizeof(std::pair)); + --_size; } - #endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ */ diff --git a/src/fsfw/controller/CMakeLists.txt b/src/fsfw/controller/CMakeLists.txt index 550acfcd..c8c000d8 100644 --- a/src/fsfw/controller/CMakeLists.txt +++ b/src/fsfw/controller/CMakeLists.txt @@ -1,4 +1,2 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - ControllerBase.cpp - ExtendedControllerBase.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE ControllerBase.cpp + ExtendedControllerBase.cpp) diff --git a/src/fsfw/coordinates/CMakeLists.txt b/src/fsfw/coordinates/CMakeLists.txt index a1fa1e52..15452b1c 100644 --- a/src/fsfw/coordinates/CMakeLists.txt +++ b/src/fsfw/coordinates/CMakeLists.txt @@ -1,5 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - CoordinateTransformations.cpp - Sgp4Propagator.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE CoordinateTransformations.cpp + Sgp4Propagator.cpp) diff --git a/src/fsfw/datalinklayer/CMakeLists.txt b/src/fsfw/datalinklayer/CMakeLists.txt index 148e7c5d..cc18088f 100644 --- a/src/fsfw/datalinklayer/CMakeLists.txt +++ b/src/fsfw/datalinklayer/CMakeLists.txt @@ -1,12 +1,11 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - Clcw.cpp - DataLinkLayer.cpp - Farm1StateLockout.cpp - Farm1StateOpen.cpp - Farm1StateWait.cpp - MapPacketExtraction.cpp - TcTransferFrame.cpp - TcTransferFrameLocal.cpp - VirtualChannelReception.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE Clcw.cpp + DataLinkLayer.cpp + Farm1StateLockout.cpp + Farm1StateOpen.cpp + Farm1StateWait.cpp + MapPacketExtraction.cpp + TcTransferFrame.cpp + TcTransferFrameLocal.cpp + VirtualChannelReception.cpp) diff --git a/src/fsfw/datapool/CMakeLists.txt b/src/fsfw/datapool/CMakeLists.txt index be4606aa..b2ac592c 100644 --- a/src/fsfw/datapool/CMakeLists.txt +++ b/src/fsfw/datapool/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - PoolDataSetBase.cpp - PoolEntry.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE PoolDataSetBase.cpp PoolEntry.cpp) diff --git a/src/fsfw/datapoollocal/CMakeLists.txt b/src/fsfw/datapoollocal/CMakeLists.txt index e2db39eb..749ef688 100644 --- a/src/fsfw/datapoollocal/CMakeLists.txt +++ b/src/fsfw/datapoollocal/CMakeLists.txt @@ -1,10 +1,6 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - LocalDataPoolManager.cpp - LocalDataSet.cpp - LocalPoolDataSetBase.cpp - LocalPoolObjectBase.cpp - SharedLocalDataSet.cpp -) +target_sources( + ${LIB_FSFW_NAME} + PRIVATE LocalDataPoolManager.cpp LocalDataSet.cpp LocalPoolDataSetBase.cpp + LocalPoolObjectBase.cpp SharedLocalDataSet.cpp) -add_subdirectory(internal) \ No newline at end of file +add_subdirectory(internal) diff --git a/src/fsfw/datapoollocal/LocalPoolVariable.tpp b/src/fsfw/datapoollocal/LocalPoolVariable.tpp index 9bb30611..f800dfd3 100644 --- a/src/fsfw/datapoollocal/LocalPoolVariable.tpp +++ b/src/fsfw/datapoollocal/LocalPoolVariable.tpp @@ -5,205 +5,189 @@ #error Include LocalPoolVariable.h before LocalPoolVariable.tpp! #endif -template -inline LocalPoolVariable::LocalPoolVariable(HasLocalDataPoolIF* hkOwner, - lp_id_t poolId, DataSetIF* dataSet, pool_rwm_t setReadWriteMode): - LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {} +template +inline LocalPoolVariable::LocalPoolVariable(HasLocalDataPoolIF* hkOwner, lp_id_t poolId, + DataSetIF* dataSet, pool_rwm_t setReadWriteMode) + : LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {} -template -inline LocalPoolVariable::LocalPoolVariable(object_id_t poolOwner, - lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode): - LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {} +template +inline LocalPoolVariable::LocalPoolVariable(object_id_t poolOwner, lp_id_t poolId, + DataSetIF* dataSet, pool_rwm_t setReadWriteMode) + : LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {} +template +inline LocalPoolVariable::LocalPoolVariable(gp_id_t globalPoolId, DataSetIF* dataSet, + pool_rwm_t setReadWriteMode) + : LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, dataSet, + setReadWriteMode) {} -template -inline LocalPoolVariable::LocalPoolVariable(gp_id_t globalPoolId, - DataSetIF *dataSet, pool_rwm_t setReadWriteMode): - LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, - dataSet, setReadWriteMode){} - - -template -inline ReturnValue_t LocalPoolVariable::read( - MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { - if(hkManager == nullptr) { - return readWithoutLock(); - } - MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager); - ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - result = readWithoutLock(); - mutex->unlockMutex(); +template +inline ReturnValue_t LocalPoolVariable::read(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + if (hkManager == nullptr) { + return readWithoutLock(); + } + MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager); + ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs); + if (result != HasReturnvaluesIF::RETURN_OK) { return result; + } + result = readWithoutLock(); + mutex->unlockMutex(); + return result; } -template +template inline ReturnValue_t LocalPoolVariable::readWithoutLock() { - if(readWriteMode == pool_rwm_t::VAR_WRITE) { - object_id_t targetObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVector", - PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId, - localPoolId); - return PoolVariableIF::INVALID_READ_WRITE_MODE; - } + if (readWriteMode == pool_rwm_t::VAR_WRITE) { + object_id_t targetObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, true, + targetObjectId, localPoolId); + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } - PoolEntry* poolEntry = nullptr; - ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, - &poolEntry); - if(result != RETURN_OK) { - object_id_t ownerObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVariable", result, - false, ownerObjectId, localPoolId); - return result; - } - - this->value = *(poolEntry->getDataPtr()); - this->valid = poolEntry->getValid(); - return RETURN_OK; -} - -template -inline ReturnValue_t LocalPoolVariable::commit(bool setValid, - MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { - this->setValid(setValid); - return commit(timeoutType, timeoutMs); -} - -template -inline ReturnValue_t LocalPoolVariable::commit( - MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { - if(hkManager == nullptr) { - return commitWithoutLock(); - } - MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager); - ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - result = commitWithoutLock(); - mutex->unlockMutex(); + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = + LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry); + if (result != RETURN_OK) { + object_id_t ownerObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVariable", result, false, ownerObjectId, localPoolId); return result; + } + + this->value = *(poolEntry->getDataPtr()); + this->valid = poolEntry->getValid(); + return RETURN_OK; } -template +template +inline ReturnValue_t LocalPoolVariable::commit(bool setValid, MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + this->setValid(setValid); + return commit(timeoutType, timeoutMs); +} + +template +inline ReturnValue_t LocalPoolVariable::commit(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + if (hkManager == nullptr) { + return commitWithoutLock(); + } + MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager); + ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = commitWithoutLock(); + mutex->unlockMutex(); + return result; +} + +template inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { - if(readWriteMode == pool_rwm_t::VAR_READ) { - object_id_t targetObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVector", - PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId, - localPoolId); - return PoolVariableIF::INVALID_READ_WRITE_MODE; - } + if (readWriteMode == pool_rwm_t::VAR_READ) { + object_id_t targetObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, false, + targetObjectId, localPoolId); + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } - PoolEntry* poolEntry = nullptr; - ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, - &poolEntry); - if(result != RETURN_OK) { - object_id_t ownerObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVariable", result, - false, ownerObjectId, localPoolId); - return result; - } + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = + LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry); + if (result != RETURN_OK) { + object_id_t ownerObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVariable", result, false, ownerObjectId, localPoolId); + return result; + } - *(poolEntry->getDataPtr()) = this->value; - poolEntry->setValid(this->valid); - return RETURN_OK; + *(poolEntry->getDataPtr()) = this->value; + poolEntry->setValid(this->valid); + return RETURN_OK; } -template -inline ReturnValue_t LocalPoolVariable::serialize(uint8_t** buffer, - size_t* size, const size_t max_size, - SerializeIF::Endianness streamEndianness) const { - return SerializeAdapter::serialize(&value, - buffer, size ,max_size, streamEndianness); +template +inline ReturnValue_t LocalPoolVariable::serialize( + uint8_t** buffer, size_t* size, const size_t max_size, + SerializeIF::Endianness streamEndianness) const { + return SerializeAdapter::serialize(&value, buffer, size, max_size, streamEndianness); } -template +template inline size_t LocalPoolVariable::getSerializedSize() const { - return SerializeAdapter::getSerializedSize(&value); + return SerializeAdapter::getSerializedSize(&value); } -template -inline ReturnValue_t LocalPoolVariable::deSerialize(const uint8_t** buffer, - size_t* size, SerializeIF::Endianness streamEndianness) { - return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness); +template +inline ReturnValue_t LocalPoolVariable::deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) { + return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness); } #if FSFW_CPP_OSTREAM_ENABLED == 1 -template -inline std::ostream& operator<< (std::ostream &out, - const LocalPoolVariable &var) { - out << var.value; - return out; +template +inline std::ostream& operator<<(std::ostream& out, const LocalPoolVariable& var) { + out << var.value; + return out; } #endif -template +template inline LocalPoolVariable::operator T() const { - return value; + return value; } -template -inline LocalPoolVariable & LocalPoolVariable::operator=( - const T& newValue) { - value = newValue; - return *this; +template +inline LocalPoolVariable& LocalPoolVariable::operator=(const T& newValue) { + value = newValue; + return *this; } -template -inline LocalPoolVariable& LocalPoolVariable::operator =( - const LocalPoolVariable& newPoolVariable) { - value = newPoolVariable.value; - return *this; +template +inline LocalPoolVariable& LocalPoolVariable::operator=( + const LocalPoolVariable& newPoolVariable) { + value = newPoolVariable.value; + return *this; } -template -inline bool LocalPoolVariable::operator ==( - const LocalPoolVariable &other) const { - return this->value == other.value; +template +inline bool LocalPoolVariable::operator==(const LocalPoolVariable& other) const { + return this->value == other.value; } -template -inline bool LocalPoolVariable::operator ==(const T &other) const { - return this->value == other; +template +inline bool LocalPoolVariable::operator==(const T& other) const { + return this->value == other; } - -template -inline bool LocalPoolVariable::operator !=( - const LocalPoolVariable &other) const { - return not (*this == other); +template +inline bool LocalPoolVariable::operator!=(const LocalPoolVariable& other) const { + return not(*this == other); } -template -inline bool LocalPoolVariable::operator !=(const T &other) const { - return not (*this == other); +template +inline bool LocalPoolVariable::operator!=(const T& other) const { + return not(*this == other); } - -template -inline bool LocalPoolVariable::operator <( - const LocalPoolVariable &other) const { - return this->value < other.value; +template +inline bool LocalPoolVariable::operator<(const LocalPoolVariable& other) const { + return this->value < other.value; } -template -inline bool LocalPoolVariable::operator <(const T &other) const { - return this->value < other; +template +inline bool LocalPoolVariable::operator<(const T& other) const { + return this->value < other; } - -template -inline bool LocalPoolVariable::operator >( - const LocalPoolVariable &other) const { - return not (*this < other); +template +inline bool LocalPoolVariable::operator>(const LocalPoolVariable& other) const { + return not(*this < other); } -template -inline bool LocalPoolVariable::operator >(const T &other) const { - return not (*this < other); +template +inline bool LocalPoolVariable::operator>(const T& other) const { + return not(*this < other); } #endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ */ diff --git a/src/fsfw/datapoollocal/LocalPoolVector.tpp b/src/fsfw/datapoollocal/LocalPoolVector.tpp index 044b8fa7..a2c2b752 100644 --- a/src/fsfw/datapoollocal/LocalPoolVector.tpp +++ b/src/fsfw/datapoollocal/LocalPoolVector.tpp @@ -5,174 +5,172 @@ #error Include LocalPoolVector.h before LocalPoolVector.tpp! #endif -template -inline LocalPoolVector::LocalPoolVector( - HasLocalDataPoolIF* hkOwner, lp_id_t poolId, DataSetIF* dataSet, - pool_rwm_t setReadWriteMode): - LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {} +template +inline LocalPoolVector::LocalPoolVector(HasLocalDataPoolIF* hkOwner, lp_id_t poolId, + DataSetIF* dataSet, + pool_rwm_t setReadWriteMode) + : LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {} -template -inline LocalPoolVector::LocalPoolVector(object_id_t poolOwner, - lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode): - LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {} +template +inline LocalPoolVector::LocalPoolVector(object_id_t poolOwner, lp_id_t poolId, + DataSetIF* dataSet, + pool_rwm_t setReadWriteMode) + : LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {} -template -inline LocalPoolVector::LocalPoolVector(gp_id_t globalPoolId, - DataSetIF *dataSet, pool_rwm_t setReadWriteMode): - LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, - dataSet, setReadWriteMode) {} +template +inline LocalPoolVector::LocalPoolVector(gp_id_t globalPoolId, DataSetIF* dataSet, + pool_rwm_t setReadWriteMode) + : LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, dataSet, + setReadWriteMode) {} -template -inline ReturnValue_t LocalPoolVector::read( - MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { - MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs); - return readWithoutLock(); +template +inline ReturnValue_t LocalPoolVector::read(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs); + return readWithoutLock(); } -template +template inline ReturnValue_t LocalPoolVector::readWithoutLock() { - if(readWriteMode == pool_rwm_t::VAR_WRITE) { - object_id_t targetObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVector", - PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId, - localPoolId); - return PoolVariableIF::INVALID_READ_WRITE_MODE; - } + if (readWriteMode == pool_rwm_t::VAR_WRITE) { + object_id_t targetObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, true, + targetObjectId, localPoolId); + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } - PoolEntry* poolEntry = nullptr; - ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, - &poolEntry); - memset(this->value, 0, vectorSize * sizeof(T)); + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = + LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry); + memset(this->value, 0, vectorSize * sizeof(T)); - if(result != RETURN_OK) { - object_id_t targetObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVector", result, true, targetObjectId, - localPoolId); - return result; - } - std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize()); - this->valid = poolEntry->getValid(); - return RETURN_OK; + if (result != RETURN_OK) { + object_id_t targetObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVector", result, true, targetObjectId, localPoolId); + return result; + } + std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize()); + this->valid = poolEntry->getValid(); + return RETURN_OK; } -template +template inline ReturnValue_t LocalPoolVector::commit(bool valid, - MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { - this->setValid(valid); - return commit(timeoutType, timeoutMs); + MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + this->setValid(valid); + return commit(timeoutType, timeoutMs); } -template -inline ReturnValue_t LocalPoolVector::commit( - MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { - MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs); - return commitWithoutLock(); +template +inline ReturnValue_t LocalPoolVector::commit(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs); + return commitWithoutLock(); } -template +template inline ReturnValue_t LocalPoolVector::commitWithoutLock() { - if(readWriteMode == pool_rwm_t::VAR_READ) { - object_id_t targetObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVector", - PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId, - localPoolId); - return PoolVariableIF::INVALID_READ_WRITE_MODE; - } - PoolEntry* poolEntry = nullptr; - ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, - &poolEntry); - if(result != RETURN_OK) { - object_id_t targetObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVector", result, false, targetObjectId, - localPoolId); - return result; - } - std::memcpy(poolEntry->getDataPtr(), this->value, poolEntry->getByteSize()); - poolEntry->setValid(this->valid); - return RETURN_OK; -} - -template -inline T& LocalPoolVector::operator [](size_t i) { - if(i < vectorSize) { - return value[i]; - } - // If this happens, I have to set some value. I consider this - // a configuration error, but I wont exit here. -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "LocalPoolVector: Invalid index. Setting or returning" - " last value!" << std::endl; -#else - sif::printWarning("LocalPoolVector: Invalid index. Setting or returning" - " last value!\n"); -#endif - return value[vectorSize - 1]; -} - -template -inline const T& LocalPoolVector::operator [](size_t i) const { - if(i < vectorSize) { - return value[i]; - } - // If this happens, I have to set some value. I consider this - // a configuration error, but I wont exit here. -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "LocalPoolVector: Invalid index. Setting or returning" - " last value!" << std::endl; -#else - sif::printWarning("LocalPoolVector: Invalid index. Setting or returning" - " last value!\n"); -#endif - return value[vectorSize - 1]; -} - -template -inline ReturnValue_t LocalPoolVector::serialize(uint8_t** buffer, - size_t* size, size_t maxSize, - SerializeIF::Endianness streamEndianness) const { - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - for (uint16_t i = 0; i < vectorSize; i++) { - result = SerializeAdapter::serialize(&(value[i]), buffer, size, - maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - break; - } - } + if (readWriteMode == pool_rwm_t::VAR_READ) { + object_id_t targetObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, false, + targetObjectId, localPoolId); + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = + LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry); + if (result != RETURN_OK) { + object_id_t targetObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVector", result, false, targetObjectId, localPoolId); return result; + } + std::memcpy(poolEntry->getDataPtr(), this->value, poolEntry->getByteSize()); + poolEntry->setValid(this->valid); + return RETURN_OK; } -template +template +inline T& LocalPoolVector::operator[](size_t i) { + if (i < vectorSize) { + return value[i]; + } + // If this happens, I have to set some value. I consider this + // a configuration error, but I wont exit here. +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "LocalPoolVector: Invalid index. Setting or returning" + " last value!" + << std::endl; +#else + sif::printWarning( + "LocalPoolVector: Invalid index. Setting or returning" + " last value!\n"); +#endif + return value[vectorSize - 1]; +} + +template +inline const T& LocalPoolVector::operator[](size_t i) const { + if (i < vectorSize) { + return value[i]; + } + // If this happens, I have to set some value. I consider this + // a configuration error, but I wont exit here. +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "LocalPoolVector: Invalid index. Setting or returning" + " last value!" + << std::endl; +#else + sif::printWarning( + "LocalPoolVector: Invalid index. Setting or returning" + " last value!\n"); +#endif + return value[vectorSize - 1]; +} + +template +inline ReturnValue_t LocalPoolVector::serialize( + uint8_t** buffer, size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + for (uint16_t i = 0; i < vectorSize; i++) { + result = SerializeAdapter::serialize(&(value[i]), buffer, size, maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + break; + } + } + return result; +} + +template inline size_t LocalPoolVector::getSerializedSize() const { - return vectorSize * SerializeAdapter::getSerializedSize(value); + return vectorSize * SerializeAdapter::getSerializedSize(value); } -template +template inline ReturnValue_t LocalPoolVector::deSerialize( - const uint8_t** buffer, size_t* size, - SerializeIF::Endianness streamEndianness) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - for (uint16_t i = 0; i < vectorSize; i++) { - result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, - streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - break; - } + const uint8_t** buffer, size_t* size, SerializeIF::Endianness streamEndianness) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + for (uint16_t i = 0; i < vectorSize; i++) { + result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + break; } - return result; + } + return result; } #if FSFW_CPP_OSTREAM_ENABLED == 1 -template -inline std::ostream& operator<< (std::ostream &out, - const LocalPoolVector &var) { - out << "Vector: ["; - for(int i = 0;i < vectorSize; i++) { - out << var.value[i]; - if(i < vectorSize - 1) { - out << ", "; - } +template +inline std::ostream& operator<<(std::ostream& out, const LocalPoolVector& var) { + out << "Vector: ["; + for (int i = 0; i < vectorSize; i++) { + out << var.value[i]; + if (i < vectorSize - 1) { + out << ", "; } - out << "]"; - return out; + } + out << "]"; + return out; } #endif diff --git a/src/fsfw/datapoollocal/internal/CMakeLists.txt b/src/fsfw/datapoollocal/internal/CMakeLists.txt index 554f3b88..6585d06e 100644 --- a/src/fsfw/datapoollocal/internal/CMakeLists.txt +++ b/src/fsfw/datapoollocal/internal/CMakeLists.txt @@ -1,5 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - HasLocalDpIFUserAttorney.cpp - HasLocalDpIFManagerAttorney.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE HasLocalDpIFUserAttorney.cpp + HasLocalDpIFManagerAttorney.cpp) diff --git a/src/fsfw/devicehandlers/CMakeLists.txt b/src/fsfw/devicehandlers/CMakeLists.txt index 50c1008f..180a89da 100644 --- a/src/fsfw/devicehandlers/CMakeLists.txt +++ b/src/fsfw/devicehandlers/CMakeLists.txt @@ -1,11 +1,10 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - AssemblyBase.cpp - ChildHandlerBase.cpp - ChildHandlerFDIR.cpp - DeviceHandlerBase.cpp - DeviceHandlerFailureIsolation.cpp - DeviceHandlerMessage.cpp - DeviceTmReportingWrapper.cpp - HealthDevice.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE AssemblyBase.cpp + ChildHandlerBase.cpp + ChildHandlerFDIR.cpp + DeviceHandlerBase.cpp + DeviceHandlerFailureIsolation.cpp + DeviceHandlerMessage.cpp + DeviceTmReportingWrapper.cpp + HealthDevice.cpp) diff --git a/src/fsfw/devicehandlers/DeviceHandlerBase.h b/src/fsfw/devicehandlers/DeviceHandlerBase.h index 5808b8e6..84dcb8dc 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerBase.h +++ b/src/fsfw/devicehandlers/DeviceHandlerBase.h @@ -1062,7 +1062,8 @@ class DeviceHandlerBase : public DeviceHandlerIF, /** * Same as triggerEvent, but for forwarding if object is used as proxy. */ - virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const override; + virtual void forwardEvent(Event event, uint32_t parameter1 = 0, + uint32_t parameter2 = 0) const override; /** * Checks if current mode is transitional mode. diff --git a/src/fsfw/events/CMakeLists.txt b/src/fsfw/events/CMakeLists.txt index 28eec772..704cca85 100644 --- a/src/fsfw/events/CMakeLists.txt +++ b/src/fsfw/events/CMakeLists.txt @@ -1,6 +1,3 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - EventManager.cpp - EventMessage.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE EventManager.cpp EventMessage.cpp) add_subdirectory(eventmatching) diff --git a/src/fsfw/events/eventmatching/CMakeLists.txt b/src/fsfw/events/eventmatching/CMakeLists.txt index 81ff9ed8..a9f9c7b3 100644 --- a/src/fsfw/events/eventmatching/CMakeLists.txt +++ b/src/fsfw/events/eventmatching/CMakeLists.txt @@ -1,7 +1,3 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - EventIdRangeMatcher.cpp - EventMatchTree.cpp - ReporterRangeMatcher.cpp - SeverityRangeMatcher.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} PRIVATE EventIdRangeMatcher.cpp EventMatchTree.cpp + ReporterRangeMatcher.cpp SeverityRangeMatcher.cpp) diff --git a/src/fsfw/fdir/CMakeLists.txt b/src/fsfw/fdir/CMakeLists.txt index f5ffbba8..d41ee2eb 100644 --- a/src/fsfw/fdir/CMakeLists.txt +++ b/src/fsfw/fdir/CMakeLists.txt @@ -1,6 +1,3 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - EventCorrelation.cpp - FailureIsolationBase.cpp - FaultCounter.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} PRIVATE EventCorrelation.cpp FailureIsolationBase.cpp + FaultCounter.cpp) diff --git a/src/fsfw/globalfunctions/CMakeLists.txt b/src/fsfw/globalfunctions/CMakeLists.txt index 5ccd3c4c..cfa02696 100644 --- a/src/fsfw/globalfunctions/CMakeLists.txt +++ b/src/fsfw/globalfunctions/CMakeLists.txt @@ -1,13 +1,12 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - arrayprinter.cpp - AsciiConverter.cpp - CRC.cpp - DleEncoder.cpp - PeriodicOperationDivider.cpp - timevalOperations.cpp - Type.cpp - bitutility.cpp -) +target_sources( + ${LIB_FSFW_NAME} + PRIVATE arrayprinter.cpp + AsciiConverter.cpp + CRC.cpp + DleEncoder.cpp + PeriodicOperationDivider.cpp + timevalOperations.cpp + Type.cpp + bitutility.cpp) add_subdirectory(math) diff --git a/src/fsfw/globalfunctions/math/CMakeLists.txt b/src/fsfw/globalfunctions/math/CMakeLists.txt index a9c4ded7..1eeb69b5 100644 --- a/src/fsfw/globalfunctions/math/CMakeLists.txt +++ b/src/fsfw/globalfunctions/math/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - QuaternionOperations.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE QuaternionOperations.cpp) diff --git a/src/fsfw/health/CMakeLists.txt b/src/fsfw/health/CMakeLists.txt index d5f3ccd3..37e4ce48 100644 --- a/src/fsfw/health/CMakeLists.txt +++ b/src/fsfw/health/CMakeLists.txt @@ -1,6 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - HealthHelper.cpp - HealthMessage.cpp - HealthTable.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE HealthHelper.cpp HealthMessage.cpp + HealthTable.cpp) diff --git a/src/fsfw/housekeeping/CMakeLists.txt b/src/fsfw/housekeeping/CMakeLists.txt index fecad2e3..236d3204 100644 --- a/src/fsfw/housekeeping/CMakeLists.txt +++ b/src/fsfw/housekeeping/CMakeLists.txt @@ -1,5 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - HousekeepingMessage.cpp - PeriodicHousekeepingHelper.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE HousekeepingMessage.cpp + PeriodicHousekeepingHelper.cpp) diff --git a/src/fsfw/internalerror/CMakeLists.txt b/src/fsfw/internalerror/CMakeLists.txt index 2b383914..87d3c3f7 100644 --- a/src/fsfw/internalerror/CMakeLists.txt +++ b/src/fsfw/internalerror/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - InternalErrorReporter.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE InternalErrorReporter.cpp) diff --git a/src/fsfw/ipc/CMakeLists.txt b/src/fsfw/ipc/CMakeLists.txt index 3bfe510d..92b91f35 100644 --- a/src/fsfw/ipc/CMakeLists.txt +++ b/src/fsfw/ipc/CMakeLists.txt @@ -1,6 +1,3 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - CommandMessage.cpp - CommandMessageCleaner.cpp - MessageQueueMessage.cpp - MessageQueueBase.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} PRIVATE CommandMessage.cpp CommandMessageCleaner.cpp + MessageQueueMessage.cpp MessageQueueBase.cpp) diff --git a/src/fsfw/memory/CMakeLists.txt b/src/fsfw/memory/CMakeLists.txt index c713cd42..9e591bae 100644 --- a/src/fsfw/memory/CMakeLists.txt +++ b/src/fsfw/memory/CMakeLists.txt @@ -1,5 +1,2 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - MemoryHelper.cpp - MemoryMessage.cpp - GenericFileSystemMessage.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE MemoryHelper.cpp MemoryMessage.cpp + GenericFileSystemMessage.cpp) diff --git a/src/fsfw/modes/CMakeLists.txt b/src/fsfw/modes/CMakeLists.txt index 8e5c719b..4eef58e0 100644 --- a/src/fsfw/modes/CMakeLists.txt +++ b/src/fsfw/modes/CMakeLists.txt @@ -1,5 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - ModeHelper.cpp - ModeMessage.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE ModeHelper.cpp ModeMessage.cpp) diff --git a/src/fsfw/monitoring/CMakeLists.txt b/src/fsfw/monitoring/CMakeLists.txt index d26e807c..48f945b5 100644 --- a/src/fsfw/monitoring/CMakeLists.txt +++ b/src/fsfw/monitoring/CMakeLists.txt @@ -1,5 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - LimitViolationReporter.cpp - MonitoringMessage.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE LimitViolationReporter.cpp + MonitoringMessage.cpp) diff --git a/src/fsfw/objectmanager/CMakeLists.txt b/src/fsfw/objectmanager/CMakeLists.txt index 72aaec89..c71f43aa 100644 --- a/src/fsfw/objectmanager/CMakeLists.txt +++ b/src/fsfw/objectmanager/CMakeLists.txt @@ -1,5 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - ObjectManager.cpp - SystemObject.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE ObjectManager.cpp SystemObject.cpp) diff --git a/src/fsfw/objectmanager/SystemObject.h b/src/fsfw/objectmanager/SystemObject.h index eeb68b8f..c541ac5e 100644 --- a/src/fsfw/objectmanager/SystemObject.h +++ b/src/fsfw/objectmanager/SystemObject.h @@ -50,7 +50,8 @@ class SystemObject : public SystemObjectIF { virtual ReturnValue_t initialize() override; virtual ReturnValue_t checkObjectConnections() override; - virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const override; + virtual void forwardEvent(Event event, uint32_t parameter1 = 0, + uint32_t parameter2 = 0) const override; }; #endif /* FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ */ diff --git a/src/fsfw/osal/CMakeLists.txt b/src/fsfw/osal/CMakeLists.txt index f3c5cfad..50fd6102 100644 --- a/src/fsfw/osal/CMakeLists.txt +++ b/src/fsfw/osal/CMakeLists.txt @@ -1,35 +1,33 @@ # Check the OS_FSFW variable if(FSFW_OSAL MATCHES "freertos") - add_subdirectory(freertos) + add_subdirectory(freertos) elseif(FSFW_OSAL MATCHES "rtems") - add_subdirectory(rtems) + add_subdirectory(rtems) elseif(FSFW_OSAL MATCHES "linux") - add_subdirectory(linux) + add_subdirectory(linux) elseif(FSFW_OSAL MATCHES "host") - add_subdirectory(host) - if (WIN32) - add_subdirectory(windows) - elseif(UNIX) - # We still need to pull in some Linux specific sources - target_sources(${LIB_FSFW_NAME} PUBLIC - linux/tcpipHelpers.cpp - ) - endif () + add_subdirectory(host) + if(WIN32) + add_subdirectory(windows) + elseif(UNIX) + # We still need to pull in some Linux specific sources + target_sources(${LIB_FSFW_NAME} PUBLIC linux/tcpipHelpers.cpp) + endif() else() - message(WARNING "The OS_FSFW variable was not set. Assuming host OS..") - # Not set. Assumuing this is a host build, try to determine host OS - if (WIN32) - add_subdirectory(host) - add_subdirectory(windows) - elseif (UNIX) - add_subdirectory(linux) - else () - # MacOS or other OSes have not been tested yet / are not supported. - message(FATAL_ERROR "The host OS could not be determined! Aborting.") - endif() + message(WARNING "The OS_FSFW variable was not set. Assuming host OS..") + # Not set. Assumuing this is a host build, try to determine host OS + if(WIN32) + add_subdirectory(host) + add_subdirectory(windows) + elseif(UNIX) + add_subdirectory(linux) + else() + # MacOS or other OSes have not been tested yet / are not supported. + message(FATAL_ERROR "The host OS could not be determined! Aborting.") + endif() endif() -add_subdirectory(common) \ No newline at end of file +add_subdirectory(common) diff --git a/src/fsfw/osal/common/CMakeLists.txt b/src/fsfw/osal/common/CMakeLists.txt index b7c8c033..c0814172 100644 --- a/src/fsfw/osal/common/CMakeLists.txt +++ b/src/fsfw/osal/common/CMakeLists.txt @@ -1,17 +1,10 @@ if(DEFINED WIN32 OR DEFINED UNIX) - target_sources(${LIB_FSFW_NAME} PRIVATE - tcpipCommon.cpp - TcpIpBase.cpp - UdpTcPollingTask.cpp - UdpTmTcBridge.cpp - TcpTmTcServer.cpp - TcpTmTcBridge.cpp - ) + target_sources( + ${LIB_FSFW_NAME} + PRIVATE tcpipCommon.cpp TcpIpBase.cpp UdpTcPollingTask.cpp + UdpTmTcBridge.cpp TcpTmTcServer.cpp TcpTmTcBridge.cpp) endif() if(WIN32) - target_link_libraries(${LIB_FSFW_NAME} PRIVATE - wsock32 - ws2_32 - ) -endif() \ No newline at end of file + target_link_libraries(${LIB_FSFW_NAME} PRIVATE wsock32 ws2_32) +endif() diff --git a/src/fsfw/osal/common/TcpTmTcServer.cpp b/src/fsfw/osal/common/TcpTmTcServer.cpp index 91cb9574..b9089245 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.cpp +++ b/src/fsfw/osal/common/TcpTmTcServer.cpp @@ -161,7 +161,7 @@ void TcpTmTcServer::handleServerOperation(socket_t& connSocket) { while (true) { ssize_t retval = recv(connSocket, reinterpret_cast(receptionBuffer.data()), - receptionBuffer.capacity(), tcpConfig.tcpFlags); + receptionBuffer.capacity(), tcpConfig.tcpFlags); if (retval == 0) { size_t availableReadData = ringBuffer.getAvailableReadData(); if (availableReadData > lastRingBufferSize) { @@ -285,7 +285,7 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) arrayprinter::print(storeAccessor.data(), storeAccessor.size()); } ssize_t retval = send(connSocket, reinterpret_cast(storeAccessor.data()), - storeAccessor.size(), tcpConfig.tcpTmFlags); + storeAccessor.size(), tcpConfig.tcpTmFlags); if (retval == static_cast(storeAccessor.size())) { // Packet sent, clear FIFO entry tmtcBridge->tmFifo->pop(); @@ -340,7 +340,7 @@ ReturnValue_t TcpTmTcServer::handleTcRingBufferData(size_t availableReadData) { size_t foundSize = 0; size_t readLen = 0; while (readLen < readAmount) { - if(spacePacketParser == nullptr) { + if (spacePacketParser == nullptr) { return HasReturnvaluesIF::RETURN_FAILED; } result = diff --git a/src/fsfw/osal/common/UdpTcPollingTask.cpp b/src/fsfw/osal/common/UdpTcPollingTask.cpp index 38fb1921..bcc8e9e3 100644 --- a/src/fsfw/osal/common/UdpTcPollingTask.cpp +++ b/src/fsfw/osal/common/UdpTcPollingTask.cpp @@ -154,7 +154,7 @@ void UdpTcPollingTask::setTimeout(double timeoutSeconds) { #endif } #elif defined(PLATFORM_UNIX) - timeval tval {}; + timeval tval{}; tval = timevalOperations::toTimeval(timeoutSeconds); int result = setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO, &tval, sizeof(receptionTimeout)); if (result == -1) { diff --git a/src/fsfw/osal/common/UdpTmTcBridge.cpp b/src/fsfw/osal/common/UdpTmTcBridge.cpp index 6089f266..e3cad58f 100644 --- a/src/fsfw/osal/common/UdpTmTcBridge.cpp +++ b/src/fsfw/osal/common/UdpTmTcBridge.cpp @@ -20,7 +20,7 @@ const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT; UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, - const std::string& udpServerPort_, object_id_t tmStoreId, + const std::string &udpServerPort_, object_id_t tmStoreId, object_id_t tcStoreId) : TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) { if (udpServerPort_.empty()) { @@ -118,7 +118,7 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) { #endif ssize_t bytesSent = sendto(serverSocket, reinterpret_cast(data), dataLen, flags, - &clientAddress, clientAddressLen); + &clientAddress, clientAddressLen); if (bytesSent == SOCKET_ERROR) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "TmTcUdpBridge::sendTm: Send operation failed." << std::endl; diff --git a/src/fsfw/osal/common/UdpTmTcBridge.h b/src/fsfw/osal/common/UdpTmTcBridge.h index b0a67430..92829c46 100644 --- a/src/fsfw/osal/common/UdpTmTcBridge.h +++ b/src/fsfw/osal/common/UdpTmTcBridge.h @@ -29,8 +29,8 @@ class UdpTmTcBridge : public TmTcBridge, public TcpIpBase { /* The ports chosen here should not be used by any other process. */ static const std::string DEFAULT_SERVER_PORT; - UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, const std::string& udpServerPort = "", - object_id_t tmStoreId = objects::TM_STORE, + UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, + const std::string& udpServerPort = "", object_id_t tmStoreId = objects::TM_STORE, object_id_t tcStoreId = objects::TC_STORE); ~UdpTmTcBridge() override; diff --git a/src/fsfw/osal/freertos/CMakeLists.txt b/src/fsfw/osal/freertos/CMakeLists.txt index 40bdcd0f..cb6ac55a 100644 --- a/src/fsfw/osal/freertos/CMakeLists.txt +++ b/src/fsfw/osal/freertos/CMakeLists.txt @@ -1,32 +1,30 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - Clock.cpp - FixedTimeslotTask.cpp - BinarySemaphore.cpp - BinSemaphUsingTask.cpp - CountingSemaphore.cpp - CountingSemaphUsingTask.cpp - MessageQueue.cpp - Mutex.cpp - MutexFactory.cpp - PeriodicTask.cpp - QueueFactory.cpp - SemaphoreFactory.cpp - TaskFactory.cpp - Timekeeper.cpp - TaskManagement.cpp - QueueMapManager.cpp -) +target_sources( + ${LIB_FSFW_NAME} + PRIVATE Clock.cpp + FixedTimeslotTask.cpp + BinarySemaphore.cpp + BinSemaphUsingTask.cpp + CountingSemaphore.cpp + CountingSemaphUsingTask.cpp + MessageQueue.cpp + Mutex.cpp + MutexFactory.cpp + PeriodicTask.cpp + QueueFactory.cpp + SemaphoreFactory.cpp + TaskFactory.cpp + Timekeeper.cpp + TaskManagement.cpp + QueueMapManager.cpp) -# FreeRTOS is required to link the FSFW now. It is recommended to compile -# FreeRTOS as a static library and set LIB_OS_NAME to the target name of the +# FreeRTOS is required to link the FSFW now. It is recommended to compile +# FreeRTOS as a static library and set LIB_OS_NAME to the target name of the # library. if(NOT LIB_OS_NAME) - message(STATUS - "LIB_OS_NAME is empty. Make sure to include the FreeRTOS header path properly." - ) + message( + STATUS + "LIB_OS_NAME is empty. Make sure to include the FreeRTOS header path properly." + ) else() - target_link_libraries(${LIB_FSFW_NAME} PRIVATE - ${LIB_OS_NAME} - ) + target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${LIB_OS_NAME}) endif() diff --git a/src/fsfw/osal/host/CMakeLists.txt b/src/fsfw/osal/host/CMakeLists.txt index 8b11a531..95ab25c9 100644 --- a/src/fsfw/osal/host/CMakeLists.txt +++ b/src/fsfw/osal/host/CMakeLists.txt @@ -1,27 +1,23 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - Clock.cpp - FixedTimeslotTask.cpp - MessageQueue.cpp - Mutex.cpp - MutexFactory.cpp - PeriodicTask.cpp - QueueFactory.cpp - QueueMapManager.cpp - SemaphoreFactory.cpp - TaskFactory.cpp - taskHelpers.cpp -) +target_sources( + ${LIB_FSFW_NAME} + PRIVATE Clock.cpp + FixedTimeslotTask.cpp + MessageQueue.cpp + Mutex.cpp + MutexFactory.cpp + PeriodicTask.cpp + QueueFactory.cpp + QueueMapManager.cpp + SemaphoreFactory.cpp + TaskFactory.cpp + taskHelpers.cpp) if(UNIX) find_package(Threads REQUIRED) - target_link_libraries(${LIB_FSFW_NAME} PRIVATE - ${CMAKE_THREAD_LIBS_INIT} - ) + target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${CMAKE_THREAD_LIBS_INIT}) if(NOT APPLE) - target_link_libraries(${LIB_FSFW_NAME} PRIVATE - rt - ) + target_link_libraries(${LIB_FSFW_NAME} PRIVATE rt) endif() -endif() \ No newline at end of file +endif() diff --git a/src/fsfw/osal/linux/CMakeLists.txt b/src/fsfw/osal/linux/CMakeLists.txt index 2e88d6d0..72a62b86 100644 --- a/src/fsfw/osal/linux/CMakeLists.txt +++ b/src/fsfw/osal/linux/CMakeLists.txt @@ -1,29 +1,25 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - Clock.cpp - BinarySemaphore.cpp - CountingSemaphore.cpp - FixedTimeslotTask.cpp - InternalErrorCodes.cpp - MessageQueue.cpp - Mutex.cpp - MutexFactory.cpp - PeriodicPosixTask.cpp - PosixThread.cpp - QueueFactory.cpp - SemaphoreFactory.cpp - TaskFactory.cpp - tcpipHelpers.cpp - unixUtility.cpp - ) +target_sources( + ${LIB_FSFW_NAME} + PRIVATE Clock.cpp + BinarySemaphore.cpp + CountingSemaphore.cpp + FixedTimeslotTask.cpp + InternalErrorCodes.cpp + MessageQueue.cpp + Mutex.cpp + MutexFactory.cpp + PeriodicPosixTask.cpp + PosixThread.cpp + QueueFactory.cpp + SemaphoreFactory.cpp + TaskFactory.cpp + tcpipHelpers.cpp + unixUtility.cpp) find_package(Threads REQUIRED) -target_link_libraries(${LIB_FSFW_NAME} PUBLIC - ${CMAKE_THREAD_LIBS_INIT} - ) +target_link_libraries(${LIB_FSFW_NAME} PUBLIC ${CMAKE_THREAD_LIBS_INIT}) if(NOT APPLE) - target_link_libraries(${LIB_FSFW_NAME} PUBLIC - rt - ) + target_link_libraries(${LIB_FSFW_NAME} PUBLIC rt) endif() diff --git a/src/fsfw/osal/rtems/CMakeLists.txt b/src/fsfw/osal/rtems/CMakeLists.txt index 734566a3..1b47e1b9 100644 --- a/src/fsfw/osal/rtems/CMakeLists.txt +++ b/src/fsfw/osal/rtems/CMakeLists.txt @@ -1,20 +1,17 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - Clock.cpp - CpuUsage.cpp - InitTask.cpp - InternalErrorCodes.cpp - MessageQueue.cpp - PeriodicTask.cpp - Mutex.cpp - MutexFactory.cpp - FixedTimeslotTask.cpp - QueueFactory.cpp - RtemsBasic.cpp - RTEMSTaskBase.cpp - TaskFactory.cpp - BinarySemaphore.cpp - SemaphoreFactory.cpp -) - - +target_sources( + ${LIB_FSFW_NAME} + PRIVATE Clock.cpp + CpuUsage.cpp + InitTask.cpp + InternalErrorCodes.cpp + MessageQueue.cpp + PeriodicTask.cpp + Mutex.cpp + MutexFactory.cpp + FixedTimeslotTask.cpp + QueueFactory.cpp + RtemsBasic.cpp + RTEMSTaskBase.cpp + TaskFactory.cpp + BinarySemaphore.cpp + SemaphoreFactory.cpp) diff --git a/src/fsfw/osal/windows/CMakeLists.txt b/src/fsfw/osal/windows/CMakeLists.txt index 36a54765..e961b25b 100644 --- a/src/fsfw/osal/windows/CMakeLists.txt +++ b/src/fsfw/osal/windows/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - tcpipHelpers.cpp - winTaskHelpers.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE tcpipHelpers.cpp winTaskHelpers.cpp) diff --git a/src/fsfw/parameters/CMakeLists.txt b/src/fsfw/parameters/CMakeLists.txt index fb5e4590..98a8085c 100644 --- a/src/fsfw/parameters/CMakeLists.txt +++ b/src/fsfw/parameters/CMakeLists.txt @@ -1,6 +1,3 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - ParameterHelper.cpp - ParameterMessage.cpp - ParameterWrapper.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} PRIVATE ParameterHelper.cpp ParameterMessage.cpp + ParameterWrapper.cpp) diff --git a/src/fsfw/power/CMakeLists.txt b/src/fsfw/power/CMakeLists.txt index 10e4a44d..b4ab0006 100644 --- a/src/fsfw/power/CMakeLists.txt +++ b/src/fsfw/power/CMakeLists.txt @@ -1,7 +1,4 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - Fuse.cpp - PowerComponent.cpp - PowerSensor.cpp - PowerSwitcher.cpp - DummyPowerSwitcher.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE Fuse.cpp PowerComponent.cpp PowerSensor.cpp PowerSwitcher.cpp + DummyPowerSwitcher.cpp PowerSwitcherComponent.cpp) diff --git a/src/fsfw/power/DummyPowerSwitcher.cpp b/src/fsfw/power/DummyPowerSwitcher.cpp index 799d49aa..48ab22c6 100644 --- a/src/fsfw/power/DummyPowerSwitcher.cpp +++ b/src/fsfw/power/DummyPowerSwitcher.cpp @@ -17,28 +17,28 @@ void DummyPowerSwitcher::setInitialFusesList(std::vector fuseList } ReturnValue_t DummyPowerSwitcher::sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) { - if (switchNr < switcherList.capacity()) { + if (switchNr < switcherList.size()) { switcherList[switchNr] = onOff; } return RETURN_FAILED; } ReturnValue_t DummyPowerSwitcher::sendFuseOnCommand(uint8_t fuseNr) { - if (fuseNr < fuseList.capacity()) { + if (fuseNr < fuseList.size()) { fuseList[fuseNr] = FUSE_ON; } return RETURN_FAILED; } ReturnValue_t DummyPowerSwitcher::getSwitchState(power::Switch_t switchNr) const { - if (switchNr < switcherList.capacity()) { + if (switchNr < switcherList.size()) { return switcherList[switchNr]; } return HasReturnvaluesIF::RETURN_FAILED; } ReturnValue_t DummyPowerSwitcher::getFuseState(uint8_t fuseNr) const { - if (fuseNr < fuseList.capacity()) { + if (fuseNr < fuseList.size()) { return fuseList[fuseNr]; } return HasReturnvaluesIF::RETURN_FAILED; diff --git a/src/fsfw/power/PowerSensor.cpp b/src/fsfw/power/PowerSensor.cpp index e73b12d0..08ff4724 100644 --- a/src/fsfw/power/PowerSensor.cpp +++ b/src/fsfw/power/PowerSensor.cpp @@ -15,8 +15,7 @@ PowerSensor::PowerSensor(object_id_t objectId, sid_t setId, VariableIds ids, Def limits.currentMin, limits.currentMax, events.currentLow, events.currentHigh), voltageLimit(objectId, MODULE_ID_VOLTAGE, ids.pidVoltage, confirmationCount, limits.voltageMin, limits.voltageMax, events.voltageLow, events.voltageHigh) { - commandQueue = - QueueFactory::instance()->createMessageQueue(3, MessageQueueMessage::MAX_MESSAGE_SIZE); + commandQueue = QueueFactory::instance()->createMessageQueue(); } PowerSensor::~PowerSensor() { QueueFactory::instance()->deleteMessageQueue(commandQueue); } diff --git a/src/fsfw/power/PowerSwitcherComponent.cpp b/src/fsfw/power/PowerSwitcherComponent.cpp new file mode 100644 index 00000000..9c1ed4cf --- /dev/null +++ b/src/fsfw/power/PowerSwitcherComponent.cpp @@ -0,0 +1,107 @@ +#include "PowerSwitcherComponent.h" + +#include +#include + +PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher, + power::Switch_t pwrSwitch) + : SystemObject(objectId), + switcher(pwrSwitcher, pwrSwitch), + modeHelper(this), + healthHelper(this, objectId) { + queue = QueueFactory::instance()->createMessageQueue(); +} + +ReturnValue_t PowerSwitcherComponent::performOperation(uint8_t opCode) { + ReturnValue_t result; + CommandMessage command; + + for (result = queue->receiveMessage(&command); result == RETURN_OK; + result = queue->receiveMessage(&command)) { + result = healthHelper.handleHealthCommand(&command); + if (result == RETURN_OK) { + continue; + } + + result = modeHelper.handleModeCommand(&command); + if (result == RETURN_OK) { + continue; + } + } + if (switcher.active()) { + switcher.doStateMachine(); + auto currState = switcher.getState(); + if (currState == PowerSwitcher::SWITCH_IS_OFF) { + setMode(MODE_OFF, 0); + } else if (currState == PowerSwitcher::SWITCH_IS_ON) { + setMode(MODE_ON, 0); + } + } + return RETURN_OK; +} + +ReturnValue_t PowerSwitcherComponent::initialize() { + ReturnValue_t result = modeHelper.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = healthHelper.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return SystemObject::initialize(); +} + +MessageQueueId_t PowerSwitcherComponent::getCommandQueue() const { return queue->getId(); } + +void PowerSwitcherComponent::getMode(Mode_t *mode, Submode_t *submode) { + *mode = this->mode; + *submode = this->submode; +} + +ReturnValue_t PowerSwitcherComponent::setHealth(HealthState health) { + healthHelper.setHealth(health); + return RETURN_OK; +} + +ReturnValue_t PowerSwitcherComponent::checkModeCommand(Mode_t mode, Submode_t submode, + uint32_t *msToReachTheMode) { + *msToReachTheMode = 5000; + if (mode != MODE_ON and mode != MODE_OFF) { + return TRANS_NOT_ALLOWED; + } + return RETURN_OK; +} + +void PowerSwitcherComponent::startTransition(Mode_t mode, Submode_t submode) { + if (mode == MODE_OFF) { + switcher.turnOff(true); + switcher.doStateMachine(); + if (switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) { + setMode(MODE_OFF, 0); + } + } else if (mode == MODE_ON) { + switcher.turnOn(true); + switcher.doStateMachine(); + if (switcher.getState() == PowerSwitcher::SWITCH_IS_ON) { + setMode(MODE_ON, 0); + } + } +} + +void PowerSwitcherComponent::setToExternalControl() { + healthHelper.setHealth(HasHealthIF::EXTERNAL_CONTROL); +} + +void PowerSwitcherComponent::announceMode(bool recursive) { + triggerEvent(MODE_INFO, mode, submode); +} + +void PowerSwitcherComponent::setMode(Mode_t newMode, Submode_t newSubmode) { + this->mode = newMode; + this->submode = newSubmode; + modeHelper.modeChanged(mode, submode); + announceMode(false); +} + +HasHealthIF::HealthState PowerSwitcherComponent::getHealth() { return healthHelper.getHealth(); } diff --git a/src/fsfw/power/PowerSwitcherComponent.h b/src/fsfw/power/PowerSwitcherComponent.h new file mode 100644 index 00000000..a3ed640e --- /dev/null +++ b/src/fsfw/power/PowerSwitcherComponent.h @@ -0,0 +1,62 @@ +#ifndef _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ +#define _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +class PowerSwitchIF; + +/** + * @brief Allows to create an power switch object with its own mode and health + * @details + * This basic component allows to create an object which is solely responsible for managing a + * switch. It also has a mode and a health by implementing the respective interface components + * which allows integrating this component into a system mode tree. + * + * Commanding this component to MODE_OFF will cause the switcher to turn the switch off while + * commanding in to MODE_ON will cause the switcher to turn the switch on. + */ +class PowerSwitcherComponent : public SystemObject, + public HasReturnvaluesIF, + public ExecutableObjectIF, + public HasModesIF, + public HasHealthIF { + public: + PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher, + power::Switch_t pwrSwitch); + + private: + MessageQueueIF *queue = nullptr; + PowerSwitcher switcher; + + Mode_t mode = MODE_OFF; + Submode_t submode = 0; + + ModeHelper modeHelper; + HealthHelper healthHelper; + + void setMode(Mode_t newMode, Submode_t newSubmode); + + virtual ReturnValue_t performOperation(uint8_t opCode) override; + + ReturnValue_t initialize() override; + + MessageQueueId_t getCommandQueue() const override; + void getMode(Mode_t *mode, Submode_t *submode) override; + ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, + uint32_t *msToReachTheMode) override; + void startTransition(Mode_t mode, Submode_t submode) override; + void setToExternalControl() override; + void announceMode(bool recursive) override; + + ReturnValue_t setHealth(HealthState health) override; + HasHealthIF::HealthState getHealth() override; +}; + +#endif /* _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ */ diff --git a/src/fsfw/pus/CMakeLists.txt b/src/fsfw/pus/CMakeLists.txt index 8b55adf0..35b35bea 100644 --- a/src/fsfw/pus/CMakeLists.txt +++ b/src/fsfw/pus/CMakeLists.txt @@ -1,12 +1,12 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - Service1TelecommandVerification.cpp - Service2DeviceAccess.cpp - Service3Housekeeping.cpp - Service5EventReporting.cpp - Service8FunctionManagement.cpp - Service9TimeManagement.cpp - Service17Test.cpp - Service20ParameterManagement.cpp - CService200ModeCommanding.cpp - CService201HealthCommanding.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE Service1TelecommandVerification.cpp + Service2DeviceAccess.cpp + Service3Housekeeping.cpp + Service5EventReporting.cpp + Service8FunctionManagement.cpp + Service9TimeManagement.cpp + Service17Test.cpp + Service20ParameterManagement.cpp + CService200ModeCommanding.cpp + CService201HealthCommanding.cpp) diff --git a/src/fsfw/pus/CService201HealthCommanding.cpp b/src/fsfw/pus/CService201HealthCommanding.cpp index f6c49cd3..644e0d7c 100644 --- a/src/fsfw/pus/CService201HealthCommanding.cpp +++ b/src/fsfw/pus/CService201HealthCommanding.cpp @@ -97,7 +97,8 @@ ReturnValue_t CService201HealthCommanding::handleReply(const CommandMessage *rep } // Not used for now, health state already reported by event -[[maybe_unused]] ReturnValue_t CService201HealthCommanding::prepareHealthSetReply(const CommandMessage *reply) { +[[maybe_unused]] ReturnValue_t CService201HealthCommanding::prepareHealthSetReply( + const CommandMessage *reply) { auto health = static_cast(HealthMessage::getHealth(reply)); auto oldHealth = static_cast(HealthMessage::getOldHealth(reply)); HealthSetReply healthSetReply(health, oldHealth); diff --git a/src/fsfw/pus/CService201HealthCommanding.h b/src/fsfw/pus/CService201HealthCommanding.h index 7ffa06d2..71b7caa0 100644 --- a/src/fsfw/pus/CService201HealthCommanding.h +++ b/src/fsfw/pus/CService201HealthCommanding.h @@ -39,7 +39,7 @@ class CService201HealthCommanding : public CommandingServiceBase { private: static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet, - const object_id_t *objectId); + const object_id_t *objectId); [[maybe_unused]] ReturnValue_t prepareHealthSetReply(const CommandMessage *reply); diff --git a/src/fsfw/pus/Service11TelecommandScheduling.h b/src/fsfw/pus/Service11TelecommandScheduling.h new file mode 100644 index 00000000..5e446b07 --- /dev/null +++ b/src/fsfw/pus/Service11TelecommandScheduling.h @@ -0,0 +1,202 @@ +#ifndef MISSION_PUS_SERVICE11TELECOMMANDSCHEDULING_H_ +#define MISSION_PUS_SERVICE11TELECOMMANDSCHEDULING_H_ + +#include +#include +#include + +#include "fsfw/FSFW.h" +#include "fsfw/returnvalues/FwClassIds.h" + +/** + * @brief: PUS-Service 11 - Telecommand scheduling. + * @details: + * PUS-Service 11 - Telecommand scheduling. + * Full documentation: ECSS-E-ST-70-41C, p. 168: + * ST[11] time-based scheduling + * + * This service provides the capability to command pre-loaded + * application processes (telecommands) by releasing them at their + * due-time. + * References to telecommands are stored together with their due-timepoints + * and are released at their corresponding due-time. + * + * Necessary subservice functionalities are implemented. + * Those are: + * TC[11,4] activity insertion + * TC[11,5] activity deletion + * TC[11,6] filter-based activity deletion + * TC[11,7] activity time-shift + * TC[11,8] filter-based activity time-shift + * + * Groups are not supported. + * This service remains always enabled. Sending a disable-request has no effect. + */ +template +class Service11TelecommandScheduling final : public PusServiceBase { + public: + static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_11; + + static constexpr ReturnValue_t INVALID_TYPE_TIME_WINDOW = + HasReturnvaluesIF::makeReturnCode(CLASS_ID, 1); + static constexpr ReturnValue_t TIMESHIFTING_NOT_POSSIBLE = + HasReturnvaluesIF::makeReturnCode(CLASS_ID, 2); + static constexpr ReturnValue_t INVALID_RELATIVE_TIME = + HasReturnvaluesIF::makeReturnCode(CLASS_ID, 3); + + // The types of PUS-11 subservices + enum Subservice : uint8_t { + ENABLE_SCHEDULING = 1, + DISABLE_SCHEDULING = 2, + RESET_SCHEDULING = 3, + INSERT_ACTIVITY = 4, + DELETE_ACTIVITY = 5, + FILTER_DELETE_ACTIVITY = 6, + TIMESHIFT_ACTIVITY = 7, + FILTER_TIMESHIFT_ACTIVITY = 8, + DETAIL_REPORT = 9, + TIMEBASE_SCHEDULE_DETAIL_REPORT = 10, + TIMESHIFT_ALL_SCHEDULE_ACTIVITIES = 15 + }; + + // The types of time windows for TC[11,6] and TC[11,8], as defined in ECSS-E-ST-70-41C, + // requirement 8.11.3c (p. 507) + enum TypeOfTimeWindow : uint32_t { + SELECT_ALL = 0, + FROM_TIMETAG_TO_TIMETAG = 1, + FROM_TIMETAG = 2, + TO_TIMETAG = 3 + }; + + Service11TelecommandScheduling(object_id_t objectId, uint16_t apid, uint8_t serviceId, + AcceptsTelecommandsIF* tcRecipient, + uint16_t releaseTimeMarginSeconds = DEFAULT_RELEASE_TIME_MARGIN, + bool debugMode = false); + + ~Service11TelecommandScheduling(); + + /** PusServiceBase overrides */ + ReturnValue_t handleRequest(uint8_t subservice) override; + ReturnValue_t performService() override; + ReturnValue_t initialize() override; + + private: + struct TelecommandStruct { + uint64_t requestId; + uint32_t seconds; + store_address_t storeAddr; // uint16 + }; + + static constexpr uint16_t DEFAULT_RELEASE_TIME_MARGIN = 5; + + // minimum release time offset to insert into schedule + const uint16_t RELEASE_TIME_MARGIN_SECONDS = 5; + + // the maximum amount of stored TCs is defined here + static constexpr uint16_t MAX_STORED_TELECOMMANDS = 500; + + bool debugMode = false; + StorageManagerIF* tcStore = nullptr; + AcceptsTelecommandsIF* tcRecipient = nullptr; + MessageQueueId_t recipientMsgQueueId = 0; + + /** + * The telecommand map uses the exectution time as a Unix time stamp as + * the key. This is mapped to a generic telecommand struct. + */ + using TelecommandMap = etl::multimap; + using TcMapIter = typename TelecommandMap::iterator; + + TelecommandMap telecommandMap; + + /** + * @brief Logic to be performed on an incoming TC[11,4]. + * @return RETURN_OK if successful + */ + ReturnValue_t doInsertActivity(const uint8_t* data, size_t size); + + /** + * @brief Logic to be performed on an incoming TC[11,5]. + * @return RETURN_OK if successful + */ + ReturnValue_t doDeleteActivity(const uint8_t* data, size_t size); + + /** + * @brief Logic to be performed on an incoming TC[11,6]. + * @return RETURN_OK if successful + */ + ReturnValue_t doFilterDeleteActivity(const uint8_t* data, size_t size); + + /** + * @brief Logic to be performed on an incoming TC[11,7]. + * @return RETURN_OK if successful + */ + ReturnValue_t doTimeshiftActivity(const uint8_t* data, size_t size); + + /** + * @brief Logic to be performed on an incoming TC[11,8]. + * @return RETURN_OK if successful + */ + ReturnValue_t doFilterTimeshiftActivity(const uint8_t* data, size_t size); + + /** + * @brief Deserializes a generic type from a payload buffer by using the FSFW + * SerializeAdapter Interface. + * @param output Output to be deserialized + * @param buf Payload buffer (application data) + * @param bufsize Remaining size of payload buffer (application data size) + * @return RETURN_OK if successful + */ + template + ReturnValue_t deserializeViaFsfwInterface(T& output, const uint8_t* buf, size_t bufsize); + + /** + * @brief Extracts the Request ID from the Application Data of a TC by utilizing a ctor of the + * class TcPacketPus. + * NOTE: This only works if the payload data is a TC (e.g. not for TC[11,5] which does not + * send a TC as payload)! + * @param data The Application data of the TC (get via getApplicationData()). + * @return requestId + */ + uint64_t getRequestIdFromDataTC(const uint8_t* data) const; + + /** + * @brief Extracts the Request ID from the Application Data directly, assuming it is packed + * as follows (acc. to ECSS): | source ID (uint32) | apid (uint32) | ssc (uint32) |. + * @param data Pointer to first byte described data + * @param dataSize Remaining size of data NOTE: non-const, this is modified by the function + * @param [out] requestId Request ID + * @return RETURN_OK if successful + */ + ReturnValue_t getRequestIdFromData(const uint8_t*& data, size_t& dataSize, uint64_t& requestId); + + /** + * @brief Builds the Request ID from its three elements. + * @param sourceId Source ID + * @param apid Application Process ID (APID) + * @param ssc Source Sequence Count + * @return Request ID + */ + uint64_t buildRequestId(uint32_t sourceId, uint16_t apid, uint16_t ssc) const; + + /** + * @brief Gets the filter range for filter TCs from a data packet + * @param data TC data + * @param dataSize TC data size + * @param [out] itBegin Begin of filter range + * @param [out] itEnd End of filter range + * @return RETURN_OK if successful + */ + ReturnValue_t getMapFilterFromData(const uint8_t*& data, size_t& size, TcMapIter& itBegin, + TcMapIter& itEnd); + + ReturnValue_t handleInvalidData(const char* ctx); + /** + * @brief Prints content of multimap. Use for simple debugging only. + */ + void debugPrintMultimapContent(void) const; +}; + +#include "Service11TelecommandScheduling.tpp" + +#endif /* MISSION_PUS_SERVICE11TELECOMMANDSCHEDULING_H_ */ diff --git a/src/fsfw/pus/Service11TelecommandScheduling.tpp b/src/fsfw/pus/Service11TelecommandScheduling.tpp new file mode 100644 index 00000000..c72e6631 --- /dev/null +++ b/src/fsfw/pus/Service11TelecommandScheduling.tpp @@ -0,0 +1,598 @@ +#pragma once + +#include +#include +#include + +#include + +static constexpr auto DEF_END = SerializeIF::Endianness::BIG; + +template +inline Service11TelecommandScheduling::Service11TelecommandScheduling( + object_id_t objectId, uint16_t apid, uint8_t serviceId, AcceptsTelecommandsIF *tcRecipient, + uint16_t releaseTimeMarginSeconds, bool debugMode) + : PusServiceBase(objectId, apid, serviceId), + RELEASE_TIME_MARGIN_SECONDS(releaseTimeMarginSeconds), + debugMode(debugMode), + tcRecipient(tcRecipient) {} + +template +inline Service11TelecommandScheduling::~Service11TelecommandScheduling() {} + +template +inline ReturnValue_t Service11TelecommandScheduling::handleRequest( + uint8_t subservice) { + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::handleRequest: Handling request " << static_cast(subservice); +#else + sif::printInfo("PUS11::handleRequest: Handling request %d\n", subservice); +#endif + } + // Get de-serialized Timestamp + const uint8_t *data = currentPacket.getApplicationData(); + size_t size = currentPacket.getApplicationDataSize(); + if (data == nullptr) { + return handleInvalidData("handleRequest"); + } + switch (subservice) { + case Subservice::INSERT_ACTIVITY: + return doInsertActivity(data, size); + case Subservice::DELETE_ACTIVITY: + return doDeleteActivity(data, size); + case Subservice::FILTER_DELETE_ACTIVITY: + return doFilterDeleteActivity(data, size); + case Subservice::TIMESHIFT_ACTIVITY: + return doTimeshiftActivity(data, size); + case Subservice::FILTER_TIMESHIFT_ACTIVITY: + return doFilterTimeshiftActivity(data, size); + default: + break; + } + + return HasReturnvaluesIF::RETURN_FAILED; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::performService() { + // DEBUG + // DebugPrintMultimapContent(); + + // get current time as UNIX timestamp + timeval tNow = {}; + Clock::getClock_timeval(&tNow); + + // NOTE: The iterator is increased in the loop here. Increasing the iterator as for-loop arg + // does not work in this case as we are deleting the current element here. + for (auto it = telecommandMap.begin(); it != telecommandMap.end();) { + if (it->first <= tNow.tv_sec) { + // release tc + TmTcMessage releaseMsg(it->second.storeAddr); + auto sendRet = this->requestQueue->sendMessage(recipientMsgQueueId, &releaseMsg, false); + + if (sendRet != HasReturnvaluesIF::RETURN_OK) { + return sendRet; + } + + telecommandMap.erase(it++); + + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "Released TC & erased it from TC map" << std::endl; +#else + sif::printInfo("Released TC & erased it from TC map\n"); +#endif + } + continue; + } + it++; + } + + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::initialize() { + ReturnValue_t res = PusServiceBase::initialize(); + if (res != HasReturnvaluesIF::RETURN_OK) { + return res; + } + + tcStore = ObjectManager::instance()->get(objects::TC_STORE); + if (!tcStore) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + if (tcRecipient == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + recipientMsgQueueId = tcRecipient->getRequestQueue(); + + return res; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::doInsertActivity( + const uint8_t *data, size_t size) { + uint32_t timestamp = 0; + const uint8_t *initData = data; + size_t initSz = size; + ReturnValue_t result = SerializeAdapter::deSerialize(×tamp, &data, &size, DEF_END); + if (result != RETURN_OK) { + return result; + } + + // Insert possible if sched. time is above margin + // (See requirement for Time margin) + timeval tNow = {}; + Clock::getClock_timeval(&tNow); + if (timestamp - tNow.tv_sec <= RELEASE_TIME_MARGIN_SECONDS) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "Service11TelecommandScheduling::doInsertActivity: Release time too close to " + "current time" + << std::endl; +#else + sif::printWarning( + "Service11TelecommandScheduling::doInsertActivity: Release time too close to current " + "time\n"); +#endif + return RETURN_FAILED; + } + + // store currentPacket and receive the store address + store_address_t addr{}; + if (tcStore->addData(&addr, initData, initSz) != RETURN_OK || + addr.raw == storeId::INVALID_STORE_ADDRESS) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "Service11TelecommandScheduling::doInsertActivity: Adding data to TC Store failed" + << std::endl; +#else + sif::printError( + "Service11TelecommandScheduling::doInsertActivity: Adding data to TC Store failed\n"); +#endif + return RETURN_FAILED; + } + + // insert into multimap with new store address + TelecommandStruct tc; + tc.seconds = timestamp; + tc.storeAddr = addr; + tc.requestId = + getRequestIdFromDataTC(data); // TODO: Missing sanity check of the returned request id + + auto it = telecommandMap.insert(std::pair(timestamp, tc)); + if (it == telecommandMap.end()) { + return RETURN_FAILED; + } + + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::doInsertActivity: Inserted into Multimap:" << std::endl; +#else + sif::printInfo("PUS11::doInsertActivity: Inserted into Multimap:\n"); +#endif + debugPrintMultimapContent(); + } + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::doDeleteActivity( + const uint8_t *data, size_t size) { + // Get request ID + uint64_t requestId; + ReturnValue_t result = getRequestIdFromData(data, size, requestId); + if (result != RETURN_OK) { + return result; + } + + // DEBUG + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::doDeleteActivity: requestId: " << requestId << std::endl; +#else + sif::printInfo("PUS11::doDeleteActivity: requestId: %d\n", requestId); +#endif + } + + TcMapIter tcToDelete; // handle to the TC to be deleted, can be used if counter is valid + int tcToDeleteCount = 0; // counter of all found TCs. Should be 1. + + for (auto it = telecommandMap.begin(); it != telecommandMap.end(); it++) { + if (it->second.requestId == requestId) { + tcToDelete = it; + tcToDeleteCount++; + } + } + + // check if 1 explicit TC is found via request ID + if (tcToDeleteCount == 0 || tcToDeleteCount > 1) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "Service11TelecommandScheduling::doDeleteActivity: No or more than 1 TC found. " + "Cannot explicitly delete TC" + << std::endl; +#else + sif::printWarning( + "Service11TelecommandScheduling::doDeleteActivity: No or more than 1 TC found. " + "Cannot explicitly delete TC"); +#endif + return RETURN_FAILED; + } + + // delete packet from store + if (tcStore->deleteData(tcToDelete->second.storeAddr) != RETURN_OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "Service11TelecommandScheduling::doDeleteActivity: Could not delete TC from Store" + << std::endl; +#else + sif::printError( + "Service11TelecommandScheduling::doDeleteActivity: Could not delete TC from Store\n"); +#endif + return RETURN_FAILED; + } + + telecommandMap.erase(tcToDelete); + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::doDeleteActivity: Deleted TC from map" << std::endl; +#else + sif::printInfo("PUS11::doDeleteActivity: Deleted TC from map\n"); +#endif + } + + return RETURN_OK; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::doFilterDeleteActivity( + const uint8_t *data, size_t size) { + TcMapIter itBegin; + TcMapIter itEnd; + + ReturnValue_t result = getMapFilterFromData(data, size, itBegin, itEnd); + // get the filter window as map range via dedicated method + if (result != RETURN_OK) { + return result; + } + + int deletedTCs = 0; + for (TcMapIter it = itBegin; it != itEnd; it++) { + // delete packet from store + if (tcStore->deleteData(it->second.storeAddr) != RETURN_OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "Service11TelecommandScheduling::doFilterDeleteActivity: Could not delete TC " + "from Store" + << std::endl; +#else + sif::printError( + "Service11TelecommandScheduling::doFilterDeleteActivity: Could not delete TC from " + "Store\n"); +#endif + continue; + } + deletedTCs++; + } + + // NOTE: Spec says this function erases all elements including itBegin but not itEnd, + // see here: https://www.cplusplus.com/reference/map/multimap/erase/ + // Therefore we need to increase itEnd by 1. (Note that end() returns the "past-the-end" iterator) + if (itEnd != telecommandMap.end()) { + itEnd++; + } + + telecommandMap.erase(itBegin, itEnd); + + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::doFilterDeleteActivity: Deleted " << deletedTCs << " TCs" << std::endl; +#else + sif::printInfo("PUS11::doFilterDeleteActivity: Deleted %d TCs\n", deletedTCs); +#endif + } + return RETURN_OK; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::doTimeshiftActivity( + const uint8_t *data, size_t size) { + // Get relative time + uint32_t relativeTime = 0; + ReturnValue_t result = SerializeAdapter::deSerialize(&relativeTime, &data, &size, DEF_END); + if (result != RETURN_OK) { + return result; + } + if (relativeTime == 0) { + return INVALID_RELATIVE_TIME; + } + // TODO further check sanity of the relative time? + + // Get request ID + uint64_t requestId; + result = getRequestIdFromData(data, size, requestId); + if (result != RETURN_OK) { + return result; + } + + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::doTimeshiftActivity: requestId: " << requestId << std::endl; +#else + sif::printInfo("PUS11::doTimeshiftActivity: requestId: %d\n", requestId); +#endif + } + + // NOTE: Despite having C++17 ETL multimap has no member function extract :( + + TcMapIter tcToTimeshiftIt; + int tcToTimeshiftCount = 0; + + for (auto it = telecommandMap.begin(); it != telecommandMap.end(); it++) { + if (it->second.requestId == requestId) { + tcToTimeshiftIt = it; + tcToTimeshiftCount++; + } + } + + if (tcToTimeshiftCount == 0 || tcToTimeshiftCount > 1) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "Service11TelecommandScheduling::doTimeshiftActivity: Either 0 or more than 1 " + "TCs found. No explicit timeshifting " + "possible" + << std::endl; + +#else + sif::printWarning( + "Service11TelecommandScheduling::doTimeshiftActivity: Either 0 or more than 1 TCs found. " + "No explicit timeshifting possible\n"); +#endif + return TIMESHIFTING_NOT_POSSIBLE; + } + + // temporarily hold the item + TelecommandStruct tempTc(tcToTimeshiftIt->second); + uint32_t tempKey = tcToTimeshiftIt->first + relativeTime; + + // delete old entry from the mm + telecommandMap.erase(tcToTimeshiftIt); + + // and then insert it again as new entry + telecommandMap.insert(std::make_pair(tempKey, tempTc)); + + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::doTimeshiftActivity: Shifted TC" << std::endl; +#else + sif::printDebug("PUS11::doTimeshiftActivity: Shifted TC\n"); +#endif + debugPrintMultimapContent(); + } + + return RETURN_OK; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::doFilterTimeshiftActivity( + const uint8_t *data, size_t size) { + // Get relative time + uint32_t relativeTime = 0; + ReturnValue_t result = SerializeAdapter::deSerialize(&relativeTime, &data, &size, DEF_END); + if (result != RETURN_OK) { + return result; + } + if (relativeTime == 0) { + return INVALID_RELATIVE_TIME; + } + + // Do time window + TcMapIter itBegin; + TcMapIter itEnd; + result = getMapFilterFromData(data, size, itBegin, itEnd); + if (result != RETURN_OK) { + return result; + } + + int shiftedItemsCount = 0; + for (auto it = itBegin; it != itEnd;) { + // temporarily hold the item + TelecommandStruct tempTc(it->second); + uint32_t tempKey = it->first + relativeTime; + + // delete the old entry from the mm + telecommandMap.erase(it++); + + // and then insert it again as new entry + telecommandMap.insert(std::make_pair(tempKey, tempTc)); + shiftedItemsCount++; + continue; + } + + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::doFilterTimeshiftActivity: shiftedItemsCount: " << shiftedItemsCount + << std::endl; +#else + sif::printInfo("PUS11::doFilterTimeshiftActivity: shiftedItemsCount: %d\n", shiftedItemsCount); +#endif + debugPrintMultimapContent(); + } + + if (shiftedItemsCount > 0) { + return RETURN_OK; + } + return RETURN_FAILED; +} + +template +inline uint64_t Service11TelecommandScheduling::getRequestIdFromDataTC( + const uint8_t *data) const { + TcPacketPus mask(data); + + uint32_t sourceId = mask.getSourceId(); + uint16_t apid = mask.getAPID(); + uint16_t sequenceCount = mask.getPacketSequenceCount(); + + return buildRequestId(sourceId, apid, sequenceCount); +} + +template +inline ReturnValue_t Service11TelecommandScheduling::getRequestIdFromData( + const uint8_t *&data, size_t &dataSize, uint64_t &requestId) { + uint32_t srcId = 0; + uint16_t apid = 0; + uint16_t ssc = 0; + + ReturnValue_t result = SerializeAdapter::deSerialize(&srcId, &data, &dataSize, DEF_END); + if (result != RETURN_OK) { + return result; + } + result = SerializeAdapter::deSerialize(&apid, &data, &dataSize, DEF_END); + if (result != RETURN_OK) { + return result; + } + result = SerializeAdapter::deSerialize(&ssc, &data, &dataSize, DEF_END); + if (result != RETURN_OK) { + return result; + } + requestId = buildRequestId(srcId, apid, ssc); + + return RETURN_OK; +} + +template +inline uint64_t Service11TelecommandScheduling::buildRequestId(uint32_t sourceId, + uint16_t apid, + uint16_t ssc) const { + uint64_t sourceId64 = static_cast(sourceId); + uint64_t apid64 = static_cast(apid); + uint64_t ssc64 = static_cast(ssc); + + return (sourceId64 << 32) | (apid64 << 16) | ssc64; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::getMapFilterFromData( + const uint8_t *&data, size_t &dataSize, TcMapIter &itBegin, TcMapIter &itEnd) { + // get filter type first + uint32_t typeRaw = 0; + ReturnValue_t result = SerializeAdapter::deSerialize(&typeRaw, &data, &dataSize, DEF_END); + if (result != RETURN_OK) { + return result; + } + + if (typeRaw > 3) { + return INVALID_TYPE_TIME_WINDOW; + } + TypeOfTimeWindow type = static_cast(typeRaw); + + // we now have the type of delete activity - so now we set the range to delete, + // according to the type of time window. + // NOTE: Blocks are used in this switch-case statement so that timestamps can be + // cleanly redefined for each case. + switch (type) { + case TypeOfTimeWindow::SELECT_ALL: { + itBegin = telecommandMap.begin(); + itEnd = telecommandMap.end(); + break; + } + + case TypeOfTimeWindow::FROM_TIMETAG: { + uint32_t fromTimestamp = 0; + result = SerializeAdapter::deSerialize(&fromTimestamp, &data, &dataSize, DEF_END); + if (result != RETURN_OK) { + return result; + } + + itBegin = telecommandMap.begin(); + while (itBegin->first < fromTimestamp && itBegin != telecommandMap.end()) { + itBegin++; + } + + itEnd = telecommandMap.end(); + break; + } + + case TypeOfTimeWindow::TO_TIMETAG: { + uint32_t toTimestamp; + result = SerializeAdapter::deSerialize(&toTimestamp, &data, &dataSize, DEF_END); + if (result != RETURN_OK) { + return result; + } + itBegin = telecommandMap.begin(); + itEnd = telecommandMap.begin(); + while (itEnd->first <= toTimestamp && itEnd != telecommandMap.end()) { + itEnd++; + } + break; + } + + case TypeOfTimeWindow::FROM_TIMETAG_TO_TIMETAG: { + uint32_t fromTimestamp; + uint32_t toTimestamp; + + result = SerializeAdapter::deSerialize(&fromTimestamp, &data, &dataSize, + SerializeIF::Endianness::BIG); + if (result != RETURN_OK) { + return result; + } + result = SerializeAdapter::deSerialize(&toTimestamp, &data, &dataSize, + SerializeIF::Endianness::BIG); + if (result != RETURN_OK) { + return result; + } + itBegin = telecommandMap.begin(); + itEnd = telecommandMap.begin(); + + while (itBegin->first < fromTimestamp && itBegin != telecommandMap.end()) { + itBegin++; + } + while (itEnd->first <= toTimestamp && itEnd != telecommandMap.end()) { + itEnd++; + } + break; + } + + default: + return RETURN_FAILED; + } + + // additional security check, this should never be true + if (itBegin->first > itEnd->first) { + sif::printError("11::GetMapFilterFromData: itBegin > itEnd\n"); + return RETURN_FAILED; + } + + // the map range should now be set according to the sent filter. + return RETURN_OK; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::handleInvalidData( + const char *ctx) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "Service11TelecommandScheduling:: " << ctx << ": Invalid buffer" << std::endl; +#else + sif::printWarning("Service11TelecommandScheduling::%s: Invalid buffer\n", ctx); +#endif +#endif + return RETURN_FAILED; +} + +template +inline void Service11TelecommandScheduling::debugPrintMultimapContent(void) const { +#if FSFW_DISABLE_PRINTOUT == 0 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::debug << "Service11TelecommandScheduling::debugPrintMultimapContent: Multimap Content" + << std::endl; + sif::debug << "[" << dit->first << "]: Request ID: " << dit->second.requestId << " | " + << "Store Address: " << dit->second.storeAddr << std::endl; +#else + sif::printDebug("Service11TelecommandScheduling::debugPrintMultimapContent: Multimap Content\n"); + for (auto dit = telecommandMap.begin(); dit != telecommandMap.end(); ++dit) { + sif::printDebug("[%d]: Request ID: %d | Store Address: %d\n", dit->first, + dit->second.requestId, dit->second.storeAddr); + } +#endif +#endif +} diff --git a/src/fsfw/returnvalues/FwClassIds.h b/src/fsfw/returnvalues/FwClassIds.h index d07cedc9..f5f57276 100644 --- a/src/fsfw/returnvalues/FwClassIds.h +++ b/src/fsfw/returnvalues/FwClassIds.h @@ -72,6 +72,7 @@ enum : uint8_t { DLE_ENCODER, // DLEE PUS_SERVICE_3, // PUS3 PUS_SERVICE_9, // PUS9 + PUS_SERVICE_11, // PUS11 FILE_SYSTEM, // FILS LINUX_OSAL, // UXOS HAL_SPI, // HSPI diff --git a/src/fsfw/rmap/CMakeLists.txt b/src/fsfw/rmap/CMakeLists.txt index 78c99e42..44184860 100644 --- a/src/fsfw/rmap/CMakeLists.txt +++ b/src/fsfw/rmap/CMakeLists.txt @@ -1,7 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - RMAP.cpp - RMAPCookie.cpp - RmapDeviceCommunicationIF.cpp -) - +target_sources(${LIB_FSFW_NAME} PRIVATE RMAP.cpp RMAPCookie.cpp + RmapDeviceCommunicationIF.cpp) diff --git a/src/fsfw/serialize/CMakeLists.txt b/src/fsfw/serialize/CMakeLists.txt index fc2387e8..5ac92d7f 100644 --- a/src/fsfw/serialize/CMakeLists.txt +++ b/src/fsfw/serialize/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - SerialBufferAdapter.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE SerialBufferAdapter.cpp) diff --git a/src/fsfw/serviceinterface/CMakeLists.txt b/src/fsfw/serviceinterface/CMakeLists.txt index 84c79177..df3f074e 100644 --- a/src/fsfw/serviceinterface/CMakeLists.txt +++ b/src/fsfw/serviceinterface/CMakeLists.txt @@ -1,5 +1,4 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - ServiceInterfaceStream.cpp - ServiceInterfaceBuffer.cpp - ServiceInterfacePrinter.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE ServiceInterfaceStream.cpp ServiceInterfaceBuffer.cpp + ServiceInterfacePrinter.cpp) diff --git a/src/fsfw/storagemanager/CMakeLists.txt b/src/fsfw/storagemanager/CMakeLists.txt index b8138cae..50ce50ed 100644 --- a/src/fsfw/storagemanager/CMakeLists.txt +++ b/src/fsfw/storagemanager/CMakeLists.txt @@ -1,7 +1,3 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - ConstStorageAccessor.cpp - StorageAccessor.cpp - LocalPool.cpp - PoolManager.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} PRIVATE ConstStorageAccessor.cpp StorageAccessor.cpp + LocalPool.cpp PoolManager.cpp) diff --git a/src/fsfw/subsystem/CMakeLists.txt b/src/fsfw/subsystem/CMakeLists.txt index 5c98ee70..164c90f7 100644 --- a/src/fsfw/subsystem/CMakeLists.txt +++ b/src/fsfw/subsystem/CMakeLists.txt @@ -1,7 +1,3 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - Subsystem.cpp - SubsystemBase.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE Subsystem.cpp SubsystemBase.cpp) -add_subdirectory(modes) \ No newline at end of file +add_subdirectory(modes) diff --git a/src/fsfw/subsystem/modes/CMakeLists.txt b/src/fsfw/subsystem/modes/CMakeLists.txt index 6ac6a293..ba57de2c 100644 --- a/src/fsfw/subsystem/modes/CMakeLists.txt +++ b/src/fsfw/subsystem/modes/CMakeLists.txt @@ -1,5 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - ModeSequenceMessage.cpp - ModeStore.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE ModeSequenceMessage.cpp ModeStore.cpp) diff --git a/src/fsfw/tasks/CMakeLists.txt b/src/fsfw/tasks/CMakeLists.txt index 1964bb4e..df69520a 100644 --- a/src/fsfw/tasks/CMakeLists.txt +++ b/src/fsfw/tasks/CMakeLists.txt @@ -1,5 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - FixedSequenceSlot.cpp - FixedSlotSequence.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE FixedSequenceSlot.cpp + FixedSlotSequence.cpp) diff --git a/src/fsfw/tcdistribution/CMakeLists.txt b/src/fsfw/tcdistribution/CMakeLists.txt index 7118c38c..ab32c509 100644 --- a/src/fsfw/tcdistribution/CMakeLists.txt +++ b/src/fsfw/tcdistribution/CMakeLists.txt @@ -1,9 +1,4 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - CCSDSDistributor.cpp - PUSDistributor.cpp - TcDistributor.cpp - TcPacketCheckPUS.cpp - TcPacketCheckCFDP.cpp - CFDPDistributor.cpp -) - +target_sources( + ${LIB_FSFW_NAME} + PRIVATE CCSDSDistributor.cpp PUSDistributor.cpp TcDistributor.cpp + TcPacketCheckPUS.cpp TcPacketCheckCFDP.cpp CFDPDistributor.cpp) diff --git a/src/fsfw/thermal/CMakeLists.txt b/src/fsfw/thermal/CMakeLists.txt index ad532721..995ebc4d 100644 --- a/src/fsfw/thermal/CMakeLists.txt +++ b/src/fsfw/thermal/CMakeLists.txt @@ -1,10 +1,9 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - AbstractTemperatureSensor.cpp - Heater.cpp - RedundantHeater.cpp - ThermalComponentCore.cpp - ThermalComponent.cpp - ThermalModule.cpp - ThermalMonitorReporter.cpp -) +target_sources( + ${LIB_FSFW_NAME} + PRIVATE AbstractTemperatureSensor.cpp + Heater.cpp + RedundantHeater.cpp + ThermalComponentCore.cpp + ThermalComponent.cpp + ThermalModule.cpp + ThermalMonitorReporter.cpp) diff --git a/src/fsfw/timemanager/CMakeLists.txt b/src/fsfw/timemanager/CMakeLists.txt index 00467772..c4f77395 100644 --- a/src/fsfw/timemanager/CMakeLists.txt +++ b/src/fsfw/timemanager/CMakeLists.txt @@ -1,8 +1,3 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - CCSDSTime.cpp - Countdown.cpp - Stopwatch.cpp - TimeMessage.cpp - TimeStamper.cpp - ClockCommon.cpp -) +target_sources( + ${LIB_FSFW_NAME} PRIVATE CCSDSTime.cpp Countdown.cpp Stopwatch.cpp + TimeMessage.cpp TimeStamper.cpp ClockCommon.cpp) diff --git a/src/fsfw/tmstorage/CMakeLists.txt b/src/fsfw/tmstorage/CMakeLists.txt index 7990d85a..80da7faf 100644 --- a/src/fsfw/tmstorage/CMakeLists.txt +++ b/src/fsfw/tmstorage/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - TmStoreMessage.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE TmStoreMessage.cpp) diff --git a/src/fsfw/tmtcpacket/CMakeLists.txt b/src/fsfw/tmtcpacket/CMakeLists.txt index e1deaba9..196ba752 100644 --- a/src/fsfw/tmtcpacket/CMakeLists.txt +++ b/src/fsfw/tmtcpacket/CMakeLists.txt @@ -1,8 +1,5 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - SpacePacket.cpp - SpacePacketBase.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE SpacePacket.cpp SpacePacketBase.cpp) add_subdirectory(cfdp) add_subdirectory(packetmatcher) -add_subdirectory(pus) \ No newline at end of file +add_subdirectory(pus) diff --git a/src/fsfw/tmtcpacket/cfdp/CMakeLists.txt b/src/fsfw/tmtcpacket/cfdp/CMakeLists.txt index 0b7ab18a..7d20aab8 100644 --- a/src/fsfw/tmtcpacket/cfdp/CMakeLists.txt +++ b/src/fsfw/tmtcpacket/cfdp/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - CFDPPacket.cpp - CFDPPacketStored.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE CFDPPacket.cpp CFDPPacketStored.cpp) diff --git a/src/fsfw/tmtcpacket/packetmatcher/CMakeLists.txt b/src/fsfw/tmtcpacket/packetmatcher/CMakeLists.txt index e9a8d03b..6ea94799 100644 --- a/src/fsfw/tmtcpacket/packetmatcher/CMakeLists.txt +++ b/src/fsfw/tmtcpacket/packetmatcher/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - PacketMatchTree.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE PacketMatchTree.cpp) diff --git a/src/fsfw/tmtcpacket/pus/tc/CMakeLists.txt b/src/fsfw/tmtcpacket/pus/tc/CMakeLists.txt index dc611263..09c63bfd 100644 --- a/src/fsfw/tmtcpacket/pus/tc/CMakeLists.txt +++ b/src/fsfw/tmtcpacket/pus/tc/CMakeLists.txt @@ -1,6 +1,3 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - TcPacketPusBase.cpp - TcPacketPus.cpp - TcPacketStoredBase.cpp - TcPacketStoredPus.cpp -) +target_sources( + ${LIB_FSFW_NAME} PRIVATE TcPacketPusBase.cpp TcPacketPus.cpp + TcPacketStoredBase.cpp TcPacketStoredPus.cpp) diff --git a/src/fsfw/tmtcpacket/pus/tm/CMakeLists.txt b/src/fsfw/tmtcpacket/pus/tm/CMakeLists.txt index ace87820..ded74ce2 100644 --- a/src/fsfw/tmtcpacket/pus/tm/CMakeLists.txt +++ b/src/fsfw/tmtcpacket/pus/tm/CMakeLists.txt @@ -1,9 +1,9 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - TmPacketStoredPusA.cpp - TmPacketStoredPusC.cpp - TmPacketPusA.cpp - TmPacketPusC.cpp - TmPacketStoredBase.cpp - TmPacketBase.cpp - TmPacketMinimal.cpp -) +target_sources( + ${LIB_FSFW_NAME} + PRIVATE TmPacketStoredPusA.cpp + TmPacketStoredPusC.cpp + TmPacketPusA.cpp + TmPacketPusC.cpp + TmPacketStoredBase.cpp + TmPacketBase.cpp + TmPacketMinimal.cpp) diff --git a/src/fsfw/tmtcservices/CMakeLists.txt b/src/fsfw/tmtcservices/CMakeLists.txt index 96cf99b5..d2a3f4ed 100644 --- a/src/fsfw/tmtcservices/CMakeLists.txt +++ b/src/fsfw/tmtcservices/CMakeLists.txt @@ -1,10 +1,9 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - CommandingServiceBase.cpp - PusServiceBase.cpp - PusVerificationReport.cpp - TmTcBridge.cpp - TmTcMessage.cpp - VerificationReporter.cpp - SpacePacketParser.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE CommandingServiceBase.cpp + PusServiceBase.cpp + PusVerificationReport.cpp + TmTcBridge.cpp + TmTcMessage.cpp + VerificationReporter.cpp + SpacePacketParser.cpp) diff --git a/src/fsfw/version.cpp b/src/fsfw/version.cpp index e4a62002..050187a9 100644 --- a/src/fsfw/version.cpp +++ b/src/fsfw/version.cpp @@ -13,11 +13,28 @@ #endif const fsfw::Version fsfw::FSFW_VERSION = {FSFW_VERSION_MAJOR, FSFW_VERSION_MINOR, - FSFW_VERSION_REVISION}; + FSFW_VERSION_REVISION, FSFW_VCS_INFO}; -fsfw::Version::Version(uint32_t major, uint32_t minor, uint32_t revision) - : major(major), minor(minor), revision(revision) {} +fsfw::Version::Version(int major, int minor, int revision, const char* addInfo) + : major(major), minor(minor), revision(revision), addInfo(addInfo) {} void fsfw::Version::getVersion(char* str, size_t maxLen) const { - snprintf(str, maxLen, "%d.%d.%d", major, minor, revision); + size_t len = snprintf(str, maxLen, "%d.%d.%d", major, minor, revision); + if (addInfo != nullptr) { + snprintf(str + len, maxLen - len, "-%s", addInfo); + } } + +namespace fsfw { + +#if FSFW_CPP_OSTREAM_ENABLED == 1 +std::ostream& operator<<(std::ostream& os, const Version& v) { + os << v.major << "." << v.minor << "." << v.revision; + if (v.addInfo != nullptr) { + os << "-" << v.addInfo; + } + return os; +} +#endif + +} // namespace fsfw diff --git a/src/fsfw/version.h b/src/fsfw/version.h index bb4d0399..a538c39a 100644 --- a/src/fsfw/version.h +++ b/src/fsfw/version.h @@ -12,10 +12,13 @@ namespace fsfw { class Version { public: - Version(uint32_t major, uint32_t minor, uint32_t revision); - uint32_t major = 0; - uint32_t minor = 0; - uint32_t revision = 0; + Version(int major, int minor, int revision, const char* addInfo = nullptr); + int major = -1; + int minor = -1; + int revision = -1; + + // Additional information, e.g. a git SHA hash + const char* addInfo = nullptr; friend bool operator==(const Version& v1, const Version& v2) { return (v1.major == v2.major and v1.minor == v2.minor and v1.revision == v2.revision); @@ -43,10 +46,7 @@ class Version { * @param v * @return */ - friend std::ostream& operator<<(std::ostream& os, const Version& v) { - os << v.major << "." << v.minor << "." << v.revision; - return os; - } + friend std::ostream& operator<<(std::ostream& os, const Version& v); #endif /** @@ -57,7 +57,7 @@ class Version { void getVersion(char* str, size_t maxLen) const; }; -extern const fsfw::Version FSFW_VERSION; +extern const Version FSFW_VERSION; } // namespace fsfw diff --git a/tests/src/fsfw_tests/unit/version.cpp b/tests/src/fsfw_tests/unit/version.cpp index 2967dfa5..662b1290 100644 --- a/tests/src/fsfw_tests/unit/version.cpp +++ b/tests/src/fsfw_tests/unit/version.cpp @@ -14,8 +14,8 @@ TEST_CASE("Version API Tests", "[TestVersionAPI]") { REQUIRE(fsfw::Version(255, 0, 0) >= fsfw::FSFW_VERSION); REQUIRE(fsfw::Version(0, 0, 0) < fsfw::FSFW_VERSION); REQUIRE(fsfw::Version(0, 0, 0) <= fsfw::FSFW_VERSION); - fsfw::Version v1 = fsfw::Version(1, 1, 1); - fsfw::Version v2 = fsfw::Version(1, 1, 1); + auto v1 = fsfw::Version(1, 1, 1); + auto v2 = fsfw::Version(1, 1, 1); REQUIRE(v1 == v2); REQUIRE(not(v1 < v2)); REQUIRE(not(v1 > v2));