Merge branch 'development' into mueller/tcp-keep-open-pr
This commit is contained in:
commit
b23ed11c7e
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,3 +2,5 @@
|
||||
.project
|
||||
.settings
|
||||
.metadata
|
||||
|
||||
/build*
|
||||
|
168
CMakeLists.txt
168
CMakeLists.txt
@ -1,5 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
set(FSFW_VERSION 2)
|
||||
set(FSFW_SUBVERSION 0)
|
||||
set(FSFW_REVISION 0)
|
||||
|
||||
option(FSFW_GENERATE_SECTIONS
|
||||
"Generate function and data sections. Required to remove unused code" ON
|
||||
)
|
||||
@ -7,6 +11,11 @@ if(FSFW_GENERATE_SECTIONS)
|
||||
option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON)
|
||||
endif()
|
||||
|
||||
option(FSFW_BUILD_UNITTESTS "Build unittest binary in addition to static library" OFF)
|
||||
if(FSFW_BUILD_UNITTESTS)
|
||||
option(FSFW_TESTS_GEN_COV "Generate coverage data for unittests" ON)
|
||||
endif()
|
||||
|
||||
option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON)
|
||||
# Options to exclude parts of the FSFW from compilation.
|
||||
option(FSFW_ADD_INTERNAL_TESTS "Add internal unit tests" ON)
|
||||
@ -26,11 +35,72 @@ option(FSFW_ADD_TMSTORAGE "Compile with tm storage components" OFF)
|
||||
option(FSFW_ADD_SGP4_PROPAGATOR "Add SGP4 propagator code" OFF)
|
||||
|
||||
set(LIB_FSFW_NAME fsfw)
|
||||
set(FSFW_TEST_TGT fsfw-tests)
|
||||
|
||||
add_library(${LIB_FSFW_NAME})
|
||||
|
||||
if(FSFW_BUILD_UNITTESTS)
|
||||
message(STATUS "Building the FSFW unittests in addition to the static library")
|
||||
# Check whether the user has already installed Catch2 first
|
||||
find_package(Catch2 3)
|
||||
# Not installed, so use FetchContent to download and provide Catch2
|
||||
if(NOT Catch2_FOUND)
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
Catch2
|
||||
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
||||
GIT_TAG v3.0.0-preview3
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(Catch2)
|
||||
endif()
|
||||
|
||||
set(FSFW_CONFIG_PATH tests/src/fsfw_tests/unit/testcfg)
|
||||
configure_file(tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in FSFWConfig.h)
|
||||
configure_file(tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in tests/TestsConfig.h)
|
||||
configure_file(tests/src/fsfw_tests/unit/testcfg/OBSWConfig.h.in OBSWConfig.h)
|
||||
|
||||
project(${FSFW_TEST_TGT} CXX C)
|
||||
add_executable(${FSFW_TEST_TGT})
|
||||
|
||||
if(FSFW_TESTS_GEN_COV)
|
||||
message(STATUS "Generating coverage data for the library")
|
||||
message(STATUS "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()
|
||||
|
||||
set(FSFW_CORE_INC_PATH "inc")
|
||||
|
||||
set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux rtems freertos)
|
||||
|
||||
# Configure Files
|
||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
if(FSFW_BUILD_UNITTESTS)
|
||||
configure_file(src/fsfw/FSFW.h.in fsfw/FSFW.h)
|
||||
configure_file(src/fsfw/FSFWVersion.h.in fsfw/FSFWVersion.h)
|
||||
else()
|
||||
configure_file(src/fsfw/FSFW.h.in FSFW.h)
|
||||
configure_file(src/fsfw/FSFWVersion.h.in FSFWVersion.h)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
@ -63,29 +133,29 @@ endif()
|
||||
set(FSFW_OSAL_DEFINITION FSFW_OSAL_HOST)
|
||||
|
||||
if(FSFW_OSAL MATCHES host)
|
||||
set(OS_FSFW_NAME "Host")
|
||||
set(FSFW_OS_NAME "Host")
|
||||
set(FSFW_OSAL_HOST ON)
|
||||
elseif(FSFW_OSAL MATCHES linux)
|
||||
set(OS_FSFW_NAME "Linux")
|
||||
set(FSFW_OS_NAME "Linux")
|
||||
set(FSFW_OSAL_LINUX ON)
|
||||
elseif(FSFW_OSAL MATCHES freertos)
|
||||
set(OS_FSFW_NAME "FreeRTOS")
|
||||
set(FSFW_OS_NAME "FreeRTOS")
|
||||
set(FSFW_OSAL_FREERTOS ON)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||
${LIB_OS_NAME}
|
||||
)
|
||||
elseif(FSFW_OSAL STREQUAL rtems)
|
||||
set(OS_FSFW_NAME "RTEMS")
|
||||
set(FSFW_OS_NAME "RTEMS")
|
||||
set(FSFW_OSAL_RTEMS ON)
|
||||
else()
|
||||
message(WARNING
|
||||
"Invalid operating system for FSFW specified! Setting to host.."
|
||||
)
|
||||
set(OS_FSFW_NAME "Host")
|
||||
set(FSFW_OS_NAME "Host")
|
||||
set(OS_FSFW "host")
|
||||
endif()
|
||||
|
||||
message(STATUS "Compiling FSFW for the ${OS_FSFW_NAME} operating system.")
|
||||
message(STATUS "Compiling FSFW for the ${FSFW_OS_NAME} operating system.")
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(tests)
|
||||
@ -94,12 +164,81 @@ if(FSFW_ADD_HAL)
|
||||
endif()
|
||||
add_subdirectory(contrib)
|
||||
|
||||
if(FSFW_BUILD_UNITTESTS)
|
||||
if(FSFW_TESTS_GEN_COV)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
include(CodeCoverage)
|
||||
|
||||
# Remove quotes.
|
||||
separate_arguments(COVERAGE_COMPILER_FLAGS
|
||||
NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}"
|
||||
)
|
||||
|
||||
# Add compile options manually, we don't want coverage for Catch2
|
||||
target_compile_options(${FSFW_TEST_TGT} PRIVATE
|
||||
"${COVERAGE_COMPILER_FLAGS}"
|
||||
)
|
||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
||||
"${COVERAGE_COMPILER_FLAGS}"
|
||||
)
|
||||
|
||||
# Exclude directories here
|
||||
if(WIN32)
|
||||
set(GCOVR_ADDITIONAL_ARGS
|
||||
"--exclude-throw-branches"
|
||||
"--exclude-unreachable-branches"
|
||||
)
|
||||
set(COVERAGE_EXCLUDES
|
||||
"/c/msys64/mingw64/*"
|
||||
)
|
||||
elseif(UNIX)
|
||||
set(COVERAGE_EXCLUDES
|
||||
"/usr/include/*" "/usr/bin/*" "Catch2/*"
|
||||
"/usr/local/include/*" "*/fsfw_tests/*"
|
||||
"*/catch2-src/*"
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_options(${FSFW_TEST_TGT} PRIVATE
|
||||
-fprofile-arcs
|
||||
-ftest-coverage
|
||||
)
|
||||
target_link_options(${LIB_FSFW_NAME} PRIVATE
|
||||
-fprofile-arcs
|
||||
-ftest-coverage
|
||||
)
|
||||
# Need to specify this as an interface, otherwise there will the compile issues
|
||||
target_link_options(${LIB_FSFW_NAME} INTERFACE
|
||||
-fprofile-arcs
|
||||
-ftest-coverage
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
setup_target_for_coverage_gcovr_html(
|
||||
NAME ${FSFW_TEST_TGT}_coverage
|
||||
EXECUTABLE ${FSFW_TEST_TGT}
|
||||
DEPENDENCIES ${FSFW_TEST_TGT}
|
||||
)
|
||||
else()
|
||||
setup_target_for_coverage_lcov(
|
||||
NAME ${FSFW_TEST_TGT}_coverage
|
||||
EXECUTABLE ${FSFW_TEST_TGT}
|
||||
DEPENDENCIES ${FSFW_TEST_TGT}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2 ${LIB_FSFW_NAME})
|
||||
endif()
|
||||
|
||||
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it.
|
||||
# If this is not given, we include the default configuration and emit a warning.
|
||||
if(NOT FSFW_CONFIG_PATH)
|
||||
message(WARNING "Flight Software Framework configuration path not set!")
|
||||
message(WARNING "Setting default configuration!")
|
||||
add_subdirectory(defaultcfg/fsfwconfig)
|
||||
set(DEF_CONF_PATH misc/defaultcfg/fsfwconfig)
|
||||
message(WARNING "Setting default configuration from ${DEF_CONF_PATH} ..")
|
||||
add_subdirectory(${DEF_CONF_PATH})
|
||||
set(FSFW_CONFIG_PATH ${DEF_CONF_PATH})
|
||||
endif()
|
||||
|
||||
# FSFW might be part of a possibly complicated folder structure, so we
|
||||
@ -187,3 +326,16 @@ target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||
${FSFW_ADDITIONAL_LINK_LIBS}
|
||||
)
|
||||
|
||||
string(CONCAT POST_BUILD_COMMENT
|
||||
"######################################################################\n"
|
||||
"Built FSFW v${FSFW_VERSION}.${FSFW_SUBVERSION}.${FSFW_REVISION}, "
|
||||
"Target OSAL: ${FSFW_OS_NAME}\n"
|
||||
"######################################################################\n"
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${LIB_FSFW_NAME}
|
||||
POST_BUILD
|
||||
COMMENT ${POST_BUILD_COMMENT}
|
||||
)
|
||||
|
83
README.md
83
README.md
@ -22,17 +22,90 @@ Currently, the FSFW provides the following OSALs:
|
||||
- FreeRTOS
|
||||
- RTEMS
|
||||
|
||||
The recommended hardware is a microprocessor with more than 1 MB of RAM and 1 MB of non-volatile Memory. For reference, current applications use a Cobham Gaisler UT699 (LEON3FT), a ISISPACE IOBC or a Zynq-7020 SoC. The `fsfw` was also successfully run on the STM32H743ZI-Nucleo board and on a Raspberry Pi and is currently running on the active satellite mission Flying Laptop.
|
||||
The recommended hardware is a microprocessor with more than 1 MB of RAM and 1 MB of non-volatile
|
||||
memory. For reference, current applications use a Cobham Gaisler UT699 (LEON3FT), a
|
||||
ISISPACE IOBC or a Zynq-7020 SoC. The `fsfw` was also successfully run on the
|
||||
STM32H743ZI-Nucleo board and on a Raspberry Pi and is currently running on the active
|
||||
satellite mission Flying Laptop.
|
||||
|
||||
## Getting started
|
||||
|
||||
The [FSFW example](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_example) provides a good starting point and a demo to see the FSFW capabilities and build it with the Make or the CMake build system. It is recommended to evaluate the FSFW by building and playing around with the demo application.
|
||||
The [Hosted FSFW example](https://egit.irs.uni-stuttgart.de/fsfw/fsfw-example-hosted) provides a
|
||||
good starting point and a demo to see the FSFW capabilities.
|
||||
It is recommended to get started by building and playing around with the demo application.
|
||||
There are also other examples provided for all OSALs using the popular embedded platforms
|
||||
Raspberry Pi, Beagle Bone Black and STM32H7.
|
||||
|
||||
Generally, the FSFW is included in a project by compiling the FSFW sources and providing
|
||||
a configuration folder and adding it to the include path. There are some functions like `printChar` which are different depending on the target architecture and need to be implemented by the mission developer.
|
||||
Generally, the FSFW is included in a project by providing
|
||||
a configuration folder, building the static library and linking against it.
|
||||
There are some functions like `printChar` which are different depending on the target architecture
|
||||
and need to be implemented by the mission developer.
|
||||
|
||||
A template configuration folder was provided and can be copied into the project root to have
|
||||
a starting point. The [configuration section](doc/README-config.md#top) provides more specific information about the possible options.
|
||||
a starting point. The [configuration section](doc/README-config.md#top) provides more specific
|
||||
information about the possible options.
|
||||
|
||||
## Adding the library
|
||||
|
||||
The following steps show how to add and use FSFW components. It is still recommended to
|
||||
try out the example mentioned above to get started, but the following steps show how to
|
||||
add and link against the FSFW library in general.
|
||||
|
||||
1. Add this repository as a submodule
|
||||
|
||||
```sh
|
||||
git submodule add https://egit.irs.uni-stuttgart.de/fsfw/fsfw.git fsfw
|
||||
```
|
||||
|
||||
2. Add the following directive inside the uppermost `CMakeLists.txt` file of your project
|
||||
|
||||
```cmake
|
||||
add_subdirectory(fsfw)
|
||||
```
|
||||
|
||||
3. Make sure to provide a configuration folder and supply the path to that folder with
|
||||
the `FSFW_CONFIG_PATH` CMake variable from the uppermost `CMakeLists.txt` file.
|
||||
It is also necessary to provide the `printChar` function. You can find an example
|
||||
implementation for a hosted build
|
||||
[here](https://egit.irs.uni-stuttgart.de/fsfw/fsfw-example-hosted/src/branch/master/bsp_hosted/utility/printChar.c).
|
||||
|
||||
4. Link against the FSFW library
|
||||
|
||||
```cmake
|
||||
target_link_libraries(<YourProjectName> PRIVATE fsfw)
|
||||
```
|
||||
|
||||
5. It should now be possible use the FSFW as a static library from the user code.
|
||||
|
||||
## Building the unittests
|
||||
|
||||
The FSFW also has unittests which use the [Catch2 library](https://github.com/catchorg/Catch2).
|
||||
These are built by setting the CMake option `FSFW_BUILD_UNITTESTS` to `ON` or `TRUE`
|
||||
from your project `CMakeLists.txt` file or from the command line.
|
||||
|
||||
The fsfw-tests binary will be built as part of the static library and dropped alongside it.
|
||||
If the unittests are built, the library and the tests will be built with coverage information by
|
||||
default. This can be disabled by setting the `FSFW_TESTS_COV_GEN` option to `OFF` or `FALSE`.
|
||||
|
||||
You can use the following commands inside the `fsfw` folder to set up the build system
|
||||
|
||||
```sh
|
||||
mkdir build-Unittest && cd build-Unittest
|
||||
cmake -DFSFW_BUILD_UNITTESTS=ON -DFSFW_OSAL=host ..
|
||||
```
|
||||
|
||||
You can also use `-DFSFW_OSAL=linux` on Linux systems.
|
||||
|
||||
Coverage data in HTML format can be generated using the `CodeCoverage`
|
||||
[CMake module](https://github.com/bilke/cmake-modules/tree/master).
|
||||
To build the unittests, run them and then generare the coverage data in this format,
|
||||
the following command can be used inside the build directory after the build system was set up
|
||||
|
||||
```sh
|
||||
cmake --build . -- fsfw-tests_coverage -j
|
||||
```
|
||||
|
||||
The `coverage.py` script located in the `script` folder can also be used to do this conveniently.
|
||||
|
||||
## Index
|
||||
|
||||
|
@ -9,12 +9,13 @@ using gpioId_t = uint16_t;
|
||||
|
||||
namespace gpio {
|
||||
|
||||
enum Levels {
|
||||
enum Levels: uint8_t {
|
||||
LOW = 0,
|
||||
HIGH = 1
|
||||
HIGH = 1,
|
||||
NONE = 99
|
||||
};
|
||||
|
||||
enum Direction {
|
||||
enum Direction: uint8_t {
|
||||
IN = 0,
|
||||
OUT = 1
|
||||
};
|
||||
@ -24,16 +25,18 @@ enum GpioOperation {
|
||||
WRITE
|
||||
};
|
||||
|
||||
enum GpioTypes {
|
||||
enum class GpioTypes {
|
||||
NONE,
|
||||
GPIO_REGULAR_BY_CHIP,
|
||||
GPIO_REGULAR_BY_LABEL,
|
||||
GPIO_REGULAR_BY_LINE_NAME,
|
||||
CALLBACK
|
||||
};
|
||||
|
||||
static constexpr gpioId_t NO_GPIO = -1;
|
||||
|
||||
using gpio_cb_t = void (*) (gpioId_t gpioId, gpio::GpioOperation gpioOp, int value, void* args);
|
||||
using gpio_cb_t = void (*) (gpioId_t gpioId, gpio::GpioOperation gpioOp, gpio::Levels value,
|
||||
void* args);
|
||||
|
||||
}
|
||||
|
||||
@ -57,7 +60,7 @@ public:
|
||||
GpioBase() = default;
|
||||
|
||||
GpioBase(gpio::GpioTypes gpioType, std::string consumer, gpio::Direction direction,
|
||||
int initValue):
|
||||
gpio::Levels initValue):
|
||||
gpioType(gpioType), consumer(consumer),direction(direction), initValue(initValue) {}
|
||||
|
||||
virtual~ GpioBase() {};
|
||||
@ -66,15 +69,21 @@ public:
|
||||
gpio::GpioTypes gpioType = gpio::GpioTypes::NONE;
|
||||
std::string consumer;
|
||||
gpio::Direction direction = gpio::Direction::IN;
|
||||
int initValue = 0;
|
||||
gpio::Levels initValue = gpio::Levels::NONE;
|
||||
};
|
||||
|
||||
class GpiodRegularBase: public GpioBase {
|
||||
public:
|
||||
GpiodRegularBase(gpio::GpioTypes gpioType, std::string consumer, gpio::Direction direction,
|
||||
int initValue, int lineNum): GpioBase(gpioType, consumer, direction, initValue),
|
||||
lineNum(lineNum) {
|
||||
gpio::Levels initValue, int lineNum):
|
||||
GpioBase(gpioType, consumer, direction, initValue), lineNum(lineNum) {
|
||||
}
|
||||
|
||||
// line number will be configured at a later point for the open by line name configuration
|
||||
GpiodRegularBase(gpio::GpioTypes gpioType, std::string consumer, gpio::Direction direction,
|
||||
gpio::Levels initValue): GpioBase(gpioType, consumer, direction, initValue) {
|
||||
}
|
||||
|
||||
int lineNum = 0;
|
||||
struct gpiod_line* lineHandle = nullptr;
|
||||
};
|
||||
@ -87,7 +96,7 @@ public:
|
||||
}
|
||||
|
||||
GpiodRegularByChip(std::string chipname_, int lineNum_, std::string consumer_,
|
||||
gpio::Direction direction_, int initValue_) :
|
||||
gpio::Direction direction_, gpio::Levels initValue_) :
|
||||
GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP,
|
||||
consumer_, direction_, initValue_, lineNum_),
|
||||
chipname(chipname_){
|
||||
@ -105,7 +114,7 @@ public:
|
||||
class GpiodRegularByLabel: public GpiodRegularBase {
|
||||
public:
|
||||
GpiodRegularByLabel(std::string label_, int lineNum_, std::string consumer_,
|
||||
gpio::Direction direction_, int initValue_) :
|
||||
gpio::Direction direction_, gpio::Levels initValue_) :
|
||||
GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LABEL, consumer_,
|
||||
direction_, initValue_, lineNum_),
|
||||
label(label_) {
|
||||
@ -120,9 +129,30 @@ public:
|
||||
std::string label;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Passing this GPIO configuration to the GPIO IF object will try to open the GPIO by its
|
||||
* line name. This line name can be set in the device tree and must be unique. Otherwise
|
||||
* the driver will open the first line with the given name.
|
||||
*/
|
||||
class GpiodRegularByLineName: public GpiodRegularBase {
|
||||
public:
|
||||
GpiodRegularByLineName(std::string lineName_, std::string consumer_, gpio::Direction direction_,
|
||||
gpio::Levels initValue_) :
|
||||
GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME, consumer_, direction_,
|
||||
initValue_), lineName(lineName_) {
|
||||
}
|
||||
|
||||
GpiodRegularByLineName(std::string lineName_, std::string consumer_) :
|
||||
GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME, consumer_,
|
||||
gpio::Direction::IN, gpio::LOW), lineName(lineName_) {
|
||||
}
|
||||
|
||||
std::string lineName;
|
||||
};
|
||||
|
||||
class GpioCallback: public GpioBase {
|
||||
public:
|
||||
GpioCallback(std::string consumer, gpio::Direction direction_, int initValue_,
|
||||
GpioCallback(std::string consumer, gpio::Direction direction_, gpio::Levels initValue_,
|
||||
gpio::gpio_cb_t callback, void* callbackArgs):
|
||||
GpioBase(gpio::GpioTypes::CALLBACK, consumer, direction_, initValue_),
|
||||
callback(callback), callbackArgs(callbackArgs) {}
|
||||
|
@ -73,7 +73,7 @@ ReturnValue_t MgmLIS3MDLHandler::buildTransitionDeviceCommand(
|
||||
switch (internalState) {
|
||||
case(InternalState::STATE_NONE):
|
||||
case(InternalState::STATE_NORMAL): {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return DeviceHandlerBase::NOTHING_TO_SEND;
|
||||
}
|
||||
case(InternalState::STATE_FIRST_CONTACT): {
|
||||
*id = MGMLIS3MDL::IDENTIFY_DEVICE;
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
|
||||
#include "LinuxLibgpioIF.h"
|
||||
|
||||
#include "fsfw_hal/common/gpio/gpioDefinitions.h"
|
||||
#include "fsfw_hal/common/gpio/GpioCookie.h"
|
||||
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
#include <utility>
|
||||
#include <unistd.h>
|
||||
@ -66,6 +67,14 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
||||
configureGpioByLabel(gpioConfig.first, *regularGpio);
|
||||
break;
|
||||
}
|
||||
case(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME):{
|
||||
auto regularGpio = dynamic_cast<GpiodRegularByLineName*>(gpioConfig.second);
|
||||
if(regularGpio == nullptr) {
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
}
|
||||
configureGpioByLineName(gpioConfig.first, *regularGpio);
|
||||
break;
|
||||
}
|
||||
case(gpio::GpioTypes::CALLBACK): {
|
||||
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioConfig.second);
|
||||
if(gpioCallback->callback == nullptr) {
|
||||
@ -84,13 +93,13 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByLabel(gpioId_t gpioId,
|
||||
std::string& label = gpioByLabel.label;
|
||||
struct gpiod_chip* chip = gpiod_chip_open_by_label(label.c_str());
|
||||
if (chip == nullptr) {
|
||||
sif::warning << "LinuxLibgpioIF::configureRegularGpio: Failed to open gpio from gpio "
|
||||
sif::warning << "LinuxLibgpioIF::configureGpioByLabel: Failed to open gpio from gpio "
|
||||
<< "group with label " << label << ". Gpio ID: " << gpioId << std::endl;
|
||||
return RETURN_FAILED;
|
||||
|
||||
}
|
||||
std::string failOutput = "label: " + label;
|
||||
return configureRegularGpio(gpioId, gpioByLabel.gpioType, chip, gpioByLabel, failOutput);
|
||||
return configureRegularGpio(gpioId, chip, gpioByLabel, failOutput);
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::configureGpioByChip(gpioId_t gpioId,
|
||||
@ -98,16 +107,41 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByChip(gpioId_t gpioId,
|
||||
std::string& chipname = gpioByChip.chipname;
|
||||
struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname.c_str());
|
||||
if (chip == nullptr) {
|
||||
sif::warning << "LinuxLibgpioIF::configureRegularGpio: Failed to open chip "
|
||||
sif::warning << "LinuxLibgpioIF::configureGpioByChip: Failed to open chip "
|
||||
<< chipname << ". Gpio ID: " << gpioId << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
std::string failOutput = "chipname: " + chipname;
|
||||
return configureRegularGpio(gpioId, gpioByChip.gpioType, chip, gpioByChip, failOutput);
|
||||
return configureRegularGpio(gpioId, chip, gpioByChip, failOutput);
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, gpio::GpioTypes gpioType,
|
||||
struct gpiod_chip* chip, GpiodRegularBase& regularGpio, std::string failOutput) {
|
||||
ReturnValue_t LinuxLibgpioIF::configureGpioByLineName(gpioId_t gpioId,
|
||||
GpiodRegularByLineName &gpioByLineName) {
|
||||
std::string& lineName = gpioByLineName.lineName;
|
||||
char chipname[MAX_CHIPNAME_LENGTH];
|
||||
unsigned int lineOffset;
|
||||
|
||||
int result = gpiod_ctxless_find_line(lineName.c_str(), chipname, MAX_CHIPNAME_LENGTH,
|
||||
&lineOffset);
|
||||
if (result != LINE_FOUND) {
|
||||
parseFindeLineResult(result, lineName);
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
gpioByLineName.lineNum = static_cast<int>(lineOffset);
|
||||
|
||||
struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname);
|
||||
if (chip == nullptr) {
|
||||
sif::warning << "LinuxLibgpioIF::configureGpioByLineName: Failed to open chip "
|
||||
<< chipname << ". <Gpio ID: " << gpioId << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
std::string failOutput = "line name: " + lineName;
|
||||
return configureRegularGpio(gpioId, chip, gpioByLineName, failOutput);
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod_chip* chip,
|
||||
GpiodRegularBase& regularGpio, std::string failOutput) {
|
||||
unsigned int lineNum;
|
||||
gpio::Direction direction;
|
||||
std::string consumer;
|
||||
@ -132,22 +166,10 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, gpio::GpioTy
|
||||
case(gpio::OUT): {
|
||||
result = gpiod_line_request_output(lineHandle, consumer.c_str(),
|
||||
regularGpio.initValue);
|
||||
if (result < 0) {
|
||||
sif::error << "LinuxLibgpioIF::configureRegularGpio: Failed to request line " << lineNum <<
|
||||
" from GPIO instance with ID: " << gpioId << std::endl;
|
||||
gpiod_line_release(lineHandle);
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(gpio::IN): {
|
||||
result = gpiod_line_request_input(lineHandle, consumer.c_str());
|
||||
if (result < 0) {
|
||||
sif::error << "LinuxLibgpioIF::configureGpios: Failed to request line "
|
||||
<< lineNum << " from GPIO instance with ID: " << gpioId << std::endl;
|
||||
gpiod_line_release(lineHandle);
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -156,6 +178,18 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, gpio::GpioTy
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "LinuxLibgpioIF::configureRegularGpio: Failed to request line " <<
|
||||
lineNum << " from GPIO instance with ID: " << gpioId << std::endl;
|
||||
#else
|
||||
sif::printError("LinuxLibgpioIF::configureRegularGpio: "
|
||||
"Failed to request line %d from GPIO instance with ID: %d\n", lineNum, gpioId);
|
||||
#endif
|
||||
gpiod_line_release(lineHandle);
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Write line handle to GPIO configuration instance so it can later be used to set or
|
||||
@ -173,8 +207,9 @@ ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
|
||||
}
|
||||
|
||||
auto gpioType = gpioMapIter->second->gpioType;
|
||||
if(gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_CHIP or
|
||||
gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LABEL) {
|
||||
if (gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_CHIP
|
||||
or gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LABEL
|
||||
or gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME) {
|
||||
auto regularGpio = dynamic_cast<GpiodRegularBase*>(gpioMapIter->second);
|
||||
if(regularGpio == nullptr) {
|
||||
return GPIO_TYPE_FAILURE;
|
||||
@ -187,7 +222,7 @@ ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
}
|
||||
gpioCallback->callback(gpioMapIter->first, gpio::GpioOperation::WRITE,
|
||||
1, gpioCallback->callbackArgs);
|
||||
gpio::Levels::HIGH, gpioCallback->callbackArgs);
|
||||
return RETURN_OK;
|
||||
}
|
||||
return GPIO_TYPE_FAILURE;
|
||||
@ -196,13 +231,18 @@ ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
|
||||
ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) {
|
||||
gpioMapIter = gpioMap.find(gpioId);
|
||||
if (gpioMapIter == gpioMap.end()) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LinuxLibgpioIF::pullLow: Unknown GPIO ID " << gpioId << std::endl;
|
||||
#else
|
||||
sif::printWarning("LinuxLibgpioIF::pullLow: Unknown GPIO ID %d\n", gpioId);
|
||||
#endif
|
||||
return UNKNOWN_GPIO_ID;
|
||||
}
|
||||
|
||||
auto& gpioType = gpioMapIter->second->gpioType;
|
||||
if(gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_CHIP or
|
||||
gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LABEL) {
|
||||
if (gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_CHIP
|
||||
or gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LABEL
|
||||
or gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME) {
|
||||
auto regularGpio = dynamic_cast<GpiodRegularBase*>(gpioMapIter->second);
|
||||
if(regularGpio == nullptr) {
|
||||
return GPIO_TYPE_FAILURE;
|
||||
@ -215,7 +255,7 @@ ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) {
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
}
|
||||
gpioCallback->callback(gpioMapIter->first, gpio::GpioOperation::WRITE,
|
||||
0, gpioCallback->callbackArgs);
|
||||
gpio::Levels::LOW, gpioCallback->callbackArgs);
|
||||
return RETURN_OK;
|
||||
}
|
||||
return GPIO_TYPE_FAILURE;
|
||||
@ -225,8 +265,13 @@ ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId,
|
||||
GpiodRegularBase& regularGpio, gpio::Levels logicLevel) {
|
||||
int result = gpiod_line_set_value(regularGpio.lineHandle, logicLevel);
|
||||
if (result < 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID " << gpioId <<
|
||||
" to logic level " << logicLevel << std::endl;
|
||||
#else
|
||||
sif::printWarning("LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID %d to "
|
||||
"logic level %d\n", gpioId, logicLevel);
|
||||
#endif
|
||||
return DRIVE_GPIO_FAILURE;
|
||||
}
|
||||
|
||||
@ -236,12 +281,18 @@ ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId,
|
||||
ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, int* gpioState) {
|
||||
gpioMapIter = gpioMap.find(gpioId);
|
||||
if (gpioMapIter == gpioMap.end()){
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LinuxLibgpioIF::readGpio: Unknown GPIOD ID " << gpioId << std::endl;
|
||||
#else
|
||||
sif::printWarning("LinuxLibgpioIF::readGpio: Unknown GPIOD ID %d\n", gpioId);
|
||||
#endif
|
||||
return UNKNOWN_GPIO_ID;
|
||||
}
|
||||
|
||||
auto gpioType = gpioMapIter->second->gpioType;
|
||||
if(gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_CHIP or
|
||||
gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LABEL) {
|
||||
if (gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_CHIP
|
||||
or gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LABEL
|
||||
or gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME) {
|
||||
auto regularGpio = dynamic_cast<GpiodRegularBase*>(gpioMapIter->second);
|
||||
if(regularGpio == nullptr) {
|
||||
return GPIO_TYPE_FAILURE;
|
||||
@ -249,10 +300,14 @@ ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, int* gpioState) {
|
||||
*gpioState = gpiod_line_get_value(regularGpio->lineHandle);
|
||||
}
|
||||
else {
|
||||
|
||||
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
|
||||
if(gpioCallback->callback == nullptr) {
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
}
|
||||
gpioCallback->callback(gpioMapIter->first, gpio::GpioOperation::READ,
|
||||
gpio::Levels::NONE, gpioCallback->callbackArgs);
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
@ -262,13 +317,14 @@ ReturnValue_t LinuxLibgpioIF::checkForConflicts(GpioMap& mapToAdd){
|
||||
for(auto& gpioConfig: mapToAdd) {
|
||||
switch(gpioConfig.second->gpioType) {
|
||||
case(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP):
|
||||
case(gpio::GpioTypes::GPIO_REGULAR_BY_LABEL): {
|
||||
case(gpio::GpioTypes::GPIO_REGULAR_BY_LABEL):
|
||||
case(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME): {
|
||||
auto regularGpio = dynamic_cast<GpiodRegularBase*>(gpioConfig.second);
|
||||
if(regularGpio == nullptr) {
|
||||
return GPIO_TYPE_FAILURE;
|
||||
}
|
||||
/* Check for conflicts and remove duplicates if necessary */
|
||||
result = checkForConflictsRegularGpio(gpioConfig.first, *regularGpio, mapToAdd);
|
||||
// Check for conflicts and remove duplicates if necessary
|
||||
result = checkForConflictsById(gpioConfig.first, gpioConfig.second->gpioType, mapToAdd);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
status = result;
|
||||
}
|
||||
@ -279,66 +335,108 @@ ReturnValue_t LinuxLibgpioIF::checkForConflicts(GpioMap& mapToAdd){
|
||||
if(callbackGpio == nullptr) {
|
||||
return GPIO_TYPE_FAILURE;
|
||||
}
|
||||
/* Check for conflicts and remove duplicates if necessary */
|
||||
result = checkForConflictsCallbackGpio(gpioConfig.first, callbackGpio, mapToAdd);
|
||||
// Check for conflicts and remove duplicates if necessary
|
||||
result = checkForConflictsById(gpioConfig.first,
|
||||
gpioConfig.second->gpioType, mapToAdd);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
status = result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "Invalid GPIO type detected for GPIO ID " << gpioConfig.first
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printWarning("Invalid GPIO type detected for GPIO ID %d\n", gpioConfig.first);
|
||||
#endif
|
||||
status = GPIO_TYPE_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::checkForConflictsRegularGpio(gpioId_t gpioIdToCheck,
|
||||
GpiodRegularBase& gpioToCheck, GpioMap& mapToAdd) {
|
||||
/* Cross check with private map */
|
||||
ReturnValue_t LinuxLibgpioIF::checkForConflictsById(gpioId_t gpioIdToCheck,
|
||||
gpio::GpioTypes expectedType, GpioMap& mapToAdd) {
|
||||
// Cross check with private map
|
||||
gpioMapIter = gpioMap.find(gpioIdToCheck);
|
||||
if(gpioMapIter != gpioMap.end()) {
|
||||
auto& gpioType = gpioMapIter->second->gpioType;
|
||||
if(gpioType != gpio::GpioTypes::GPIO_REGULAR_BY_CHIP and
|
||||
gpioType != gpio::GpioTypes::GPIO_REGULAR_BY_LABEL) {
|
||||
sif::warning << "LinuxLibgpioIF::checkForConflicts: ID already exists for different "
|
||||
"GPIO type" << gpioIdToCheck << ". Removing duplicate." << std::endl;
|
||||
mapToAdd.erase(gpioIdToCheck);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
bool eraseDuplicateDifferentType = false;
|
||||
switch(expectedType) {
|
||||
case(gpio::GpioTypes::NONE): {
|
||||
break;
|
||||
}
|
||||
auto ownRegularGpio = dynamic_cast<GpiodRegularBase*>(gpioMapIter->second);
|
||||
if(ownRegularGpio == nullptr) {
|
||||
return GPIO_TYPE_FAILURE;
|
||||
case(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP):
|
||||
case(gpio::GpioTypes::GPIO_REGULAR_BY_LABEL):
|
||||
case(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME): {
|
||||
if(gpioType == gpio::GpioTypes::NONE or gpioType == gpio::GpioTypes::CALLBACK) {
|
||||
eraseDuplicateDifferentType = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(gpio::GpioTypes::CALLBACK): {
|
||||
if(gpioType != gpio::GpioTypes::CALLBACK) {
|
||||
eraseDuplicateDifferentType = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(eraseDuplicateDifferentType) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LinuxLibgpioIF::checkForConflicts: ID already exists for "
|
||||
"different GPIO type " << gpioIdToCheck <<
|
||||
". Removing duplicate from map to add" << std::endl;
|
||||
#else
|
||||
sif::printWarning("LinuxLibgpioIF::checkForConflicts: ID already exists for "
|
||||
"different GPIO type %d. Removing duplicate from map to add\n", gpioIdToCheck);
|
||||
#endif
|
||||
mapToAdd.erase(gpioIdToCheck);
|
||||
return GPIO_DUPLICATE_DETECTED;
|
||||
}
|
||||
|
||||
/* Remove element from map to add because a entry for this GPIO
|
||||
already exists */
|
||||
sif::warning << "LinuxLibgpioIF::checkForConflictsRegularGpio: Duplicate GPIO definition"
|
||||
<< " detected. Duplicate will be removed from map to add." << std::endl;
|
||||
// Remove element from map to add because a entry for this GPIO already exists
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LinuxLibgpioIF::checkForConflictsRegularGpio: Duplicate GPIO "
|
||||
"definition with ID " << gpioIdToCheck << " detected. " <<
|
||||
"Duplicate will be removed from map to add" << std::endl;
|
||||
#else
|
||||
sif::printWarning("LinuxLibgpioIF::checkForConflictsRegularGpio: Duplicate GPIO definition "
|
||||
"with ID %d detected. Duplicate will be removed from map to add\n", gpioIdToCheck);
|
||||
#endif
|
||||
mapToAdd.erase(gpioIdToCheck);
|
||||
return GPIO_DUPLICATE_DETECTED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::checkForConflictsCallbackGpio(gpioId_t gpioIdToCheck,
|
||||
GpioCallback *callbackGpio, GpioMap& mapToAdd) {
|
||||
/* Cross check with private map */
|
||||
gpioMapIter = gpioMap.find(gpioIdToCheck);
|
||||
if(gpioMapIter != gpioMap.end()) {
|
||||
if(gpioMapIter->second->gpioType != gpio::GpioTypes::CALLBACK) {
|
||||
sif::warning << "LinuxLibgpioIF::checkForConflicts: ID already exists for different "
|
||||
"GPIO type" << gpioIdToCheck << ". Removing duplicate." << std::endl;
|
||||
mapToAdd.erase(gpioIdToCheck);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
void LinuxLibgpioIF::parseFindeLineResult(int result, std::string& lineName) {
|
||||
switch (result) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
case LINE_NOT_EXISTS:
|
||||
case LINE_ERROR: {
|
||||
sif::warning << "LinuxLibgpioIF::parseFindeLineResult: Line with name " << lineName <<
|
||||
" does not exist" << std::endl;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sif::warning << "LinuxLibgpioIF::parseFindeLineResult: Unknown return code for line "
|
||||
"with name " << lineName << std::endl;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
case LINE_NOT_EXISTS:
|
||||
case LINE_ERROR: {
|
||||
sif::printWarning("LinuxLibgpioIF::parseFindeLineResult: Line with name %s "
|
||||
"does not exist\n", lineName);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sif::printWarning("LinuxLibgpioIF::parseFindeLineResult: Unknown return code for line "
|
||||
"with name %s\n", lineName);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Remove element from map to add because a entry for this GPIO
|
||||
already exists */
|
||||
sif::warning << "LinuxLibgpioIF::checkForConflictsRegularGpio: Duplicate GPIO definition"
|
||||
<< " detected. Duplicate will be removed from map to add." << std::endl;
|
||||
mapToAdd.erase(gpioIdToCheck);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
#ifndef LINUX_GPIO_LINUXLIBGPIOIF_H_
|
||||
#define LINUX_GPIO_LINUXLIBGPIOIF_H_
|
||||
|
||||
#include "../../common/gpio/GpioIF.h"
|
||||
#include <returnvalues/classIds.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include "fsfw/returnvalues/FwClassIds.h"
|
||||
#include "fsfw_hal/common/gpio/GpioIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
|
||||
class GpioCookie;
|
||||
class GpiodRegularIF;
|
||||
|
||||
/**
|
||||
* @brief This class implements the GpioIF for a linux based system. The
|
||||
* implementation is based on the libgpiod lib which requires linux 4.8
|
||||
* or higher.
|
||||
* @note The Petalinux SDK from Xilinx supports libgpiod since Petalinux
|
||||
* 2019.1.
|
||||
* @brief This class implements the GpioIF for a linux based system.
|
||||
* @details
|
||||
* This implementation is based on the libgpiod lib which requires Linux 4.8 or higher.
|
||||
* @note
|
||||
* The Petalinux SDK from Xilinx supports libgpiod since Petalinux 2019.1.
|
||||
*/
|
||||
class LinuxLibgpioIF : public GpioIF, public SystemObject {
|
||||
public:
|
||||
@ -28,6 +28,8 @@ public:
|
||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 3);
|
||||
static constexpr ReturnValue_t GPIO_INVALID_INSTANCE =
|
||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 4);
|
||||
static constexpr ReturnValue_t GPIO_DUPLICATE_DETECTED =
|
||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 5);
|
||||
|
||||
LinuxLibgpioIF(object_id_t objectId);
|
||||
virtual ~LinuxLibgpioIF();
|
||||
@ -38,7 +40,13 @@ public:
|
||||
ReturnValue_t readGpio(gpioId_t gpioId, int* gpioState) override;
|
||||
|
||||
private:
|
||||
/* Holds the information and configuration of all used GPIOs */
|
||||
|
||||
static const size_t MAX_CHIPNAME_LENGTH = 11;
|
||||
static const int LINE_NOT_EXISTS = 0;
|
||||
static const int LINE_ERROR = -1;
|
||||
static const int LINE_FOUND = 1;
|
||||
|
||||
// Holds the information and configuration of all used GPIOs
|
||||
GpioUnorderedMap gpioMap;
|
||||
GpioUnorderedMapIter gpioMapIter;
|
||||
|
||||
@ -53,8 +61,10 @@ private:
|
||||
|
||||
ReturnValue_t configureGpioByLabel(gpioId_t gpioId, GpiodRegularByLabel& gpioByLabel);
|
||||
ReturnValue_t configureGpioByChip(gpioId_t gpioId, GpiodRegularByChip& gpioByChip);
|
||||
ReturnValue_t configureRegularGpio(gpioId_t gpioId, gpio::GpioTypes gpioType,
|
||||
struct gpiod_chip* chip, GpiodRegularBase& regularGpio, std::string failOutput);
|
||||
ReturnValue_t configureGpioByLineName(gpioId_t gpioId,
|
||||
GpiodRegularByLineName &gpioByLineName);
|
||||
ReturnValue_t configureRegularGpio(gpioId_t gpioId, struct gpiod_chip* chip,
|
||||
GpiodRegularBase& regularGpio, std::string failOutput);
|
||||
|
||||
/**
|
||||
* @brief This function checks if GPIOs are already registered and whether
|
||||
@ -67,9 +77,7 @@ private:
|
||||
*/
|
||||
ReturnValue_t checkForConflicts(GpioMap& mapToAdd);
|
||||
|
||||
ReturnValue_t checkForConflictsRegularGpio(gpioId_t gpiodId, GpiodRegularBase& regularGpio,
|
||||
GpioMap& mapToAdd);
|
||||
ReturnValue_t checkForConflictsCallbackGpio(gpioId_t gpiodId, GpioCallback* regularGpio,
|
||||
ReturnValue_t checkForConflictsById(gpioId_t gpiodId, gpio::GpioTypes type,
|
||||
GpioMap& mapToAdd);
|
||||
|
||||
/**
|
||||
@ -77,6 +85,7 @@ private:
|
||||
*/
|
||||
ReturnValue_t configureGpios(GpioMap& mapToAdd);
|
||||
|
||||
void parseFindeLineResult(int result, std::string& lineName);
|
||||
};
|
||||
|
||||
#endif /* LINUX_GPIO_LINUXLIBGPIOIF_H_ */
|
||||
|
76
scripts/coverage.py
Executable file
76
scripts/coverage.py
Executable file
@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*
|
||||
"""Small portable helper script to generate LCOV HTML coverage data"""
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
import time
|
||||
import argparse
|
||||
from typing import List
|
||||
|
||||
|
||||
"""Copy this helper script into your project folder. It will try to determine a CMake build folder
|
||||
and then attempt to build your project with coverage information.
|
||||
|
||||
See Unittest documentation at https://egit.irs.uni-stuttgart.de/fsfw/fsfw for more
|
||||
information how to set up the build folder.
|
||||
"""
|
||||
def main():
|
||||
|
||||
parser = argparse.ArgumentParser(description="Processing arguments for LCOV helper script.")
|
||||
|
||||
build_dir_list = []
|
||||
if not os.path.isfile('README.md'):
|
||||
os.chdir('..')
|
||||
for directory in os.listdir("."):
|
||||
if os.path.isdir(directory):
|
||||
os.chdir(directory)
|
||||
check_for_cmake_build_dir(build_dir_list)
|
||||
os.chdir("..")
|
||||
|
||||
if len(build_dir_list) == 0:
|
||||
print("No valid CMake build directory found. Trying to set up hosted build")
|
||||
build_directory = 'build-Debug-Host'
|
||||
os.mkdir(build_directory)
|
||||
os.chdir(build_directory)
|
||||
os.system('cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON ..')
|
||||
os.chdir('..')
|
||||
elif len(build_dir_list) == 1:
|
||||
build_directory = build_dir_list[0]
|
||||
else:
|
||||
print("Multiple build directories found!")
|
||||
build_directory = determine_build_dir(build_dir_list)
|
||||
perform_lcov_operation(build_directory)
|
||||
|
||||
|
||||
def check_for_cmake_build_dir(build_dir_dict: list):
|
||||
if os.path.isfile("CMakeCache.txt"):
|
||||
build_dir_dict.append(os.getcwd())
|
||||
|
||||
|
||||
def perform_lcov_operation(directory):
|
||||
os.chdir(directory)
|
||||
os.system("cmake --build . -- fsfw-tests_coverage -j")
|
||||
|
||||
|
||||
def determine_build_dir(build_dir_list: List[str]):
|
||||
build_directory = ""
|
||||
for idx, directory in enumerate(build_dir_list):
|
||||
print(f"{idx + 1}: {directory}")
|
||||
while True:
|
||||
idx = input("Pick the directory to perform LCOV HTML generation by index: ")
|
||||
if not idx.isdigit():
|
||||
print("Invalid input!")
|
||||
continue
|
||||
|
||||
idx = int(idx)
|
||||
if idx > len(build_dir_list) or idx < 1:
|
||||
print("Invalid input!")
|
||||
continue
|
||||
build_directory = build_dir_list[idx - 1]
|
||||
break
|
||||
return build_directory
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,10 +0,0 @@
|
||||
#ifndef FSFW_VERSION_H_
|
||||
#define FSFW_VERSION_H_
|
||||
|
||||
const char* const FSFW_VERSION_NAME = "ASTP";
|
||||
|
||||
#define FSFW_VERSION 2
|
||||
#define FSFW_SUBVERSION 0
|
||||
#define FSFW_REVISION 0
|
||||
|
||||
#endif /* FSFW_VERSION_H_ */
|
9
src/fsfw/FSFWVersion.h.in
Normal file
9
src/fsfw/FSFWVersion.h.in
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef FSFW_VERSION_H_
|
||||
#define FSFW_VERSION_H_
|
||||
|
||||
// Versioning is kept in project CMakeLists.txt file
|
||||
#define FSFW_VERSION @FSFW_VERSION@
|
||||
#define FSFW_SUBVERSION @FSFW_SUBVERSION@
|
||||
#define FSFW_REVISION @FSFW_REVISION@
|
||||
|
||||
#endif /* FSFW_VERSION_H_ */
|
@ -118,7 +118,7 @@ void TmPacketStoredBase::handleStoreFailure(const char *const packetType, Return
|
||||
"%d too large\n", packetType, sizeToReserve);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -3,6 +3,6 @@ if(FSFW_ADD_INTERNAL_TESTS)
|
||||
add_subdirectory(internal)
|
||||
endif()
|
||||
|
||||
if(FSFW_ADD_UNITTESTS)
|
||||
if(FSFW_BUILD_UNITTESTS)
|
||||
add_subdirectory(unit)
|
||||
endif()
|
||||
|
@ -1,9 +1,9 @@
|
||||
#include "fsfw_tests/internal/InternalUnitTester.h"
|
||||
#include "fsfw_tests/internal/UnittDefinitions.h"
|
||||
|
||||
#include "fsfw_tests/internal/osal/IntTestMq.h"
|
||||
#include "fsfw_tests/internal/osal/IntTestSemaphore.h"
|
||||
#include "fsfw_tests/internal/osal/IntTestMutex.h"
|
||||
#include "fsfw_tests/internal/osal/testMq.h"
|
||||
#include "fsfw_tests/internal/osal/testSemaphore.h"
|
||||
#include "fsfw_tests/internal/osal/testMutex.h"
|
||||
#include "fsfw_tests/internal/serialize/IntTestSerialization.h"
|
||||
#include "fsfw_tests/internal/globalfunctions/TestArrayPrinter.h"
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
IntTestMq.cpp
|
||||
IntTestMutex.cpp
|
||||
IntTestSemaphore.cpp
|
||||
testMq.cpp
|
||||
testMutex.cpp
|
||||
testSemaphore.cpp
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "fsfw_tests/internal/osal/IntTestMq.h"
|
||||
#include "testMq.h"
|
||||
#include "fsfw_tests/internal/UnittDefinitions.h"
|
||||
|
||||
#include <fsfw/ipc/MessageQueueIF.h>
|
@ -1,4 +1,4 @@
|
||||
#include "fsfw_tests/internal/osal/IntTestMutex.h"
|
||||
#include "testMutex.h"
|
||||
#include "fsfw_tests/internal/UnittDefinitions.h"
|
||||
#include "fsfw/platform.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw_tests/internal/osal/IntTestSemaphore.h"
|
||||
#include "testSemaphore.h"
|
||||
#include "fsfw_tests/internal/UnittDefinitions.h"
|
||||
|
||||
#include "fsfw/tasks/SemaphoreFactory.h"
|
@ -1,16 +1,17 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
CatchDefinitions.cpp
|
||||
CatchFactory.cpp
|
||||
printChar.cpp
|
||||
)
|
||||
|
||||
if(FSFW_CUSTOM_UNITTEST_RUNNER)
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
# if(FSFW_CUSTOM_UNITTEST_RUNNER)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
CatchRunner.cpp
|
||||
CatchSetup.cpp
|
||||
)
|
||||
endif()
|
||||
# endif()
|
||||
|
||||
add_subdirectory(testcfg)
|
||||
add_subdirectory(action)
|
||||
add_subdirectory(container)
|
||||
add_subdirectory(osal)
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "CatchFactory.h"
|
||||
#include "tests/TestsConfig.h"
|
||||
#include "datapoollocal/LocalPoolOwnerBase.h"
|
||||
#include "mocks/HkReceiverMock.h"
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef FSFW_CATCHFACTORY_H_
|
||||
#define FSFW_CATCHFACTORY_H_
|
||||
|
||||
#include "TestsConfig.h"
|
||||
#include "tests/TestsConfig.h"
|
||||
#include "fsfw/objectmanager/SystemObjectIF.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
extern int customSetup();
|
||||
|
||||
int fsfwtest::customMain(int argc, char* argv[]) {
|
||||
int main(int argc, char* argv[]) {
|
||||
customSetup();
|
||||
|
||||
// Catch internal function call
|
||||
|
@ -7,7 +7,7 @@ namespace fsfwtest {
|
||||
* Can be called by upper level main() if default Catch2 main is overriden
|
||||
* @return
|
||||
*/
|
||||
int customMain(int argc, char* argv[]);
|
||||
//int customMain(int argc, char* argv[]);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
TestActionHelper.cpp
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
RingBufferTest.cpp
|
||||
TestArrayList.cpp
|
||||
TestDynamicFifo.cpp
|
||||
|
@ -1,4 +1,4 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
LocalPoolVariableTest.cpp
|
||||
LocalPoolVectorTest.cpp
|
||||
DataSetTest.cpp
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "LocalPoolOwnerBase.h"
|
||||
#include "tests/TestsConfig.h"
|
||||
#include "fsfw_tests/unit/CatchDefinitions.h"
|
||||
|
||||
#include <fsfw/objectmanager/ObjectManager.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_
|
||||
#define FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_
|
||||
|
||||
#include "objects/systemObjectList.h"
|
||||
#include "tests/TestsConfig.h"
|
||||
#include "../mocks/MessageQueueMockBase.h"
|
||||
|
||||
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "LocalPoolOwnerBase.h"
|
||||
#include "tests/TestsConfig.h"
|
||||
#include "fsfw_tests/unit/CatchDefinitions.h"
|
||||
|
||||
#include <fsfw/objectmanager/ObjectManager.h>
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "LocalPoolOwnerBase.h"
|
||||
#include "tests/TestsConfig.h"
|
||||
#include "fsfw_tests/unit/CatchDefinitions.h"
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
@ -1,3 +1,3 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
testDleEncoder.cpp
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
TestMessageQueue.cpp
|
||||
TestSemaphore.cpp
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
TestSerialBufferAdapter.cpp
|
||||
TestSerialization.cpp
|
||||
TestSerialLinkedPacket.cpp
|
||||
|
@ -1,4 +1,4 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
TestNewAccessor.cpp
|
||||
TestPool.cpp
|
||||
)
|
||||
|
23
tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt
Normal file
23
tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt
Normal file
@ -0,0 +1,23 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
ipc/MissionMessageTypes.cpp
|
||||
pollingsequence/PollingSequenceFactory.cpp
|
||||
)
|
||||
|
||||
# Add include paths for the executable
|
||||
target_include_directories(${FSFW_TEST_TGT} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
# If a special translation file for object IDs exists, compile it.
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp")
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
objects/translateObjects.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# If a special translation file for events exists, compile it.
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp")
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
events/translateEvents.cpp
|
||||
)
|
||||
endif()
|
@ -9,22 +9,19 @@
|
||||
//! the C stdio functions can be used alternatively
|
||||
#define FSFW_CPP_OSTREAM_ENABLED 0
|
||||
|
||||
//! More FSFW related printouts. Useful for development.
|
||||
#define FSFW_ENHANCED_PRINTOUT 0
|
||||
//! More FSFW related printouts depending on level. Useful for development.
|
||||
#define FSFW_VERBOSE_LEVEL 0
|
||||
|
||||
//! Can be used to completely disable printouts, even the C stdio ones.
|
||||
//! By default, printouts will be disabled for the unit tests.
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_ENHANCED_PRINTOUT == 0
|
||||
#ifndef FSFW_DISABLE_PRINTOUT
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_VERBOSE_LEVEL == 0
|
||||
#define FSFW_DISABLE_PRINTOUT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//! Can be used to enable additional debugging printouts for developing the FSFW
|
||||
#define FSFW_PRINT_VERBOSITY_LEVEL 0
|
||||
#define FSFW_USE_PUS_C_TELEMETRY 1
|
||||
#define FSFW_USE_PUS_C_TELECOMMANDS 1
|
||||
|
||||
//! Can be used to disable the ANSI color sequences for C stdio.
|
||||
#define FSFW_COLORED_OUTPUT 0
|
||||
#define FSFW_COLORED_OUTPUT 1
|
||||
|
||||
//! If FSFW_OBJ_EVENT_TRANSLATION is set to one,
|
||||
//! additional output which requires the translation files translateObjects
|
||||
@ -54,9 +51,9 @@
|
||||
#define FSFW_USE_REALTIME_FOR_LINUX 1
|
||||
|
||||
namespace fsfwconfig {
|
||||
//! Default timestamp size. The default timestamp will be an eight byte CDC
|
||||
//! short timestamp.
|
||||
static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 8;
|
||||
|
||||
//! Default timestamp size. The default timestamp will be an seven byte CDC short timestamp.
|
||||
static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 7;
|
||||
|
||||
//! Configure the allocated pool sizes for the event manager.
|
||||
static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240;
|
||||
@ -65,13 +62,13 @@ static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120;
|
||||
|
||||
//! Defines the FIFO depth of each commanding service base which
|
||||
//! also determines how many commands a CSB service can handle in one cycle
|
||||
//! simulataneously. This will increase the required RAM for
|
||||
//! simultaneously. This will increase the required RAM for
|
||||
//! each CSB service !
|
||||
static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 6;
|
||||
|
||||
static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 124;
|
||||
|
||||
static constexpr size_t FSFW_MAX_TM_PACKET_SIZE = 1500;
|
||||
static constexpr size_t FSFW_MAX_TM_PACKET_SIZE = 2048;
|
||||
|
||||
}
|
||||
|
15
tests/src/fsfw_tests/unit/testcfg/OBSWConfig.h.in
Normal file
15
tests/src/fsfw_tests/unit/testcfg/OBSWConfig.h.in
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef CONFIG_TMTC_TMTCSIZE_H_
|
||||
#define CONFIG_TMTC_TMTCSIZE_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
#define OBSW_PRINT_MISSED_DEADLINES 0
|
||||
#define OBSW_VERBOSE_LEVEL 0
|
||||
#define OBSW_ADD_TEST_CODE 1
|
||||
|
||||
namespace config {
|
||||
static constexpr uint32_t MAX_STORED_TELECOMMANDS = 2000;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_TMTC_TMTCSIZE_H_ */
|
@ -2,7 +2,7 @@
|
||||
#define CONFIG_DEVICES_LOGICALADDRESSES_H_
|
||||
|
||||
#include <fsfw/devicehandlers/CookieIF.h>
|
||||
#include <fsfw/unittest/config/objects/systemObjectList.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace addresses {
|
@ -1,8 +1,9 @@
|
||||
#ifndef CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_
|
||||
#define CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_
|
||||
|
||||
#include "fsfw/events/fwSubsystemIdRanges.h"
|
||||
#include <cstdint>
|
||||
#include <fsfw/events/fwSubsystemIdRanges.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Custom subsystem IDs can be added here
|
||||
@ -12,6 +13,7 @@
|
||||
namespace SUBSYSTEM_ID {
|
||||
enum: uint8_t {
|
||||
SUBSYSTEM_ID_START = FW_SUBSYSTEM_ID_RANGE,
|
||||
SUBSYSTEM_ID_END // [EXPORT] : [END]
|
||||
};
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#ifndef HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_
|
||||
#define HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_
|
||||
|
||||
#include "fsfw/objectmanager/frameworkObjects.h"
|
||||
#include <cstdint>
|
||||
#include <fsfw/objectmanager/frameworkObjects.h>
|
||||
|
||||
// The objects will be instantiated in the ID order
|
||||
namespace objects {
|
||||
@ -11,10 +11,6 @@ namespace objects {
|
||||
FSFW_CONFIG_RESERVED_START = PUS_SERVICE_1_VERIFICATION,
|
||||
FSFW_CONFIG_RESERVED_END = TM_STORE,
|
||||
|
||||
CCSDS_DISTRIBUTOR = 10,
|
||||
PUS_DISTRIBUTOR = 11,
|
||||
TM_FUNNEL = 12,
|
||||
|
||||
UDP_BRIDGE = 15,
|
||||
UDP_POLLING_TASK = 16,
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "PollingSequenceFactory.h"
|
||||
|
||||
#include <TestsConfig.h>
|
||||
#include "tests/TestsConfig.h"
|
||||
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
|
@ -1,7 +1,7 @@
|
||||
#ifndef CONFIG_RETURNVALUES_CLASSIDS_H_
|
||||
#define CONFIG_RETURNVALUES_CLASSIDS_H_
|
||||
|
||||
#include <fsfw/returnvalues/FwClassIds.h>
|
||||
#include "fsfw/returnvalues/FwClassIds.h"
|
||||
|
||||
/**
|
||||
* @brief CLASS_ID defintions which are required for custom returnvalues.
|
@ -1,6 +1,5 @@
|
||||
#include <fsfw/unittest/catch2/catch.hpp>
|
||||
#include <fsfw/unittest/core/CatchDefinitions.h>
|
||||
|
||||
#include "fsfw_tests/unit/CatchDefinitions.h"
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
/**
|
||||
* @brief Template test file
|
@ -1,3 +1,3 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
TestCountdown.cpp
|
||||
)
|
||||
|
@ -1,3 +1,3 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
PusTmTest.cpp
|
||||
)
|
||||
|
@ -1,261 +0,0 @@
|
||||
################################################################################
|
||||
# CMake support for the Flight Software Framework Tests
|
||||
# Author: R. Mueller
|
||||
################################################################################
|
||||
|
||||
################################################################################
|
||||
# Pre-Project preparation
|
||||
################################################################################
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
# set(CMAKE_VERBOSE TRUE)
|
||||
# set(CODE_COVERAGE_VERBOSE TRUE)
|
||||
|
||||
set(CMAKE_SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
option(TMTC_TEST "Build binary for manual or automatic TMTC tests" FALSE)
|
||||
option(GENERATE_COVERAGE
|
||||
"Specify whether coverage data is generated with GCOV"
|
||||
TRUE
|
||||
)
|
||||
|
||||
set(FSFW_ADD_UNITTESTS ON)
|
||||
|
||||
if(TMTC_TEST)
|
||||
set(LINK_CATCH2 FALSE)
|
||||
else()
|
||||
set(LINK_CATCH2 TRUE)
|
||||
endif()
|
||||
|
||||
# Tests can be built with the Host OSAL or with the Linux OSAL.
|
||||
if(NOT FSFW_OSAL)
|
||||
set(FSFW_OSAL host CACHE STRING "OS for the FSFW.")
|
||||
endif()
|
||||
|
||||
option(FSFW_CUSTOM_UNITTEST_RUNNER
|
||||
"Specify whether custom main or Catch2 main is used" TRUE
|
||||
)
|
||||
|
||||
# Project Name
|
||||
project(fsfw-tests C CXX)
|
||||
|
||||
################################################################################
|
||||
# Pre-Sources preparation
|
||||
################################################################################
|
||||
|
||||
# Specify the C++ standard
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
# Set names and variables
|
||||
set(TARGET_NAME ${CMAKE_PROJECT_NAME})
|
||||
if(FSFW_CUSTOM_UNITTEST_RUNNER)
|
||||
set(CATCH2_TARGET Catch2)
|
||||
else()
|
||||
set(CATCH2_TARGET Catch2WithMain)
|
||||
endif()
|
||||
set(LIB_FSFW_NAME fsfw)
|
||||
|
||||
# Set path names
|
||||
set(FSFW_PATH fsfw)
|
||||
set(CATCH2_PATH Catch2)
|
||||
set(FSFW_TESTS_PATH fsfw/unittest)
|
||||
set(TEST_SETUP_PATH unittest)
|
||||
set(TMTC_TEST_PATH tests)
|
||||
|
||||
# Analyse different OS and architecture/target options and
|
||||
# determine BSP_PATH
|
||||
|
||||
# FreeRTOS
|
||||
if(FSFW_OSAL STREQUAL linux)
|
||||
add_definitions(-DUNIX -DLINUX)
|
||||
find_package(Threads REQUIRED)
|
||||
# Hosted
|
||||
else()
|
||||
if(WIN32)
|
||||
add_definitions(-DWIN32)
|
||||
elseif(UNIX)
|
||||
find_package(Threads REQUIRED)
|
||||
add_definitions(-DUNIX -DLINUX)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(GENERATE_COVERAGE)
|
||||
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/cmake-modules)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
include(CodeCoverage)
|
||||
# Add compile options on target base, we don't want coverage for Catch2
|
||||
# append_coverage_compiler_flags()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(FSFW_CONFIG_PATH testcfg)
|
||||
set(FSFW_ADDITIONAL_INC_PATHS ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
configure_file(${FSFW_CONFIG_PATH}/FSFWConfig.h.in FSFWConfig.h)
|
||||
configure_file(${FSFW_CONFIG_PATH}/OBSWConfig.h.in OBSWConfig.h)
|
||||
configure_file(${FSFW_CONFIG_PATH}/TestsConfig.h.in TestsConfig.h)
|
||||
|
||||
################################################################################
|
||||
# Executable and Sources
|
||||
################################################################################
|
||||
|
||||
# Add executable
|
||||
add_executable(${TARGET_NAME})
|
||||
|
||||
# Add subdirectories
|
||||
add_subdirectory(${FSFW_PATH})
|
||||
add_subdirectory(${FSFW_CONFIG_PATH})
|
||||
|
||||
if(LINK_CATCH2)
|
||||
add_subdirectory(${CATCH2_PATH})
|
||||
add_subdirectory(${TEST_SETUP_PATH})
|
||||
else()
|
||||
target_compile_definitions(${TARGET_NAME} PRIVATE
|
||||
FSFW_DISABLE_PRINTOUT=0
|
||||
)
|
||||
target_compile_definitions(${LIB_FSFW_NAME} PRIVATE
|
||||
FSFW_DISABLE_PRINTOUT=0
|
||||
)
|
||||
add_subdirectory(${TMTC_TEST_PATH})
|
||||
add_subdirectory(${FSFW_TESTS_PATH})
|
||||
endif()
|
||||
|
||||
|
||||
################################################################################
|
||||
# Post-Sources preparation
|
||||
################################################################################
|
||||
|
||||
# Add libraries for all sources.
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE
|
||||
${LIB_FSFW_NAME}
|
||||
)
|
||||
|
||||
if(LINK_CATCH2)
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE
|
||||
${CATCH2_TARGET}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(GENERATE_COVERAGE)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
# set(CODE_COVERAGE_VERBOSE TRUE)
|
||||
include(CodeCoverage)
|
||||
|
||||
# Remove quotes.
|
||||
separate_arguments(COVERAGE_COMPILER_FLAGS
|
||||
NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}"
|
||||
)
|
||||
|
||||
# Add compile options manually, we don't want coverage for Catch2
|
||||
target_compile_options(${TARGET_NAME} PRIVATE
|
||||
"${COVERAGE_COMPILER_FLAGS}"
|
||||
)
|
||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
||||
"${COVERAGE_COMPILER_FLAGS}"
|
||||
)
|
||||
|
||||
# Exclude internal unittest from coverage for now.
|
||||
if(WIN32)
|
||||
set(GCOVR_ADDITIONAL_ARGS
|
||||
"--exclude-throw-branches"
|
||||
"--exclude-unreachable-branches"
|
||||
)
|
||||
set(COVERAGE_EXCLUDES
|
||||
"/c/msys64/mingw64/*" "Catch2"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/fsfw/unittest/internal"
|
||||
)
|
||||
elseif(UNIX)
|
||||
set(COVERAGE_EXCLUDES
|
||||
"/usr/include/*" "/usr/bin/*" "Catch2/*"
|
||||
"fsfw/unittest/internal/*"
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_options(${TARGET_NAME} PRIVATE
|
||||
-fprofile-arcs
|
||||
-ftest-coverage
|
||||
)
|
||||
target_link_options(${LIB_FSFW_NAME} PRIVATE
|
||||
-fprofile-arcs
|
||||
-ftest-coverage
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
setup_target_for_coverage_gcovr_html(
|
||||
NAME ${TARGET_NAME}_coverage
|
||||
EXECUTABLE ${TARGET_NAME}
|
||||
DEPENDENCIES ${TARGET_NAME}
|
||||
)
|
||||
else()
|
||||
setup_target_for_coverage_lcov(
|
||||
NAME ${TARGET_NAME}_coverage
|
||||
EXECUTABLE ${TARGET_NAME}
|
||||
DEPENDENCIES ${TARGET_NAME}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Add include paths for all sources.
|
||||
target_include_directories(${TARGET_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${FSFW_CONFIG_PATH}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(WARNING_FLAGS
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wshadow=local
|
||||
-Wimplicit-fallthrough=1
|
||||
-Wno-unused-parameter
|
||||
-Wno-psabi
|
||||
)
|
||||
|
||||
# Remove unused sections.
|
||||
target_compile_options(${TARGET_NAME} PRIVATE
|
||||
"-ffunction-sections"
|
||||
"-fdata-sections"
|
||||
)
|
||||
|
||||
# Removed unused sections.
|
||||
target_link_options(${TARGET_NAME} PRIVATE
|
||||
"-Wl,--gc-sections"
|
||||
)
|
||||
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
set(COMPILER_FLAGS "/permissive-")
|
||||
endif()
|
||||
|
||||
if(CMAKE_VERBOSE)
|
||||
message(STATUS "Warning flags: ${WARNING_FLAGS}")
|
||||
endif()
|
||||
|
||||
# Compile options for all sources.
|
||||
target_compile_options(${TARGET_NAME} PRIVATE
|
||||
${WARNING_FLAGS}
|
||||
)
|
||||
|
||||
if(NOT CMAKE_SIZE)
|
||||
set(CMAKE_SIZE size)
|
||||
if(WIN32)
|
||||
set(FILE_SUFFIX ".exe")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
string(CONCAT POST_BUILD_COMMENT
|
||||
"Build directory: ${CMAKE_BINARY_DIR}\n"
|
||||
"Target OSAL: ${FSFW_OSAL}\n"
|
||||
"Target Build Type: ${CMAKE_BUILD_TYPE}"
|
||||
)
|
||||
|
||||
add_custom_command(TARGET ${TARGET_NAME}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_SIZE} ${TARGET_NAME}${FILE_SUFFIX}
|
||||
COMMENT ${POST_BUILD_COMMENT}
|
||||
)
|
||||
|
||||
include (${CMAKE_SCRIPT_PATH}/BuildType.cmake)
|
||||
set_build_type()
|
@ -1,19 +0,0 @@
|
||||
## FSFW Testing
|
||||
|
||||
This folder contains testing and unit testing components.
|
||||
|
||||
### Instructions
|
||||
|
||||
The easiest way to run the unittest contained in this folder is to follow
|
||||
the steps in the [test repository](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_tests).
|
||||
This is recommended even if the goal is to set up a custom test repository to have
|
||||
a starting point.
|
||||
|
||||
To set up a custom test repository or project, following steps can be performed:
|
||||
|
||||
1. Copy the user folder content into the project root.
|
||||
2. Clone [Catch2](https://github.com/catchorg/Catch2) in the project root.
|
||||
3. Use the `CMakeLists.txt` as a starting point to add tests and build the test
|
||||
executable.
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
lcov --capture --directory . --output-file coverage.info
|
||||
genhtml coverage.info --output-directory _coverage
|
@ -1,11 +0,0 @@
|
||||
target_sources(${TARGET_NAME}
|
||||
PRIVATE
|
||||
ipc/MissionMessageTypes.cpp
|
||||
pollingsequence/PollingSequenceFactory.cpp
|
||||
)
|
||||
|
||||
# Add include paths for the executable
|
||||
target_include_directories(${TARGET_NAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
@ -1,8 +0,0 @@
|
||||
#ifndef TESTCFG_OBSWCONFIG_H_
|
||||
#define TESTCFG_OBSWCONFIG_H_
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* TESTCFG_OBSWCONFIG_H_ */
|
Loading…
Reference in New Issue
Block a user