Compare commits

...

64 Commits

Author SHA1 Message Date
70f0a72f1b added explicit checkout of v3.0.0-preview5 2022-04-27 13:54:15 +02:00
b5d890eedd install Catch2 for docker_d2 and update Jenkinsfile 2022-04-27 13:43:49 +02:00
50b1b48678 link Catch2 issue 2022-04-27 13:36:26 +02:00
0e0dbc74aa Merge branch 'mueller/hotfix-etl' into mueller/bump-catch2 2022-04-27 09:45:42 +02:00
8c34051d8b bump Catch2 revision 2022-04-27 09:45:20 +02:00
b00d83cb1a bump ETL revision 2022-04-27 09:41:16 +02:00
17e609c3a5 some more var replacements 2022-04-27 09:37:11 +02:00
64f0166b64 hotfix for new ETL dependency 2022-04-27 09:16:52 +02:00
c80f06fbcb hotfix for ETL lib dep 2022-04-27 09:08:17 +02:00
e796f82203 Merge pull request 'gpio bug fix' (#602) from KSat/fsfw:hoffmann/gpioBugfix into development
Reviewed-on: fsfw/fsfw#602
2022-04-27 08:41:54 +02:00
5b7ca8c13c update CHANGELOG.md, apply afmt 2022-04-27 08:39:21 +02:00
031739ef51 Merge branch 'development' into hoffmann/gpioBugfix 2022-04-25 15:45:21 +02:00
b8516b15cb Merge pull request 'Added an additional conversion function' (#584) from eive/fsfw:mueller/clock-addition into development
Reviewed-on: fsfw/fsfw#584
2022-04-25 15:22:07 +02:00
ac5a54b5da Merge branch 'development' into mueller/clock-addition 2022-04-25 15:12:24 +02:00
29015b340b update changelog 2022-04-25 15:10:50 +02:00
64274acbeb Merge pull request 'Add ETL dependency' (#592) from KSat/fsfw:mueller/add-etl-dependency into development
Reviewed-on: fsfw/fsfw#592
2022-04-25 15:08:05 +02:00
ff98c42514 Merge branch 'development' into mueller/clock-addition 2022-04-25 14:54:22 +02:00
126ac52975 Merge pull request 'Allow passing a MqArgs struct to the MQ creation' (#583) from eive/fsfw:mueller/ipc-pass-arbitrary-args-to-mq into development
Reviewed-on: fsfw/fsfw#583
2022-04-25 14:43:52 +02:00
70d3197212 gpio init bug fix
Return values from configureGpios were not checked
2022-04-25 14:32:05 +02:00
dd90980520 push test 2022-04-25 14:19:03 +02:00
352ab43c1f Merge remote-tracking branch 'upstream/development' into mueller/add-etl-dependency 2022-04-12 17:11:41 +02:00
97e98eae24 Merge branch 'development' into mueller/ipc-pass-arbitrary-args-to-mq 2022-04-12 17:06:30 +02:00
5ac88f2b15 Merge pull request 'added missing empty implementation in STM32 SPI HAL' (#599) from mueller/small-stm32-hal-bugifx into development
Reviewed-on: fsfw/fsfw#599
2022-04-11 17:48:48 +02:00
b03a6684f9 Merge branch 'development' into mueller/small-stm32-hal-bugifx 2022-04-11 17:34:39 +02:00
7c2e50b665 added related PR in changelog 2022-04-11 17:32:01 +02:00
c04ca704d2 Merge pull request 'progagate reply returnvalue' (#597) from eive/fsfw:mueller/propagate-pool-manage-retval into development
Reviewed-on: fsfw/fsfw#597
2022-04-11 17:31:54 +02:00
6aa54fe1d4 added missing empty implementation 2022-04-11 17:30:27 +02:00
c55925959b Merge branch 'mueller/add-etl-dependency' of https://egit.irs.uni-stuttgart.de/KSat/fsfw into mueller/add-etl-dependency 2022-04-11 16:44:30 +02:00
4f0669c574 doc update 2022-04-11 16:44:20 +02:00
f0d996ffd2 Merge branch 'development' into mueller/add-etl-dependency 2022-04-11 16:17:46 +02:00
f4d05c2c9c Merge branch 'mueller/ipc-pass-arbitrary-args-to-mq' of https://egit.irs.uni-stuttgart.de/eive/fsfw into mueller/ipc-pass-arbitrary-args-to-mq 2022-04-11 16:13:55 +02:00
d1151ca707 changelog update 2022-04-11 16:13:47 +02:00
82f46992f6 Merge branch 'development' into mueller/ipc-pass-arbitrary-args-to-mq 2022-04-11 16:11:57 +02:00
c0f80680ef Merge branch 'mueller/propagate-pool-manage-retval' of https://egit.irs.uni-stuttgart.de/eive/fsfw into mueller/propagate-pool-manage-retval 2022-04-11 14:35:28 +02:00
7761b66fe2 delete data from ipc store if reply fails 2022-04-11 14:35:16 +02:00
acc4c8d975 check serialize result as well 2022-04-11 14:33:28 +02:00
fe739aa81a Merge branch 'development' into mueller/propagate-pool-manage-retval 2022-04-11 14:26:34 +02:00
afe006e234 Merge pull request 'Alternative reply ID activation' (#595) from meier/alternativeReply into development
Reviewed-on: fsfw/fsfw#595
2022-04-11 14:18:52 +02:00
17771c0497 progagate reply returnvalue 2022-04-11 13:57:18 +02:00
c05184e1c4 Merge branch 'development' into meier/alternativeReply 2022-04-04 14:25:08 +02:00
b2252bdc0b Merge remote-tracking branch 'upstream/development' into mueller/add-etl-dependency 2022-04-04 14:18:30 +02:00
6c1db8473b get alternative reply from device command info 2022-03-31 14:36:45 +02:00
1a530633ca small fix 2022-03-28 21:10:51 +02:00
8037e8074b more docs 2022-03-28 21:03:18 +02:00
d07e0e5576 trying something 2022-03-28 21:01:26 +02:00
5525466b52 update changelog 2022-03-28 20:57:30 +02:00
c2a89bf709 bugfix 2022-03-28 20:57:13 +02:00
8dd0b2608d cache version variables 2022-03-28 20:55:34 +02:00
05495077ec doc update 2022-03-28 20:53:39 +02:00
8ff9eadf30 update changelog, add basic instructions for etl 2022-03-28 20:43:36 +02:00
082c86ea18 link ETL lib as well 2022-03-28 20:18:49 +02:00
2800d6f28c add ETL dependency 2022-03-28 20:16:11 +02:00
b4effe7a46 Clang format 2022-03-28 18:33:24 +02:00
e6e71436c2 Added more tests 2022-03-28 18:32:51 +02:00
a887f852c8 Merge branch 'development' into mueller/clock-addition 2022-03-28 15:45:58 +02:00
0b3255e463 Fixed tests 2022-03-28 15:17:59 +02:00
631a531212 Merge branch 'development' into mueller/clock-addition 2022-03-28 14:51:23 +02:00
665d8cd479 Applied clang format 2022-03-25 18:48:53 +01:00
10398855a9 Added more unittest coverage
Added Mutex for gmtime functions
Moved Statics used in ClockCommon to ClockCommon
2022-03-25 18:47:31 +01:00
d0fec93dc3 argument order inversion 2022-03-25 13:42:49 +01:00
59ab54b2fb call corrections 2022-03-25 13:41:37 +01:00
7095999bd2 remove CCSDSTime function 2022-03-25 13:34:35 +01:00
7ffb4107d2 added missing docs 2022-03-25 13:34:08 +01:00
9ce59d3c75 added an additional conversion function
- timeval to TimeOfDay_t
2022-03-22 17:54:09 +01:00
39 changed files with 603 additions and 121 deletions

View File

@ -24,6 +24,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `oneShotAction` flag in the `TestTask` class is not static anymore - `oneShotAction` flag in the `TestTask` class is not static anymore
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations - HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
- 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
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583
- Clock:
- `timeval` to `TimeOfDay_t`
- Added Mutex for gmtime calls: (compare http://www.opengate.at/blog/2020/01/timeless/)
- Moved the statics used by Clock in ClockCommon.cpp to this file
- Better check for leap seconds
- Added Unittests for Clock (only getter)
## Removed ## Removed
@ -37,6 +47,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information - Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
inside `fsfw/version.h` inside `fsfw/version.h`
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
- Added ETL dependency and improved library dependency management
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592
## Fixed
- Small bugfix in STM32 HAL for SPI
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/599
- HAL GPIO: Improved error checking in `LinuxLibgpioIF::configureGpios(...)`. If a GPIO
configuration fails, the function will exit prematurely with a dedicated error code
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/602
# [v4.0.0] # [v4.0.0]

View File

@ -7,6 +7,23 @@ set(FSFW_REVISION 0)
# Add the cmake folder so the FindSphinx module is found # Add the cmake folder so the FindSphinx module is found
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
set(FSFW_ETL_LIB_MAJOR_VERSION 20 CACHE STRING
"ETL library major version requirement"
)
set(FSFW_ETL_LIB_VERSION ${FSFW_ETL_LIB_MAJOR_VERSION}.27.3 CACHE STRING
"ETL library exact version requirement"
)
set(FSFW_ETL_LINK_TARGET etl::etl)
set(FSFW_CATCH2_LIB_MAJOR_VERSION 3 CACHE STRING
"Catch2 library major version requirement"
)
set(FSFW_CATCH2_LIB_VERSION v${FSFW_CATCH2_LIB_MAJOR_VERSION}.0.0-preview5 CACHE STRING
"Catch2 library exact version requirement"
)
set(FSFW_ETL_LIB_NAME etl)
option(FSFW_GENERATE_SECTIONS option(FSFW_GENERATE_SECTIONS
"Generate function and data sections. Required to remove unused code" ON "Generate function and data sections. Required to remove unused code" ON
) )
@ -48,7 +65,7 @@ add_library(${LIB_FSFW_NAME})
if(FSFW_BUILD_UNITTESTS) if(FSFW_BUILD_UNITTESTS)
message(STATUS "Building the FSFW unittests in addition to the static library") message(STATUS "Building the FSFW unittests in addition to the static library")
# Check whether the user has already installed Catch2 first # Check whether the user has already installed Catch2 first
find_package(Catch2 3 QUIET) find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION})
# Not installed, so use FetchContent to download and provide Catch2 # Not installed, so use FetchContent to download and provide Catch2
if(NOT Catch2_FOUND) if(NOT Catch2_FOUND)
message(STATUS "Catch2 installation not found. Downloading Catch2 library with FetchContent") message(STATUS "Catch2 installation not found. Downloading Catch2 library with FetchContent")
@ -57,11 +74,12 @@ if(FSFW_BUILD_UNITTESTS)
FetchContent_Declare( FetchContent_Declare(
Catch2 Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v3.0.0-preview4 GIT_TAG ${FSFW_CATCH2_LIB_VERSION}
) )
FetchContent_MakeAvailable(Catch2) FetchContent_MakeAvailable(Catch2)
#fixes regression -preview4, to be confirmed in later releases # fixes regression -preview4, to be confirmed in later releases
# Related GitHub issue: https://github.com/catchorg/Catch2/issues/2417
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "") set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
endif() endif()
@ -89,6 +107,28 @@ if(FSFW_BUILD_UNITTESTS)
endif() endif()
endif() endif()
message(STATUS "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)
# Not installed, so use FetchContent to download and provide etl
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
message(STATUS
"No ETL installation was found with find_package. Installing and providing "
"etl with FindPackage"
)
include(FetchContent)
FetchContent_Declare(
${FSFW_ETL_LIB_NAME}
GIT_REPOSITORY https://github.com/ETLCPP/etl
GIT_TAG ${FSFW_ETL_LIB_VERSION}
)
FetchContent_MakeAvailable(${FSFW_ETL_LIB_NAME})
add_library(${FSFW_ETL_LINK_TARGET} ALIAS ${FSFW_ETL_LIB_NAME})
endif()
set(FSFW_CORE_INC_PATH "inc") set(FSFW_CORE_INC_PATH "inc")
set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux rtems freertos) set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux rtems freertos)
@ -350,6 +390,7 @@ target_compile_options(${LIB_FSFW_NAME} PRIVATE
) )
target_link_libraries(${LIB_FSFW_NAME} PRIVATE target_link_libraries(${LIB_FSFW_NAME} PRIVATE
${FSFW_ETL_LINK_TARGET}
${FSFW_ADDITIONAL_LINK_LIBS} ${FSFW_ADDITIONAL_LINK_LIBS}
) )

View File

@ -11,9 +11,15 @@ with Airbus Defence and Space GmbH.
## Quick facts ## Quick facts
The framework is designed for systems, which communicate with external devices, perform control loops, receive telecommands and send telemetry, and need to maintain a high level of availability. Therefore, a mode and health system provides control over the states of the software and the controlled devices. In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well. The framework is designed for systems, which communicate with external devices, perform control loops,
receive telecommands and send telemetry, and need to maintain a high level of availability. Therefore,
a mode and health system provides control over the states of the software and the controlled devices.
In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well.
The FSFW provides abstraction layers for operating systems to provide a uniform operating system abstraction layer (OSAL). Some components of this OSAL are required internally by the FSFW but is also very useful for developers to implement the same application logic on different operating systems with a uniform interface. The FSFW provides abstraction layers for operating systems to provide a uniform operating system
abstraction layer (OSAL). Some components of this OSAL are required internally by the FSFW but is
also very useful for developers to implement the same application logic on different operating
systems with a uniform interface.
Currently, the FSFW provides the following OSALs: Currently, the FSFW provides the following OSALs:
@ -45,6 +51,28 @@ A template configuration folder was provided and can be copied into the project
a starting point. The [configuration section](docs/README-config.md#top) provides more specific a starting point. The [configuration section](docs/README-config.md#top) provides more specific
information about the possible options. information about the possible options.
## Prerequisites
The Embedded Template Library (etl) is a dependency of the FSFW which is automatically
installed and provided by the build system unless the correction version was installed.
The current recommended version can be found inside the fsfw `CMakeLists.txt` file or by using
`ccmake` and looking up the `FSFW_ETL_LIB_MAJOR_VERSION` variable.
You can install the ETL library like this. On Linux, it might be necessary to add `sudo` before
the install call:
```cpp
git clone https://github.com/ETLCPP/etl
cd etl
git checkout <currentRecommendedVersion>
mkdir build && cd build
cmake ..
cmake --install .
```
It is recommended to install `20.27.2` or newer for the package version handling of
ETL to work.
## Adding the library ## Adding the library
The following steps show how to add and use FSFW components. It is still recommended to The following steps show how to add and use FSFW components. It is still recommended to
@ -83,6 +111,19 @@ The FSFW also has unittests which use the [Catch2 library](https://github.com/ca
These are built by setting the CMake option `FSFW_BUILD_UNITTESTS` to `ON` or `TRUE` 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. from your project `CMakeLists.txt` file or from the command line.
You can install the Catch2 library, which prevents the build system to avoid re-downloading
the dependency if the unit tests are completely rebuilt. The current recommended version
can be found inside the fsfw `CMakeLists.txt` file or by using `ccmake` and looking up
the `FSFW_CATCH2_LIB_VERSION` variable.
```sh
git clone https://github.com/catchorg/Catch2.git
cd Catch2
git checkout <currentRecommendedVersion>
cmake -Bbuild -H. -DBUILD_TESTING=OFF
sudo cmake --build build/ --target install
```
The fsfw-tests binary will be built as part of the static library and dropped alongside it. 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 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`. default. This can be disabled by setting the `FSFW_TESTS_COV_GEN` option to `OFF` or `FALSE`.

View File

@ -6,3 +6,9 @@ RUN apt-get --yes upgrade
#tzdata is a dependency, won't install otherwise #tzdata is a dependency, won't install otherwise
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping
RUN git clone https://github.com/catchorg/Catch2.git && \
cd Catch2 && \
git checkout v3.0.0-preview5 && \
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
cmake --build build/ --target install

View File

@ -3,7 +3,7 @@ pipeline {
BUILDDIR = 'build-tests' BUILDDIR = 'build-tests'
} }
agent { agent {
docker { image 'fsfw-ci:d1'} docker { image 'fsfw-ci:d2'}
} }
stages { stages {
stage('Clean') { stage('Clean') {

View File

@ -19,6 +19,29 @@ A template configuration folder was provided and can be copied into the project
a starting point. The [configuration section](docs/README-config.md#top) provides more specific a starting point. The [configuration section](docs/README-config.md#top) provides more specific
information about the possible options. information about the possible options.
Prerequisites
-------------------
The Embedded Template Library (etl) is a dependency of the FSFW which is automatically
installed and provided by the build system unless the correction version was installed.
The current recommended version can be found inside the fsfw ``CMakeLists.txt`` file or by using
``ccmake`` and looking up the ``FSFW_ETL_LIB_MAJOR_VERSION`` variable.
You can install the ETL library like this. On Linux, it might be necessary to add ``sudo`` before
the install call:
.. code-block:: console
git clone https://github.com/ETLCPP/etl
cd etl
git checkout <currentRecommendedVersion>
mkdir build && cd build
cmake ..
cmake --install .
It is recommended to install ``20.27.2`` or newer for the package version handling of
ETL to work.
Adding the library Adding the library
------------------- -------------------
@ -60,6 +83,20 @@ The FSFW also has unittests which use the `Catch2 library`_.
These are built by setting the CMake option ``FSFW_BUILD_UNITTESTS`` to ``ON`` or `TRUE` 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. from your project `CMakeLists.txt` file or from the command line.
You can install the Catch2 library, which prevents the build system to avoid re-downloading
the dependency if the unit tests are completely rebuilt. The current recommended version
can be found inside the fsfw ``CMakeLists.txt`` file or by using ``ccmake`` and looking up
the ``FSFW_CATCH2_LIB_VERSION`` variable.
.. code-block:: console
git clone https://github.com/catchorg/Catch2.git
cd Catch2
git checkout <currentRecommendedVersion>
cmake -Bbuild -H. -DBUILD_TESTING=OFF
sudo cmake --build build/ --target install
The fsfw-tests binary will be built as part of the static library and dropped alongside it. 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 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`. default. This can be disabled by setting the `FSFW_TESTS_COV_GEN` option to `OFF` or `FALSE`.

View File

@ -1,9 +1,9 @@
#include "MgmLIS3MDLHandler.h" #include "MgmLIS3MDLHandler.h"
#include "fsfw/datapool/PoolReadGuard.h"
#include <cmath> #include <cmath>
#include "fsfw/datapool/PoolReadGuard.h"
MgmLIS3MDLHandler::MgmLIS3MDLHandler(object_id_t objectId, object_id_t deviceCommunication, MgmLIS3MDLHandler::MgmLIS3MDLHandler(object_id_t objectId, object_id_t deviceCommunication,
CookieIF *comCookie, uint32_t transitionDelay) CookieIF *comCookie, uint32_t transitionDelay)
: DeviceHandlerBase(objectId, deviceCommunication, comCookie), : DeviceHandlerBase(objectId, deviceCommunication, comCookie),

View File

@ -44,6 +44,7 @@ ReturnValue_t LinuxLibgpioIF::addGpios(GpioCookie* gpioCookie) {
} }
ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) { ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
ReturnValue_t result = RETURN_OK;
for (auto& gpioConfig : mapToAdd) { for (auto& gpioConfig : mapToAdd) {
auto& gpioType = gpioConfig.second->gpioType; auto& gpioType = gpioConfig.second->gpioType;
switch (gpioType) { switch (gpioType) {
@ -55,7 +56,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
if (regularGpio == nullptr) { if (regularGpio == nullptr) {
return GPIO_INVALID_INSTANCE; return GPIO_INVALID_INSTANCE;
} }
configureGpioByChip(gpioConfig.first, *regularGpio); result = configureGpioByChip(gpioConfig.first, *regularGpio);
break; break;
} }
case (gpio::GpioTypes::GPIO_REGULAR_BY_LABEL): { case (gpio::GpioTypes::GPIO_REGULAR_BY_LABEL): {
@ -63,7 +64,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
if (regularGpio == nullptr) { if (regularGpio == nullptr) {
return GPIO_INVALID_INSTANCE; return GPIO_INVALID_INSTANCE;
} }
configureGpioByLabel(gpioConfig.first, *regularGpio); result = configureGpioByLabel(gpioConfig.first, *regularGpio);
break; break;
} }
case (gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME): { case (gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME): {
@ -71,7 +72,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
if (regularGpio == nullptr) { if (regularGpio == nullptr) {
return GPIO_INVALID_INSTANCE; return GPIO_INVALID_INSTANCE;
} }
configureGpioByLineName(gpioConfig.first, *regularGpio); result = configureGpioByLineName(gpioConfig.first, *regularGpio);
break; break;
} }
case (gpio::GpioTypes::CALLBACK): { case (gpio::GpioTypes::CALLBACK): {
@ -83,8 +84,11 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
gpioCallback->initValue, gpioCallback->callbackArgs); gpioCallback->initValue, gpioCallback->callbackArgs);
} }
} }
if (result != RETURN_OK) {
return GPIO_INIT_FAILED;
} }
return RETURN_OK; }
return result;
} }
ReturnValue_t LinuxLibgpioIF::configureGpioByLabel(gpioId_t gpioId, ReturnValue_t LinuxLibgpioIF::configureGpioByLabel(gpioId_t gpioId,

View File

@ -29,6 +29,8 @@ class LinuxLibgpioIF : public GpioIF, public SystemObject {
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 4); HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 4);
static constexpr ReturnValue_t GPIO_DUPLICATE_DETECTED = static constexpr ReturnValue_t GPIO_DUPLICATE_DETECTED =
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 5); HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 5);
static constexpr ReturnValue_t GPIO_INIT_FAILED =
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 6);
LinuxLibgpioIF(object_id_t objectId); LinuxLibgpioIF(object_id_t objectId);
virtual ~LinuxLibgpioIF(); virtual ~LinuxLibgpioIF();

View File

@ -24,9 +24,7 @@ void UartCookie::setParityEven() { parity = Parity::EVEN; }
Parity UartCookie::getParity() const { return parity; } Parity UartCookie::getParity() const { return parity; }
void UartCookie::setBitsPerWord(BitsPerWord bitsPerWord_) { void UartCookie::setBitsPerWord(BitsPerWord bitsPerWord_) { bitsPerWord = bitsPerWord_; }
bitsPerWord = bitsPerWord_;
}
BitsPerWord UartCookie::getBitsPerWord() const { return bitsPerWord; } BitsPerWord UartCookie::getBitsPerWord() const { return bitsPerWord; }

View File

@ -21,7 +21,7 @@ using mspCb = void (*)(void);
namespace spi { namespace spi {
struct MspCfgBase { struct MspCfgBase {
MspCfgBase(); MspCfgBase() {}
MspCfgBase(stm32h7::GpioCfg sck, stm32h7::GpioCfg mosi, stm32h7::GpioCfg miso, MspCfgBase(stm32h7::GpioCfg sck, stm32h7::GpioCfg mosi, stm32h7::GpioCfg miso,
mspCb cleanupCb = nullptr, mspCb setupCb = nullptr) mspCb cleanupCb = nullptr, mspCb setupCb = nullptr)
: sck(sck), mosi(mosi), miso(miso), cleanupCb(cleanupCb), setupCb(setupCb) {} : sck(sck), mosi(mosi), miso(miso), cleanupCb(cleanupCb), setupCb(setupCb) {}

View File

@ -787,6 +787,10 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool i
// Serialize set packet into store. // Serialize set packet into store.
size_t size = 0; size_t size = 0;
result = setPacket.serialize(&storePtr, &size, expectedSize, SerializeIF::Endianness::BIG); result = setPacket.serialize(&storePtr, &size, expectedSize, SerializeIF::Endianness::BIG);
if (result != HasReturnvaluesIF::RETURN_OK) {
ipcStore->deleteData(storeId);
return result;
}
if (expectedSize != size) { if (expectedSize != size) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateSetStructurePacket", printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateSetStructurePacket",
HasReturnvaluesIF::RETURN_FAILED, HasReturnvaluesIF::RETURN_FAILED,
@ -801,7 +805,10 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool i
HousekeepingMessage::setHkStuctureReportReply(&reply, sid, storeId); HousekeepingMessage::setHkStuctureReportReply(&reply, sid, storeId);
} }
hkQueue->reply(&reply); result = hkQueue->reply(&reply);
if (result != HasReturnvaluesIF::RETURN_OK) {
ipcStore->deleteData(storeId);
}
return result; return result;
} }

View File

@ -410,7 +410,7 @@ ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet, DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) { size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) {
// No need to check, as we may try to insert multiple times. // No need to check, as we may try to insert multiple times.
insertInCommandMap(deviceCommand); insertInCommandMap(deviceCommand, hasDifferentReplyId, replyId);
if (hasDifferentReplyId) { if (hasDifferentReplyId) {
return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic); return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic);
} else { } else {
@ -437,11 +437,15 @@ ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
} }
} }
ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand) { ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand,
bool useAlternativeReply,
DeviceCommandId_t alternativeReplyId) {
DeviceCommandInfo info; DeviceCommandInfo info;
info.expectedReplies = 0; info.expectedReplies = 0;
info.isExecuting = false; info.isExecuting = false;
info.sendReplyTo = NO_COMMANDER; info.sendReplyTo = NO_COMMANDER;
info.useAlternativeReplyId = alternativeReplyId;
info.alternativeReplyId = alternativeReplyId;
auto resultPair = deviceCommandMap.emplace(deviceCommand, info); auto resultPair = deviceCommandMap.emplace(deviceCommand, info);
if (resultPair.second) { if (resultPair.second) {
return RETURN_OK; return RETURN_OK;
@ -451,12 +455,20 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceComm
} }
size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) { size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) {
DeviceReplyIter iter = deviceReplyMap.find(commandId); DeviceCommandId_t replyId = NO_COMMAND_ID;
if (iter != deviceReplyMap.end()) { DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
return iter->second.replyLen; if (command->second.useAlternativeReplyId) {
replyId = command->second.alternativeReplyId;
} else { } else {
return 0; replyId = commandId;
} }
DeviceReplyIter iter = deviceReplyMap.find(replyId);
if (iter != deviceReplyMap.end()) {
if (iter->second.delayCycles != 0) {
return iter->second.replyLen;
}
}
return 0;
} }
ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply, ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply,
@ -651,7 +663,9 @@ void DeviceHandlerBase::doGetWrite() {
// We need to distinguish here, because a raw command never expects a reply. // We need to distinguish here, because a raw command never expects a reply.
//(Could be done in eRIRM, but then child implementations need to be careful. //(Could be done in eRIRM, but then child implementations need to be careful.
result = enableReplyInReplyMap(cookieInfo.pendingCommand); DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
result = enableReplyInReplyMap(command, 1, command->second.useAlternativeReplyId,
command->second.alternativeReplyId);
} else { } else {
// always generate a failure event, so that FDIR knows what's up // always generate a failure event, so that FDIR knows what's up
triggerEvent(DEVICE_SENDING_COMMAND_FAILED, result, cookieInfo.pendingCommand->first); triggerEvent(DEVICE_SENDING_COMMAND_FAILED, result, cookieInfo.pendingCommand->first);

View File

@ -478,7 +478,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* @return - @c RETURN_OK when the command was successfully inserted, * @return - @c RETURN_OK when the command was successfully inserted,
* - @c RETURN_FAILED else. * - @c RETURN_FAILED else.
*/ */
ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand); ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand,
bool useAlternativeReply = false,
DeviceCommandId_t alternativeReplyId = 0);
/** /**
* Enables a periodic reply for a given command. It sets to delay cycles to the specified * Enables a periodic reply for a given command. It sets to delay cycles to the specified
@ -751,6 +753,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
//! if this is != NO_COMMANDER, DHB was commanded externally and shall //! if this is != NO_COMMANDER, DHB was commanded externally and shall
//! report everything to commander. //! report everything to commander.
MessageQueueId_t sendReplyTo; MessageQueueId_t sendReplyTo;
bool useAlternativeReplyId;
DeviceCommandId_t alternativeReplyId;
}; };
using DeviceCommandMap = std::map<DeviceCommandId_t, DeviceCommandInfo>; using DeviceCommandMap = std::map<DeviceCommandId_t, DeviceCommandInfo>;
/** /**

View File

@ -1,9 +1,9 @@
#include "MessageQueueBase.h" #include "MessageQueueBase.h"
MessageQueueBase::MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MessageQueueBase::MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* args)
MqArgs* args): id(id) { : id(id) {
this->defaultDest = defaultDest; this->defaultDest = defaultDest;
if(args != nullptr) { if (args != nullptr) {
this->args = *args; this->args = *args;
} }
} }
@ -29,29 +29,19 @@ ReturnValue_t MessageQueueBase::receiveMessage(MessageQueueMessageIF* message,
return status; return status;
} }
MessageQueueId_t MessageQueueBase::getLastPartner() const { MessageQueueId_t MessageQueueBase::getLastPartner() const { return last; }
return last;
}
MessageQueueId_t MessageQueueBase::getId() const { MessageQueueId_t MessageQueueBase::getId() const { return id; }
return id;
}
MqArgs& MessageQueueBase::getMqArgs() { MqArgs& MessageQueueBase::getMqArgs() { return args; }
return args;
}
void MessageQueueBase::setDefaultDestination(MessageQueueId_t defaultDestination) { void MessageQueueBase::setDefaultDestination(MessageQueueId_t defaultDestination) {
this->defaultDest = defaultDestination; this->defaultDest = defaultDestination;
} }
MessageQueueId_t MessageQueueBase::getDefaultDestination() const { MessageQueueId_t MessageQueueBase::getDefaultDestination() const { return defaultDest; }
return defaultDest;
}
bool MessageQueueBase::isDefaultDestinationSet() const { bool MessageQueueBase::isDefaultDestinationSet() const { return (defaultDest != NO_QUEUE); }
return (defaultDest != NO_QUEUE);
}
ReturnValue_t MessageQueueBase::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message, ReturnValue_t MessageQueueBase::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) { bool ignoreFault) {

View File

@ -1,11 +1,11 @@
#ifndef FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_ #ifndef FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
#define FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_ #define FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
#include <fsfw/ipc/definitions.h>
#include <fsfw/ipc/MessageQueueIF.h> #include <fsfw/ipc/MessageQueueIF.h>
#include <fsfw/ipc/definitions.h>
class MessageQueueBase: public MessageQueueIF { class MessageQueueBase : public MessageQueueIF {
public: public:
MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* mqArgs); MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* mqArgs);
virtual ~MessageQueueBase(); virtual ~MessageQueueBase();
@ -22,20 +22,19 @@ public:
virtual ReturnValue_t reply(MessageQueueMessageIF* message) override; virtual ReturnValue_t reply(MessageQueueMessageIF* message) override;
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message, virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) override; MessageQueueId_t* receivedFrom) override;
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
MessageQueueId_t sentFrom, bool ignoreFault = false) override; bool ignoreFault = false) override;
// OSAL specific, forward the abstract function // OSAL specific, forward the abstract function
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0; virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0;
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false) = 0; MessageQueueId_t sentFrom, bool ignoreFault = false) = 0;
protected:
protected:
MessageQueueId_t id = MessageQueueIF::NO_QUEUE; MessageQueueId_t id = MessageQueueIF::NO_QUEUE;
MessageQueueId_t last = MessageQueueIF::NO_QUEUE; MessageQueueId_t last = MessageQueueIF::NO_QUEUE;
MessageQueueId_t defaultDest = MessageQueueIF::NO_QUEUE; MessageQueueId_t defaultDest = MessageQueueIF::NO_QUEUE;
MqArgs args = {}; MqArgs args = {};
}; };
#endif /* FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_ */ #endif /* FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_ */

View File

@ -2,6 +2,7 @@
#define FSFW_IPC_MESSAGEQUEUEIF_H_ #define FSFW_IPC_MESSAGEQUEUEIF_H_
#include <fsfw/ipc/definitions.h> #include <fsfw/ipc/definitions.h>
#include <cstdint> #include <cstdint>
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
@ -45,7 +46,8 @@ class MessageQueueIF {
virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0; virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0;
/** /**
* @brief This function reads available messages from the message queue and returns the sender. * @brief This function reads available messages from the message queue and returns the
* sender.
* @details * @details
* It works identically to the other receiveMessage call, but in addition * It works identically to the other receiveMessage call, but in addition
* returns the sender's queue id. * returns the sender's queue id.

View File

@ -11,9 +11,6 @@
// TODO sanitize input? // TODO sanitize input?
// TODO much of this code can be reused for tick-only systems // TODO much of this code can be reused for tick-only systems
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = nullptr;
uint32_t Clock::getTicksPerSecond(void) { return 1000; } uint32_t Clock::getTicksPerSecond(void) { return 1000; }
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {

View File

@ -2,6 +2,7 @@
#define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_ #define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
#include <fsfw/ipc/MessageQueueBase.h> #include <fsfw/ipc/MessageQueueBase.h>
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "TaskManagement.h" #include "TaskManagement.h"
#include "fsfw/internalerror/InternalErrorReporterIF.h" #include "fsfw/internalerror/InternalErrorReporterIF.h"

View File

@ -2,6 +2,7 @@
#include <chrono> #include <chrono>
#include "fsfw/ipc/MutexGuard.h"
#include "fsfw/platform.h" #include "fsfw/platform.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
@ -11,9 +12,6 @@
#include <fstream> #include <fstream>
#endif #endif
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL;
using SystemClock = std::chrono::system_clock; using SystemClock = std::chrono::system_clock;
uint32_t Clock::getTicksPerSecond(void) { uint32_t Clock::getTicksPerSecond(void) {
@ -127,6 +125,13 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now); auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
auto fraction = now - seconds; auto fraction = now - seconds;
time_t tt = SystemClock::to_time_t(now); time_t tt = SystemClock::to_time_t(now);
ReturnValue_t result = checkOrCreateClockMutex();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
MutexGuard helper(timeMutex);
// gmtime writes its output in a global buffer which is not Thread Safe
// Therefore we have to use a Mutex here
struct tm* timeInfo; struct tm* timeInfo;
timeInfo = gmtime(&tt); timeInfo = gmtime(&tt);
time->year = timeInfo->tm_year + 1900; time->year = timeInfo->tm_year + 1900;

View File

@ -1,17 +1,17 @@
#ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ #ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
#define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ #define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
#include "fsfw/ipc/MessageQueueBase.h" #include <memory>
#include <queue>
#include "fsfw/internalerror/InternalErrorReporterIF.h" #include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueBase.h"
#include "fsfw/ipc/MessageQueueIF.h" #include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h" #include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/MutexIF.h" #include "fsfw/ipc/MutexIF.h"
#include "fsfw/ipc/definitions.h" #include "fsfw/ipc/definitions.h"
#include "fsfw/timemanager/Clock.h" #include "fsfw/timemanager/Clock.h"
#include <memory>
#include <queue>
/** /**
* @brief This class manages sending and receiving of * @brief This class manages sending and receiving of
* message queue messages. * message queue messages.

View File

@ -8,11 +8,9 @@
#include <fstream> #include <fstream>
#include "fsfw/ipc/MutexGuard.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL;
uint32_t Clock::getTicksPerSecond(void) { uint32_t Clock::getTicksPerSecond(void) {
uint32_t ticks = sysconf(_SC_CLK_TCK); uint32_t ticks = sysconf(_SC_CLK_TCK);
return ticks; return ticks;
@ -117,7 +115,13 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
// TODO errno // TODO errno
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
ReturnValue_t result = checkOrCreateClockMutex();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
MutexGuard helper(timeMutex);
// gmtime writes its output in a global buffer which is not Thread Safe
// Therefore we have to use a Mutex here
struct tm* timeInfo; struct tm* timeInfo;
timeInfo = gmtime(&timeUnix.tv_sec); timeInfo = gmtime(&timeUnix.tv_sec);
time->year = timeInfo->tm_year + 1900; time->year = timeInfo->tm_year + 1900;

View File

@ -61,8 +61,7 @@ class MessageQueue : public MessageQueueBase {
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override; ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
ReturnValue_t flush(uint32_t* count) override; ReturnValue_t flush(uint32_t* count) override;
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, MessageQueueId_t sentFrom, bool ignoreFault = false) override;
bool ignoreFault = false) override;
protected: protected:
/** /**

View File

@ -6,9 +6,6 @@
#include "fsfw/ipc/MutexGuard.h" #include "fsfw/ipc/MutexGuard.h"
#include "fsfw/osal/rtems/RtemsBasic.h" #include "fsfw/osal/rtems/RtemsBasic.h"
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = nullptr;
uint32_t Clock::getTicksPerSecond(void) { uint32_t Clock::getTicksPerSecond(void) {
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second(); rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
return static_cast<uint32_t>(ticks_per_second); return static_cast<uint32_t>(ticks_per_second);

View File

@ -2,6 +2,7 @@
#define FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_ #define FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
#include <fsfw/ipc/MessageQueueBase.h> #include <fsfw/ipc/MessageQueueBase.h>
#include "RtemsBasic.h" #include "RtemsBasic.h"
#include "fsfw/internalerror/InternalErrorReporterIF.h" #include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueIF.h" #include "fsfw/ipc/MessageQueueIF.h"

View File

@ -59,14 +59,13 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
*/ */
ReturnValue_t addComponent(object_id_t object) override; ReturnValue_t addComponent(object_id_t object) override;
/** /**
* Adds an object to the list of objects to be executed. * Adds an object to the list of objects to be executed.
* The objects are executed in the order added. * The objects are executed in the order added.
* @param object pointer to the object to add. * @param object pointer to the object to add.
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added. * @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
*/ */
ReturnValue_t addComponent(ExecutableObjectIF* object) override; ReturnValue_t addComponent(ExecutableObjectIF *object) override;
uint32_t getPeriodMs() const override; uint32_t getPeriodMs() const override;

View File

@ -91,7 +91,7 @@ ReturnValue_t CCSDSTime::convertFromCDS(Clock::TimeOfDay_t* to, const uint8_t* f
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
return convertTimevalToTimeOfDay(to, &time); return Clock::convertTimevalToTimeOfDay(&time, to);
} }
ReturnValue_t CCSDSTime::convertFromCCS(Clock::TimeOfDay_t* to, const uint8_t* from, ReturnValue_t CCSDSTime::convertFromCCS(Clock::TimeOfDay_t* to, const uint8_t* from,
@ -489,11 +489,6 @@ ReturnValue_t CCSDSTime::checkTimeOfDay(const Clock::TimeOfDay_t* time) {
return RETURN_OK; return RETURN_OK;
} }
ReturnValue_t CCSDSTime::convertTimevalToTimeOfDay(Clock::TimeOfDay_t* to, timeval* from) {
// This is rather tricky. Implement only if needed. Also, if so, move to OSAL.
return UNSUPPORTED_TIME_FORMAT;
}
ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from, size_t* foundLength, ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from, size_t* foundLength,
size_t maxLength) { size_t maxLength) {
uint8_t pField = *from; uint8_t pField = *from;
@ -583,7 +578,7 @@ ReturnValue_t CCSDSTime::convertFromCDS(Clock::TimeOfDay_t* to, const CCSDSTime:
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
return CCSDSTime::convertTimevalToTimeOfDay(to, &tempTimeval); return Clock::convertTimevalToTimeOfDay(&tempTimeval, to);
} }
ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField, const uint8_t* from, ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField, const uint8_t* from,

View File

@ -223,7 +223,6 @@ class CCSDSTime : public HasReturnvaluesIF {
uint8_t *day); uint8_t *day);
static bool isLeapYear(uint32_t year); static bool isLeapYear(uint32_t year);
static ReturnValue_t convertTimevalToTimeOfDay(Clock::TimeOfDay_t *to, timeval *from);
}; };
#endif /* FSFW_TIMEMANAGER_CCSDSTIME_H_ */ #endif /* FSFW_TIMEMANAGER_CCSDSTIME_H_ */

View File

@ -99,6 +99,13 @@ class Clock {
*/ */
static ReturnValue_t getDateAndTime(TimeOfDay_t *time); static ReturnValue_t getDateAndTime(TimeOfDay_t *time);
/**
* Convert to time of day struct given the POSIX timeval struct
* @param from
* @param to
* @return
*/
static ReturnValue_t convertTimevalToTimeOfDay(const timeval *from, TimeOfDay_t *to);
/** /**
* Converts a time of day struct to POSIX seconds. * Converts a time of day struct to POSIX seconds.
* @param time The time of day as input * @param time The time of day as input
@ -166,6 +173,7 @@ class Clock {
static MutexIF *timeMutex; static MutexIF *timeMutex;
static uint16_t leapSeconds; static uint16_t leapSeconds;
static bool leapSecondsSet;
}; };
#endif /* FSFW_TIMEMANAGER_CLOCK_H_ */ #endif /* FSFW_TIMEMANAGER_CLOCK_H_ */

View File

@ -1,7 +1,13 @@
#include <ctime>
#include "fsfw/ipc/MutexGuard.h" #include "fsfw/ipc/MutexGuard.h"
#include "fsfw/timemanager/Clock.h" #include "fsfw/timemanager/Clock.h"
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval *tt) { uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = nullptr;
bool Clock::leapSecondsSet = false;
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
uint16_t leapSeconds; uint16_t leapSeconds;
ReturnValue_t result = getLeapSeconds(&leapSeconds); ReturnValue_t result = getLeapSeconds(&leapSeconds);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
@ -27,12 +33,16 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
MutexGuard helper(timeMutex); MutexGuard helper(timeMutex);
leapSeconds = leapSeconds_; leapSeconds = leapSeconds_;
leapSecondsSet = true;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Clock::getLeapSeconds(uint16_t *leapSeconds_) { ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
if (timeMutex == nullptr) { if (not leapSecondsSet) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if (checkOrCreateClockMutex() != HasReturnvaluesIF::RETURN_OK) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
MutexGuard helper(timeMutex); MutexGuard helper(timeMutex);
@ -42,9 +52,32 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t *leapSeconds_) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* to) {
struct tm* timeInfo;
// According to https://en.cppreference.com/w/c/chrono/gmtime, the implementation of gmtime_s
// in the Windows CRT is incompatible with the C standard but this should not be an issue for
// this implementation
ReturnValue_t result = checkOrCreateClockMutex();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
MutexGuard helper(timeMutex);
// gmtime writes its output in a global buffer which is not Thread Safe
// Therefore we have to use a Mutex here
timeInfo = gmtime(&from->tv_sec);
to->year = timeInfo->tm_year + 1900;
to->month = timeInfo->tm_mon + 1;
to->day = timeInfo->tm_mday;
to->hour = timeInfo->tm_hour;
to->minute = timeInfo->tm_min;
to->second = timeInfo->tm_sec;
to->usecond = from->tv_usec;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::checkOrCreateClockMutex() { ReturnValue_t Clock::checkOrCreateClockMutex() {
if (timeMutex == nullptr) { if (timeMutex == nullptr) {
MutexFactory *mutexFactory = MutexFactory::instance(); MutexFactory* mutexFactory = MutexFactory::instance();
if (mutexFactory == nullptr) { if (mutexFactory == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }

View File

@ -1,8 +1,9 @@
#include "version.h" #include "version.h"
#include "fsfw/FSFWVersion.h"
#include <cstdio> #include <cstdio>
#include "fsfw/FSFWVersion.h"
#ifdef major #ifdef major
#undef major #undef major
#endif #endif

View File

@ -29,7 +29,7 @@ class Version {
} }
friend bool operator>(const Version& v1, const Version& v2) { friend bool operator>(const Version& v1, const Version& v2) {
return not (v1 < v2) and not (v1 == v2); return not(v1 < v2) and not(v1 == v2);
} }
friend bool operator<=(const Version& v1, const Version& v2) { return ((v1 == v2) or (v1 < v2)); } friend bool operator<=(const Version& v1, const Version& v2) { return ((v1 == v2) or (v1 < v2)); }

View File

@ -3,4 +3,5 @@ target_sources(${FSFW_TEST_TGT} PRIVATE
testOpDivider.cpp testOpDivider.cpp
testBitutil.cpp testBitutil.cpp
testCRC.cpp testCRC.cpp
testTimevalOperations.cpp
) )

View File

@ -0,0 +1,124 @@
#include <fsfw/globalfunctions/timevalOperations.h>
#include <catch2/catch_approx.hpp>
#include <catch2/catch_test_macros.hpp>
#include "fsfw_tests/unit/CatchDefinitions.h"
TEST_CASE("TimevalTest", "[timevalOperations]") {
SECTION("Comparison") {
timeval t1;
t1.tv_sec = 1648227422;
t1.tv_usec = 123456;
timeval t2;
t2.tv_sec = 1648227422;
t2.tv_usec = 123456;
REQUIRE(t1 == t2);
REQUIRE(t2 == t1);
REQUIRE_FALSE(t1 != t2);
REQUIRE_FALSE(t2 != t1);
REQUIRE(t1 <= t2);
REQUIRE(t2 <= t1);
REQUIRE(t1 >= t2);
REQUIRE(t2 >= t1);
REQUIRE_FALSE(t1 < t2);
REQUIRE_FALSE(t2 < t1);
REQUIRE_FALSE(t1 > t2);
REQUIRE_FALSE(t2 > t1);
timeval t3;
t3.tv_sec = 1648227422;
t3.tv_usec = 123457;
REQUIRE_FALSE(t1 == t3);
REQUIRE(t1 != t3);
REQUIRE(t1 <= t3);
REQUIRE_FALSE(t3 <= t1);
REQUIRE_FALSE(t1 >= t3);
REQUIRE(t3 >= t1);
REQUIRE(t1 < t3);
REQUIRE_FALSE(t3 < t1);
REQUIRE_FALSE(t1 > t3);
REQUIRE(t3 > t1);
timeval t4;
t4.tv_sec = 1648227423;
t4.tv_usec = 123456;
REQUIRE_FALSE(t1 == t4);
REQUIRE(t1 != t4);
REQUIRE(t1 <= t4);
REQUIRE_FALSE(t4 <= t1);
REQUIRE_FALSE(t1 >= t4);
REQUIRE(t4 >= t1);
REQUIRE(t1 < t4);
REQUIRE_FALSE(t4 < t1);
REQUIRE_FALSE(t1 > t4);
REQUIRE(t4 > t1);
}
SECTION("Operators") {
timeval t1;
t1.tv_sec = 1648227422;
t1.tv_usec = 123456;
timeval t2;
t2.tv_sec = 1648227422;
t2.tv_usec = 123456;
timeval t3 = t1 - t2;
REQUIRE(t3.tv_sec == 0);
REQUIRE(t3.tv_usec == 0);
timeval t4 = t1 - t3;
REQUIRE(t4.tv_sec == 1648227422);
REQUIRE(t4.tv_usec == 123456);
timeval t5 = t3 - t1;
REQUIRE(t5.tv_sec == -1648227422);
REQUIRE(t5.tv_usec == -123456);
timeval t6;
t6.tv_sec = 1648227400;
t6.tv_usec = 999999;
timeval t7 = t6 + t1;
REQUIRE(t7.tv_sec == (1648227422ull + 1648227400ull + 1ull));
REQUIRE(t7.tv_usec == 123455);
timeval t8 = t1 - t6;
REQUIRE(t8.tv_sec == 1648227422 - 1648227400 - 1);
REQUIRE(t8.tv_usec == 123457);
double scalar = 2;
timeval t9 = t1 * scalar;
REQUIRE(t9.tv_sec == 3296454844);
REQUIRE(t9.tv_usec == 246912);
timeval t10 = scalar * t1;
REQUIRE(t10.tv_sec == 3296454844);
REQUIRE(t10.tv_usec == 246912);
timeval t11 = t6 * scalar;
REQUIRE(t11.tv_sec == (3296454800 + 1));
REQUIRE(t11.tv_usec == 999998);
timeval t12 = t1 / scalar;
REQUIRE(t12.tv_sec == 824113711);
REQUIRE(t12.tv_usec == 61728);
timeval t13 = t6 / scalar;
REQUIRE(t13.tv_sec == 824113700);
// Rounding issue
REQUIRE(t13.tv_usec == 499999);
double scalar2 = t9 / t1;
REQUIRE(scalar2 == Catch::Approx(2.0));
double scalar3 = t1 / t6;
REQUIRE(scalar3 == Catch::Approx(1.000000013));
double scalar4 = t3 / t1;
REQUIRE(scalar4 == Catch::Approx(0));
double scalar5 = t12 / t1;
REQUIRE(scalar5 == Catch::Approx(0.5));
}
SECTION("timevalOperations::toTimeval") {
double seconds = 1648227422.123456;
timeval t1 = timevalOperations::toTimeval(seconds);
REQUIRE(t1.tv_sec == 1648227422);
// Allow 1 usec rounding tolerance
REQUIRE(t1.tv_usec >= 123455);
REQUIRE(t1.tv_usec <= 123457);
}
}

View File

@ -4,8 +4,8 @@
#include <cstring> #include <cstring>
#include <queue> #include <queue>
#include "fsfw/ipc/MessageQueueBase.h"
#include "fsfw/ipc/CommandMessage.h" #include "fsfw/ipc/CommandMessage.h"
#include "fsfw/ipc/MessageQueueBase.h"
#include "fsfw/ipc/MessageQueueIF.h" #include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h" #include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw_tests/unit/CatchDefinitions.h" #include "fsfw_tests/unit/CatchDefinitions.h"

View File

@ -1,4 +1,5 @@
target_sources(${FSFW_TEST_TGT} PRIVATE target_sources(${FSFW_TEST_TGT} PRIVATE
TestMessageQueue.cpp TestMessageQueue.cpp
TestSemaphore.cpp TestSemaphore.cpp
TestClock.cpp
) )

View File

@ -0,0 +1,86 @@
#include <fsfw/globalfunctions/timevalOperations.h>
#include <fsfw/timemanager/Clock.h>
#include <array>
#include <catch2/catch_approx.hpp>
#include <catch2/catch_test_macros.hpp>
#include "fsfw_tests/unit/CatchDefinitions.h"
TEST_CASE("OSAL::Clock Test", "[OSAL::Clock Test]") {
SECTION("Test getClock") {
timeval time;
ReturnValue_t result = Clock::getClock_timeval(&time);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
Clock::TimeOfDay_t timeOfDay;
result = Clock::getDateAndTime(&timeOfDay);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
timeval timeOfDayAsTimeval;
result = Clock::convertTimeOfDayToTimeval(&timeOfDay, &timeOfDayAsTimeval);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
// We require timeOfDayAsTimeval to be larger than time as it
// was request a few ns later
double difference = timevalOperations::toDouble(timeOfDayAsTimeval - time);
CHECK(difference >= 0.0);
CHECK(difference <= 0.005);
// Conversion in the other direction
Clock::TimeOfDay_t timevalAsTimeOfDay;
result = Clock::convertTimevalToTimeOfDay(&time, &timevalAsTimeOfDay);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
CHECK(timevalAsTimeOfDay.year <= timeOfDay.year);
// TODO We should write TimeOfDay operators!
}
SECTION("Leap seconds") {
uint16_t leapSeconds = 0;
ReturnValue_t result = Clock::getLeapSeconds(&leapSeconds);
REQUIRE(result == HasReturnvaluesIF::RETURN_FAILED);
REQUIRE(leapSeconds == 0);
result = Clock::setLeapSeconds(18);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
result = Clock::getLeapSeconds(&leapSeconds);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
REQUIRE(leapSeconds == 18);
}
SECTION("usec Test") {
timeval timeAsTimeval;
ReturnValue_t result = Clock::getClock_timeval(&timeAsTimeval);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
uint64_t timeAsUsec = 0;
result = Clock::getClock_usecs(&timeAsUsec);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
double timeAsUsecDouble = static_cast<double>(timeAsUsec) / 1000000.0;
timeval timeAsUsecTimeval = timevalOperations::toTimeval(timeAsUsecDouble);
double difference = timevalOperations::toDouble(timeAsUsecTimeval - timeAsTimeval);
// We accept 5 ms difference
CHECK(difference >= 0.0);
CHECK(difference <= 0.005);
uint64_t timevalAsUint64 = static_cast<uint64_t>(timeAsTimeval.tv_sec) * 1000000ull +
static_cast<uint64_t>(timeAsTimeval.tv_usec);
CHECK((timeAsUsec - timevalAsUint64) >= 0);
CHECK((timeAsUsec - timevalAsUint64) <= (5 * 1000));
}
SECTION("Test j2000") {
double j2000;
timeval time;
time.tv_sec = 1648208539;
time.tv_usec = 0;
ReturnValue_t result = Clock::convertTimevalToJD2000(time, &j2000);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
double correctJ2000 = 2459663.98772 - 2451545.0;
CHECK(j2000 == Catch::Approx(correctJ2000).margin(1.2 * 1e-8));
}
SECTION("Convert to TT") {
timeval utcTime;
utcTime.tv_sec = 1648208539;
utcTime.tv_usec = 999000;
timeval tt;
ReturnValue_t result = Clock::setLeapSeconds(27);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
result = Clock::convertUTCToTT(utcTime, &tt);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
CHECK(tt.tv_usec == 183000);
// The plus 1 is a own forced overflow of usecs
CHECK(tt.tv_sec == (1648208539 + 27 + 10 + 32 + 1));
}
}

View File

@ -81,7 +81,8 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") {
std::string timeAscii = "2022-12-31T23:59:59.123Z"; std::string timeAscii = "2022-12-31T23:59:59.123Z";
Clock::TimeOfDay_t timeTo; Clock::TimeOfDay_t timeTo;
const uint8_t* timeChar = reinterpret_cast<const uint8_t*>(timeAscii.c_str()); const uint8_t* timeChar = reinterpret_cast<const uint8_t*>(timeAscii.c_str());
CCSDSTime::convertFromASCII(&timeTo, timeChar, timeAscii.length()); auto result = CCSDSTime::convertFromASCII(&timeTo, timeChar, timeAscii.length());
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
REQUIRE(timeTo.year == 2022); REQUIRE(timeTo.year == 2022);
REQUIRE(timeTo.month == 12); REQUIRE(timeTo.month == 12);
REQUIRE(timeTo.day == 31); REQUIRE(timeTo.day == 31);
@ -89,6 +90,19 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") {
REQUIRE(timeTo.minute == 59); REQUIRE(timeTo.minute == 59);
REQUIRE(timeTo.second == 59); REQUIRE(timeTo.second == 59);
REQUIRE(timeTo.usecond == Catch::Approx(123000)); REQUIRE(timeTo.usecond == Catch::Approx(123000));
std::string timeAscii2 = "2022-365T23:59:59.123Z";
const uint8_t* timeChar2 = reinterpret_cast<const uint8_t*>(timeAscii2.c_str());
Clock::TimeOfDay_t timeTo2;
result = CCSDSTime::convertFromCcsds(&timeTo2, timeChar2, timeAscii2.length());
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
REQUIRE(timeTo2.year == 2022);
REQUIRE(timeTo2.month == 12);
REQUIRE(timeTo2.day == 31);
REQUIRE(timeTo2.hour == 23);
REQUIRE(timeTo2.minute == 59);
REQUIRE(timeTo2.second == 59);
REQUIRE(timeTo2.usecond == Catch::Approx(123000));
} }
SECTION("CDS Conversions") { SECTION("CDS Conversions") {
@ -119,6 +133,7 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") {
CHECK(cdsTime.msDay_h == 0xE0); CHECK(cdsTime.msDay_h == 0xE0);
CHECK(cdsTime.msDay_l == 0xC5); CHECK(cdsTime.msDay_l == 0xC5);
CHECK(cdsTime.msDay_ll == 0xC3); CHECK(cdsTime.msDay_ll == 0xC3);
CHECK(cdsTime.pField == CCSDSTime::P_FIELD_CDS_SHORT);
// Conversion back to timeval // Conversion back to timeval
timeval timeReturnAsTimeval; timeval timeReturnAsTimeval;
@ -128,5 +143,56 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") {
timeval difference = timeAsTimeval - timeReturnAsTimeval; timeval difference = timeAsTimeval - timeReturnAsTimeval;
CHECK(difference.tv_usec == 456); CHECK(difference.tv_usec == 456);
CHECK(difference.tv_sec == 0); CHECK(difference.tv_sec == 0);
Clock::TimeOfDay_t timeReturnAsTimeOfDay;
result = CCSDSTime::convertFromCDS(&timeReturnAsTimeOfDay, &cdsTime);
CHECK(result == HasReturnvaluesIF::RETURN_OK);
CHECK(timeReturnAsTimeOfDay.year == 2020);
CHECK(timeReturnAsTimeOfDay.month == 2);
CHECK(timeReturnAsTimeOfDay.day == 29);
CHECK(timeReturnAsTimeOfDay.hour == 13);
CHECK(timeReturnAsTimeOfDay.minute == 24);
CHECK(timeReturnAsTimeOfDay.second == 45);
// micro seconds precision is lost
CHECK(timeReturnAsTimeOfDay.usecond == 123000);
Clock::TimeOfDay_t timeReturnAsTodFromBuffer;
const uint8_t* buffer = reinterpret_cast<const uint8_t*>(&cdsTime);
result = CCSDSTime::convertFromCDS(&timeReturnAsTodFromBuffer, buffer, sizeof(cdsTime));
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
CHECK(timeReturnAsTodFromBuffer.year == time.year);
CHECK(timeReturnAsTodFromBuffer.month == time.month);
CHECK(timeReturnAsTodFromBuffer.day == time.day);
CHECK(timeReturnAsTodFromBuffer.hour == time.hour);
CHECK(timeReturnAsTodFromBuffer.minute == time.minute);
CHECK(timeReturnAsTodFromBuffer.second == time.second);
CHECK(timeReturnAsTodFromBuffer.usecond == 123000);
Clock::TimeOfDay_t todFromCCSDS;
result = CCSDSTime::convertFromCcsds(&todFromCCSDS, buffer, sizeof(cdsTime));
CHECK(result == HasReturnvaluesIF::RETURN_OK);
CHECK(todFromCCSDS.year == time.year);
CHECK(todFromCCSDS.month == time.month);
CHECK(todFromCCSDS.day == time.day);
CHECK(todFromCCSDS.hour == time.hour);
CHECK(todFromCCSDS.minute == time.minute);
CHECK(todFromCCSDS.second == time.second);
CHECK(todFromCCSDS.usecond == 123000);
}
SECTION("CCSDS Failures") {
Clock::TimeOfDay_t time;
time.year = 2020;
time.month = 12;
time.day = 32;
time.hour = 13;
time.minute = 24;
time.second = 45;
time.usecond = 123456;
CCSDSTime::Ccs_mseconds to;
auto result = CCSDSTime::convertToCcsds(&to, &time);
REQUIRE(result == CCSDSTime::INVALID_TIME_FORMAT);
CCSDSTime::Ccs_seconds to2;
result = CCSDSTime::convertToCcsds(&to2, &time);
REQUIRE(result == CCSDSTime::INVALID_TIME_FORMAT);
} }
} }

View File

@ -17,15 +17,15 @@ TEST_CASE("Version API Tests", "[TestVersionAPI]") {
fsfw::Version v1 = fsfw::Version(1, 1, 1); fsfw::Version v1 = fsfw::Version(1, 1, 1);
fsfw::Version v2 = fsfw::Version(1, 1, 1); fsfw::Version v2 = fsfw::Version(1, 1, 1);
REQUIRE(v1 == v2); REQUIRE(v1 == v2);
REQUIRE(not (v1 < v2)); REQUIRE(not(v1 < v2));
REQUIRE(not (v1 > v2)); REQUIRE(not(v1 > v2));
REQUIRE(v1 <= v2); REQUIRE(v1 <= v2);
REQUIRE(v1 >= v2); REQUIRE(v1 >= v2);
v1.revision -= 1; v1.revision -= 1;
REQUIRE(v1 != v2); REQUIRE(v1 != v2);
REQUIRE(not (v1 == v2)); REQUIRE(not(v1 == v2));
REQUIRE(not (v1 > v2)); REQUIRE(not(v1 > v2));
REQUIRE(not (v1 >= v2)); REQUIRE(not(v1 >= v2));
REQUIRE(v1 < v2); REQUIRE(v1 < v2);
REQUIRE(v1 <= v2); REQUIRE(v1 <= v2);
v1.revision += 1; v1.revision += 1;
@ -33,60 +33,60 @@ TEST_CASE("Version API Tests", "[TestVersionAPI]") {
REQUIRE(v1 != v2); REQUIRE(v1 != v2);
REQUIRE(v1 < v2); REQUIRE(v1 < v2);
REQUIRE(v1 <= v2); REQUIRE(v1 <= v2);
REQUIRE(not (v1 == v2)); REQUIRE(not(v1 == v2));
REQUIRE(not (v1 > v2)); REQUIRE(not(v1 > v2));
REQUIRE(not (v1 >= v2)); REQUIRE(not(v1 >= v2));
v1.minor += 1; v1.minor += 1;
v1.major -= 1; v1.major -= 1;
REQUIRE(v1 != v2); REQUIRE(v1 != v2);
REQUIRE(v1 < v2); REQUIRE(v1 < v2);
REQUIRE(v1 <= v2); REQUIRE(v1 <= v2);
REQUIRE(not (v1 == v2)); REQUIRE(not(v1 == v2));
REQUIRE(not (v1 > v2)); REQUIRE(not(v1 > v2));
REQUIRE(not (v1 >= v2)); REQUIRE(not(v1 >= v2));
v1.major += 1; v1.major += 1;
REQUIRE(v1 == v2); REQUIRE(v1 == v2);
REQUIRE(v1 <= v2); REQUIRE(v1 <= v2);
REQUIRE(v1 >= v2); REQUIRE(v1 >= v2);
REQUIRE(not (v1 != v2)); REQUIRE(not(v1 != v2));
REQUIRE(not (v1 > v2)); REQUIRE(not(v1 > v2));
REQUIRE(not (v1 < v2)); REQUIRE(not(v1 < v2));
v1.major += 1; v1.major += 1;
v1.minor -= 1; v1.minor -= 1;
REQUIRE(v1 != v2); REQUIRE(v1 != v2);
REQUIRE(v1 > v2); REQUIRE(v1 > v2);
REQUIRE(v1 >= v2); REQUIRE(v1 >= v2);
REQUIRE(not (v1 == v2)); REQUIRE(not(v1 == v2));
REQUIRE(not (v1 < v2)); REQUIRE(not(v1 < v2));
REQUIRE(not (v1 <= v2)); REQUIRE(not(v1 <= v2));
v1.major -= 1; v1.major -= 1;
v1.minor += 2; v1.minor += 2;
v1.revision -= 1; v1.revision -= 1;
REQUIRE(v1 != v2); REQUIRE(v1 != v2);
REQUIRE(v1 > v2); REQUIRE(v1 > v2);
REQUIRE(v1 >= v2); REQUIRE(v1 >= v2);
REQUIRE(not (v1 == v2)); REQUIRE(not(v1 == v2));
REQUIRE(not (v1 < v2)); REQUIRE(not(v1 < v2));
REQUIRE(not (v1 <= v2)); REQUIRE(not(v1 <= v2));
v1.minor -= 1; v1.minor -= 1;
v1.revision += 2; v1.revision += 2;
REQUIRE(v1 != v2); REQUIRE(v1 != v2);
REQUIRE(v1 > v2); REQUIRE(v1 > v2);
REQUIRE(v1 >= v2); REQUIRE(v1 >= v2);
REQUIRE(not (v1 == v2)); REQUIRE(not(v1 == v2));
REQUIRE(not (v1 < v2)); REQUIRE(not(v1 < v2));
REQUIRE(not (v1 <= v2)); REQUIRE(not(v1 <= v2));
v1.revision -= 1; v1.revision -= 1;
REQUIRE(v1 == v2); REQUIRE(v1 == v2);
REQUIRE(v1 <= v2); REQUIRE(v1 <= v2);
REQUIRE(v1 >= v2); REQUIRE(v1 >= v2);
REQUIRE(not (v1 != v2)); REQUIRE(not(v1 != v2));
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "v" << fsfw::FSFW_VERSION << std::endl; sif::info << "v" << fsfw::FSFW_VERSION << std::endl;
#endif #endif
char verString[10] = {}; char verString[10] = {};
fsfw::FSFW_VERSION.getVersion(verString, sizeof(verString)); fsfw::FSFW_VERSION.getVersion(verString, sizeof(verString));
#if FSFW_DISABLE_PRINTOUT == 0 #if FSFW_DISABLE_PRINTOUT == 0
printf("v%s\n",verString); printf("v%s\n", verString);
#endif #endif
} }