Compare commits
63 Commits
develop
...
mueller/ma
Author | SHA1 | Date | |
---|---|---|---|
39d64bcbdc | |||
6d005a0957 | |||
bd4735eba7 | |||
3e2b092a17 | |||
1a530633ca | |||
0cb2868b24 | |||
8037e8074b | |||
d07e0e5576 | |||
238d98b81a | |||
5525466b52 | |||
c2a89bf709 | |||
d85f905431 | |||
8dd0b2608d | |||
05495077ec | |||
8ff9eadf30 | |||
082c86ea18 | |||
2800d6f28c | |||
2f2c393a4e | |||
2739328404 | |||
b819cad025 | |||
|
31ca1fe7cc | ||
|
a79e163524 | ||
|
7ddfc21030 | ||
|
3ded705242 | ||
|
f8864d497e | ||
5f82d58b8e | |||
45dc16170b | |||
67a79c505a | |||
e2a0c62188 | |||
c20bf31d5d | |||
|
3c06d2dbbb | ||
|
018d814f29 | ||
|
c0648a789b | ||
|
9579e94a71 | ||
|
235fd79dfb | ||
83635d3667 | |||
581ae4c990 | |||
940c53eba6 | |||
b7f6a6961b | |||
a910a05541 | |||
973996e102 | |||
b3aee76d91 | |||
b3151a0ba0 | |||
fca48257b7 | |||
8f95b03e6a | |||
527dba9a9d | |||
22cd38fffd | |||
1a518109d0 | |||
8030d9ac1b | |||
70e1db0954 | |||
1249212305 | |||
8a9452cb69 | |||
992c05df56 | |||
6698d283b6 | |||
33386550cf | |||
3a65c0db91 | |||
41614303d7 | |||
783176848a | |||
07cb980e06 | |||
d8c5bd125e | |||
facd8518eb | |||
6b8ca85dcf | |||
f7cb0bbf31 |
|
@ -37,6 +37,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
||||
inside `fsfw/version.h`
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
||||
- Added ETL dependency and improved library dependency management
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592
|
||||
|
||||
# [v4.0.0]
|
||||
|
||||
|
|
|
@ -7,6 +7,22 @@ set(FSFW_REVISION 0)
|
|||
# Add the cmake folder so the FindSphinx module is found
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||
|
||||
set(FSFW_ETL_LIB_MAJOR_VERSION 20 CACHE STRING
|
||||
"ETL library major version requirement"
|
||||
)
|
||||
set(FSFW_ETL_LIB_VERSION ${FSFW_ETL_LIB_MAJOR_VERSION}.26.0 CACHE STRING
|
||||
"ETL library exact version requirement"
|
||||
)
|
||||
|
||||
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-preview4 CACHE STRING
|
||||
"Catch2 library exact version requirement"
|
||||
)
|
||||
|
||||
set(FSFW_ETL_LIB_NAME etl)
|
||||
|
||||
option(FSFW_GENERATE_SECTIONS
|
||||
"Generate function and data sections. Required to remove unused code" ON
|
||||
)
|
||||
|
@ -48,7 +64,7 @@ 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)
|
||||
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION})
|
||||
# Not installed, so use FetchContent to download and provide Catch2
|
||||
if(NOT Catch2_FOUND)
|
||||
include(FetchContent)
|
||||
|
@ -56,7 +72,7 @@ if(FSFW_BUILD_UNITTESTS)
|
|||
FetchContent_Declare(
|
||||
Catch2
|
||||
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
||||
GIT_TAG v3.0.0-preview4
|
||||
GIT_TAG ${FSFW_CATCH2_LIB_VERSION}
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(Catch2)
|
||||
|
@ -88,6 +104,29 @@ if(FSFW_BUILD_UNITTESTS)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "Finding and/or providing ETL library")
|
||||
# Check whether the user has already installed ETL first
|
||||
# I think the version provisioning feature of CMake has not been implemented for the ETL library
|
||||
# yet. Therefore we can not specify any (not even the major) version here and we have to rely
|
||||
# on the user having installed the correct version for now
|
||||
find_package(${FSFW_ETL_LIB_NAME} 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(etl)
|
||||
endif()
|
||||
|
||||
set(FSFW_CORE_INC_PATH "inc")
|
||||
|
||||
set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux rtems freertos)
|
||||
|
@ -349,6 +388,7 @@ target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
|||
)
|
||||
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||
${FSFW_ETL_LIB_NAME}
|
||||
${FSFW_ADDITIONAL_LINK_LIBS}
|
||||
)
|
||||
|
||||
|
|
46
README.md
46
README.md
|
@ -11,9 +11,15 @@ with Airbus Defence and Space GmbH.
|
|||
|
||||
## 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:
|
||||
|
||||
|
@ -45,6 +51,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
|
||||
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_VERSION` variable.
|
||||
|
||||
You can install the ETL library like this:
|
||||
|
||||
```cpp
|
||||
git clone https://github.com/ETLCPP/etl
|
||||
cd etl
|
||||
git checkout <currentRecommendedVersion>
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --install .
|
||||
```
|
||||
|
||||
Right now, the version provision feature by the ETL library has not been implemented
|
||||
yet so `CMake` is unable to determine and check the major version of the ETL
|
||||
library. You have to ensure that the ETL library has been installed with the
|
||||
correct major version.
|
||||
|
||||
## Adding the library
|
||||
|
||||
The following steps show how to add and use FSFW components. It is still recommended to
|
||||
|
@ -83,6 +112,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`
|
||||
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.
|
||||
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`.
|
||||
|
|
|
@ -19,6 +19,30 @@ 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
|
||||
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_VERSION`` variable.
|
||||
|
||||
You can install the ETL library like this:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
git clone https://github.com/ETLCPP/etl
|
||||
cd etl
|
||||
git checkout <currentRecommendedVersion>
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --install .
|
||||
|
||||
Right now, the version provision feature by the ETL library has not been implemented
|
||||
yet so ``CMake`` is unable to determine and check the major version of the ETL
|
||||
library. You have to ensure that the ETL library has been installed with the
|
||||
correct major version.
|
||||
|
||||
Adding the library
|
||||
-------------------
|
||||
|
||||
|
@ -60,6 +84,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`
|
||||
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.
|
||||
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`.
|
||||
|
|
|
@ -74,7 +74,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
|||
configureGpioByLineName(gpioConfig.first, *regularGpio);
|
||||
break;
|
||||
}
|
||||
case (gpio::GpioTypes::CALLBACK): {
|
||||
case (gpio::GpioTypes::TYPE_CALLBACK): {
|
||||
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioConfig.second);
|
||||
if (gpioCallback->callback == nullptr) {
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
|
@ -327,7 +327,7 @@ ReturnValue_t LinuxLibgpioIF::checkForConflicts(GpioMap& mapToAdd) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case (gpio::GpioTypes::CALLBACK): {
|
||||
case (gpio::GpioTypes::TYPE_CALLBACK): {
|
||||
auto callbackGpio = dynamic_cast<GpioCallback*>(gpioConfig.second);
|
||||
if (callbackGpio == nullptr) {
|
||||
return GPIO_TYPE_FAILURE;
|
||||
|
@ -367,13 +367,13 @@ ReturnValue_t LinuxLibgpioIF::checkForConflictsById(gpioId_t gpioIdToCheck,
|
|||
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) {
|
||||
if (gpioType == gpio::GpioTypes::NONE or gpioType == gpio::GpioTypes::TYPE_CALLBACK) {
|
||||
eraseDuplicateDifferentType = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (gpio::GpioTypes::CALLBACK): {
|
||||
if (gpioType != gpio::GpioTypes::CALLBACK) {
|
||||
case (gpio::GpioTypes::TYPE_CALLBACK): {
|
||||
if (gpioType != gpio::GpioTypes::TYPE_CALLBACK) {
|
||||
eraseDuplicateDifferentType = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -210,7 +210,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||
#endif
|
||||
return result;
|
||||
}
|
||||
ReturnValue_t result = gpioComIF->pullLow(gpioId);
|
||||
result = gpioComIF->pullLow(gpioId);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
|
|
|
@ -29,6 +29,7 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event)
|
|||
switch (event->getEvent()) {
|
||||
case HasModesIF::MODE_TRANSITION_FAILED:
|
||||
case HasModesIF::OBJECT_IN_INVALID_MODE:
|
||||
case DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT:
|
||||
// We'll try a recovery as long as defined in MAX_REBOOT.
|
||||
// Might cause some AssemblyBase cycles, so keep number low.
|
||||
handleRecovery(event->getEvent());
|
||||
|
|
|
@ -109,6 +109,7 @@ class DeviceHandlerIF {
|
|||
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, severity::LOW);
|
||||
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, severity::LOW);
|
||||
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, severity::HIGH);
|
||||
static const Event DEVICE_WANTS_HARD_REBOOT = MAKE_EVENT(11, severity::HIGH);
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;
|
||||
|
||||
|
|
|
@ -182,9 +182,9 @@ void EventManager::printUtility(sif::OutputTypes printType, EventMessage* messag
|
|||
sif::printDebug("Event Manager: Reporter ID 0x%08x reported event with ID %d\n",
|
||||
message->getReporter(), message->getEventId());
|
||||
}
|
||||
sif::printDebug("P1 Hex: 0x%x | P1 Dec: %d | P2 Hex: 0x%x | P2 Dec: %d\n",
|
||||
message->getParameter1(), message->getParameter1(), message->getParameter2(),
|
||||
message->getParameter2());
|
||||
sif::printDebug("%s | P1 Hex: 0x%x | P1 Dec: %d | P2 Hex: 0x%x | P2 Dec: %d\n",
|
||||
translateEvents(message->getEvent()), message->getParameter1(),
|
||||
message->getParameter1(), message->getParameter2(), message->getParameter2());
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 0 */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,13 +14,12 @@ class FailureIsolationBase : public HasReturnvaluesIF,
|
|||
public HasParametersIF {
|
||||
public:
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1;
|
||||
static const Event FDIR_CHANGED_STATE =
|
||||
MAKE_EVENT(1, severity::INFO); //!< FDIR has an internal state, which changed from par2
|
||||
//!< (oldState) to par1 (newState).
|
||||
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(
|
||||
2, severity::MEDIUM); //!< FDIR tries to restart device. Par1: event that caused recovery.
|
||||
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(
|
||||
3, severity::MEDIUM); //!< FDIR turns off device. Par1: event that caused recovery.
|
||||
//! FDIR has an internal state, which changed from par2 (oldState) to par1 (newState).
|
||||
static const Event FDIR_CHANGED_STATE = MAKE_EVENT(1, severity::INFO);
|
||||
//! FDIR tries to restart device. Par1: event that caused recovery.
|
||||
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(2, severity::MEDIUM);
|
||||
//! FDIR turns off device. Par1: event that caused recovery.
|
||||
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(3, severity::MEDIUM);
|
||||
|
||||
FailureIsolationBase(object_id_t owner, object_id_t parent = objects::NO_OBJECT,
|
||||
uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0);
|
||||
|
|
|
@ -23,19 +23,15 @@ class HasHealthIF {
|
|||
static const Event HEALTH_INFO = MAKE_EVENT(6, severity::INFO);
|
||||
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO);
|
||||
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW);
|
||||
static const Event OVERWRITING_HEALTH =
|
||||
MAKE_EVENT(9, severity::LOW); //!< Assembly overwrites health information of children to keep
|
||||
//!< satellite alive.
|
||||
static const Event TRYING_RECOVERY =
|
||||
MAKE_EVENT(10, severity::MEDIUM); //!< Someone starts a recovery of a component (typically
|
||||
//!< power-cycle). No parameters.
|
||||
static const Event RECOVERY_STEP =
|
||||
MAKE_EVENT(11, severity::MEDIUM); //!< Recovery is ongoing. Comes twice during recovery. P1:
|
||||
//!< 0 for the first, 1 for the second event. P2: 0
|
||||
static const Event RECOVERY_DONE = MAKE_EVENT(
|
||||
12,
|
||||
severity::MEDIUM); //!< Recovery was completed. Not necessarily successful. No parameters.
|
||||
|
||||
//! Assembly overwrites health information of children to keep satellite alive.
|
||||
static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, severity::LOW);
|
||||
//! Someone starts a recovery of a component (typically power-cycle). No parameters.
|
||||
static const Event TRYING_RECOVERY = MAKE_EVENT(10, severity::MEDIUM);
|
||||
//! Recovery is ongoing. Comes twice during recovery.
|
||||
//! P1: 0 for the first, 1 for the second event. P2: 0
|
||||
static const Event RECOVERY_STEP = MAKE_EVENT(11, severity::MEDIUM);
|
||||
//! Recovery was completed. Not necessarily successful. No parameters.
|
||||
static const Event RECOVERY_DONE = MAKE_EVENT(12, severity::MEDIUM);
|
||||
virtual ~HasHealthIF() {}
|
||||
|
||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
|
|
|
@ -19,32 +19,29 @@ class HasModesIF {
|
|||
static const ReturnValue_t INVALID_SUBMODE = MAKE_RETURN_CODE(0x04);
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER;
|
||||
static const Event CHANGING_MODE =
|
||||
MAKE_EVENT(0, severity::INFO); //!< An object announces changing the mode. p1: target mode.
|
||||
//!< p2: target submode
|
||||
static const Event MODE_INFO = MAKE_EVENT(
|
||||
1,
|
||||
severity::INFO); //!< An Object announces its mode; parameter1 is mode, parameter2 is submode
|
||||
//! An object announces changing the mode. p1: target mode. p2: target submode
|
||||
static const Event CHANGING_MODE = MAKE_EVENT(0, severity::INFO);
|
||||
//! An Object announces its mode; parameter1 is mode, parameter2 is submode
|
||||
static const Event MODE_INFO = MAKE_EVENT(1, severity::INFO);
|
||||
static const Event FALLBACK_FAILED = MAKE_EVENT(2, severity::HIGH);
|
||||
static const Event MODE_TRANSITION_FAILED = MAKE_EVENT(3, severity::LOW);
|
||||
static const Event CANT_KEEP_MODE = MAKE_EVENT(4, severity::HIGH);
|
||||
static const Event OBJECT_IN_INVALID_MODE =
|
||||
MAKE_EVENT(5, severity::LOW); //!< Indicates a bug or configuration failure: Object is in a
|
||||
//!< mode it should never be in.
|
||||
static const Event FORCING_MODE = MAKE_EVENT(
|
||||
6, severity::MEDIUM); //!< The mode is changed, but for some reason, the change is forced,
|
||||
//!< i.e. EXTERNAL_CONTROL ignored. p1: target mode. p2: target submode
|
||||
static const Event MODE_CMD_REJECTED =
|
||||
MAKE_EVENT(7, severity::LOW); //!< A mode command was rejected by the called object. Par1:
|
||||
//!< called object id, Par2: return code.
|
||||
//! Indicates a bug or configuration failure: Object is in a mode it should never be in.
|
||||
static const Event OBJECT_IN_INVALID_MODE = MAKE_EVENT(5, severity::LOW);
|
||||
//! The mode is changed, but for some reason, the change is forced, i.e. EXTERNAL_CONTROL ignored.
|
||||
//! p1: target mode. p2: target submode
|
||||
static const Event FORCING_MODE = MAKE_EVENT(6, severity::MEDIUM);
|
||||
//! A mode command was rejected by the called object. Par1: called object id, Par2: return code.
|
||||
static const Event MODE_CMD_REJECTED = MAKE_EVENT(7, severity::LOW);
|
||||
|
||||
static const Mode_t MODE_ON =
|
||||
1; //!< The device is powered and ready to perform operations. In this mode, no commands are
|
||||
//!< sent by the device handler itself, but direct commands van be commanded and will be
|
||||
//!< interpreted
|
||||
static const Mode_t MODE_OFF = 0; //!< The device is powered off. The only command accepted in
|
||||
//!< this mode is a mode change to on.
|
||||
static const Submode_t SUBMODE_NONE = 0; //!< To avoid checks against magic number "0".
|
||||
//! The device is powered and ready to perform operations. In this mode, no commands are
|
||||
//! sent by the device handler itself, but direct commands van be commanded and will be
|
||||
//! interpreted
|
||||
static const Mode_t MODE_ON = 1;
|
||||
//! The device is powered off. The only command accepted in this mode is a mode change to on.
|
||||
static const Mode_t MODE_OFF = 0;
|
||||
//! To avoid checks against magic number "0".
|
||||
static const Submode_t SUBMODE_NONE = 0;
|
||||
|
||||
virtual ~HasModesIF() {}
|
||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
|
|
|
@ -34,14 +34,14 @@ class Fuse : public SystemObject,
|
|||
};
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_1;
|
||||
static const Event FUSE_CURRENT_HIGH = MAKE_EVENT(
|
||||
1, severity::LOW); //!< PSS detected that current on a fuse is totally out of bounds.
|
||||
static const Event FUSE_WENT_OFF =
|
||||
MAKE_EVENT(2, severity::LOW); //!< PSS detected a fuse that went off.
|
||||
static const Event POWER_ABOVE_HIGH_LIMIT =
|
||||
MAKE_EVENT(4, severity::LOW); //!< PSS detected a fuse that violates its limits.
|
||||
static const Event POWER_BELOW_LOW_LIMIT =
|
||||
MAKE_EVENT(5, severity::LOW); //!< PSS detected a fuse that violates its limits.
|
||||
//! PSS detected that current on a fuse is totally out of bounds.
|
||||
static const Event FUSE_CURRENT_HIGH = MAKE_EVENT(1, severity::LOW);
|
||||
//! PSS detected a fuse that went off.
|
||||
static const Event FUSE_WENT_OFF = MAKE_EVENT(2, severity::LOW);
|
||||
//! PSS detected a fuse that violates its limits.
|
||||
static const Event POWER_ABOVE_HIGH_LIMIT = MAKE_EVENT(4, severity::LOW);
|
||||
//! PSS detected a fuse that violates its limits.
|
||||
static const Event POWER_BELOW_LOW_LIMIT = MAKE_EVENT(5, severity::LOW);
|
||||
|
||||
typedef std::list<PowerComponentIF *> DeviceList;
|
||||
Fuse(object_id_t fuseObjectId, uint8_t fuseId, sid_t variableSet, VariableIds ids,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <fsfw/tmtcservices/TmTcMessage.h>
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/returnvalues/FwClassIds.h"
|
||||
|
||||
/**
|
||||
* @brief: PUS-Service 11 - Telecommand scheduling.
|
||||
|
@ -34,8 +35,12 @@
|
|||
template <size_t MAX_NUM_TCS>
|
||||
class Service11TelecommandScheduling final : public PusServiceBase {
|
||||
public:
|
||||
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_11;
|
||||
|
||||
static constexpr ReturnValue_t INVALID_TYPE_TIME_WINDOW =
|
||||
HasReturnvaluesIF::makeReturnCode(CLASS_ID, 1);
|
||||
// The types of PUS-11 subservices
|
||||
enum Subservice {
|
||||
enum Subservice : uint8_t {
|
||||
ENABLE_SCHEDULING = 1,
|
||||
DISABLE_SCHEDULING = 2,
|
||||
RESET_SCHEDULING = 3,
|
||||
|
@ -103,31 +108,31 @@ class Service11TelecommandScheduling final : public PusServiceBase {
|
|||
* @brief Logic to be performed on an incoming TC[11,4].
|
||||
* @return RETURN_OK if successful
|
||||
*/
|
||||
ReturnValue_t doInsertActivity(void);
|
||||
ReturnValue_t doInsertActivity(const uint8_t* data, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Logic to be performed on an incoming TC[11,5].
|
||||
* @return RETURN_OK if successful
|
||||
*/
|
||||
ReturnValue_t doDeleteActivity(void);
|
||||
ReturnValue_t doDeleteActivity(const uint8_t* data, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Logic to be performed on an incoming TC[11,6].
|
||||
* @return RETURN_OK if successful
|
||||
*/
|
||||
ReturnValue_t doFilterDeleteActivity(void);
|
||||
ReturnValue_t doFilterDeleteActivity(const uint8_t* data, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Logic to be performed on an incoming TC[11,7].
|
||||
* @return RETURN_OK if successful
|
||||
*/
|
||||
ReturnValue_t doTimeshiftActivity(void);
|
||||
ReturnValue_t doTimeshiftActivity(const uint8_t* data, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Logic to be performed on an incoming TC[11,8].
|
||||
* @return RETURN_OK if successful
|
||||
*/
|
||||
ReturnValue_t doFilterTimeshiftActivity(void);
|
||||
ReturnValue_t doFilterTimeshiftActivity(const uint8_t* data, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Deserializes a generic type from a payload buffer by using the FSFW
|
||||
|
@ -158,7 +163,7 @@ class Service11TelecommandScheduling final : public PusServiceBase {
|
|||
* @param [out] requestId Request ID
|
||||
* @return RETURN_OK if successful
|
||||
*/
|
||||
ReturnValue_t getRequestIdFromData(const uint8_t* data, size_t& dataSize, uint64_t& requestId);
|
||||
ReturnValue_t getRequestIdFromData(const uint8_t*& data, size_t& dataSize, uint64_t& requestId);
|
||||
|
||||
/**
|
||||
* @brief Builds the Request ID from its three elements.
|
||||
|
@ -177,9 +182,10 @@ class Service11TelecommandScheduling final : public PusServiceBase {
|
|||
* @param [out] itEnd End of filter range
|
||||
* @return RETURN_OK if successful
|
||||
*/
|
||||
ReturnValue_t getMapFilterFromData(const uint8_t* data, size_t dataSize, TcMapIter& itBegin,
|
||||
ReturnValue_t getMapFilterFromData(const uint8_t*& data, size_t& size, TcMapIter& itBegin,
|
||||
TcMapIter& itEnd);
|
||||
|
||||
ReturnValue_t handleInvalidData(const char* ctx);
|
||||
/**
|
||||
* @brief Prints content of multimap. Use for simple debugging only.
|
||||
*/
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include <cstddef>
|
||||
|
||||
static constexpr auto DEF_END = SerializeIF::Endianness::BIG;
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline Service11TelecommandScheduling<MAX_NUM_TCS>::Service11TelecommandScheduling(
|
||||
object_id_t objectId, uint16_t apid, uint8_t serviceId, AcceptsTelecommandsIF *tcRecipient,
|
||||
|
@ -28,17 +30,23 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::handleRequest(
|
|||
sif::printInfo("PUS11::handleRequest: Handling request %d\n", subservice);
|
||||
#endif
|
||||
}
|
||||
// Get de-serialized Timestamp
|
||||
const uint8_t *data = currentPacket.getApplicationData();
|
||||
size_t size = currentPacket.getApplicationDataSize();
|
||||
if (data == nullptr) {
|
||||
return handleInvalidData("handleRequest");
|
||||
}
|
||||
switch (subservice) {
|
||||
case Subservice::INSERT_ACTIVITY:
|
||||
return doInsertActivity();
|
||||
return doInsertActivity(data, size);
|
||||
case Subservice::DELETE_ACTIVITY:
|
||||
return doDeleteActivity();
|
||||
return doDeleteActivity(data, size);
|
||||
case Subservice::FILTER_DELETE_ACTIVITY:
|
||||
return doFilterDeleteActivity();
|
||||
return doFilterDeleteActivity(data, size);
|
||||
case Subservice::TIMESHIFT_ACTIVITY:
|
||||
return doTimeshiftActivity();
|
||||
return doTimeshiftActivity(data, size);
|
||||
case Subservice::FILTER_TIMESHIFT_ACTIVITY:
|
||||
return doFilterTimeshiftActivity();
|
||||
return doFilterTimeshiftActivity(data, size);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -105,17 +113,15 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::initialize() {
|
|||
}
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivity(void) {
|
||||
// Get de-serialized Timestamp
|
||||
const uint8_t *data = currentPacket.getApplicationData();
|
||||
size_t dataSize = currentPacket.getApplicationDataSize();
|
||||
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivity(
|
||||
const uint8_t *data, size_t size) {
|
||||
uint32_t timestamp = 0;
|
||||
if (deserializeViaFsfwInterface<uint32_t>(timestamp, data, dataSize) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
const uint8_t *initData = data;
|
||||
size_t initSz = size;
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(×tamp, &data, &size, DEF_END);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
data += sizeof(uint32_t); // move ptr past timestamp (for later)
|
||||
dataSize -= sizeof(uint32_t); // and reduce size accordingly
|
||||
|
||||
// Insert possible if sched. time is above margin
|
||||
// (See requirement for Time margin)
|
||||
|
@ -135,8 +141,8 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivi
|
|||
}
|
||||
|
||||
// store currentPacket and receive the store address
|
||||
store_address_t addr;
|
||||
if (tcStore->addData(&addr, data, dataSize) != RETURN_OK ||
|
||||
store_address_t addr{};
|
||||
if (tcStore->addData(&addr, initData, initSz) != RETURN_OK ||
|
||||
addr.raw == storeId::INVALID_STORE_ADDRESS) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Service11TelecommandScheduling::doInsertActivity: Adding data to TC Store failed"
|
||||
|
@ -172,14 +178,13 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivi
|
|||
}
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doDeleteActivity(void) {
|
||||
const uint8_t *data = currentPacket.getApplicationData();
|
||||
size_t dataSize = currentPacket.getApplicationDataSize();
|
||||
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doDeleteActivity(
|
||||
const uint8_t *data, size_t size) {
|
||||
// Get request ID
|
||||
uint64_t requestId;
|
||||
if (getRequestIdFromData(data, dataSize, requestId) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
ReturnValue_t result = getRequestIdFromData(data, size, requestId);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// DEBUG
|
||||
|
@ -240,16 +245,15 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doDeleteActivi
|
|||
}
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doFilterDeleteActivity(void) {
|
||||
const uint8_t *data = currentPacket.getApplicationData();
|
||||
size_t dataSize = currentPacket.getApplicationDataSize();
|
||||
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doFilterDeleteActivity(
|
||||
const uint8_t *data, size_t size) {
|
||||
TcMapIter itBegin;
|
||||
TcMapIter itEnd;
|
||||
|
||||
ReturnValue_t result = getMapFilterFromData(data, size, itBegin, itEnd);
|
||||
// get the filter window as map range via dedicated method
|
||||
if (getMapFilterFromData(data, dataSize, itBegin, itEnd) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int deletedTCs = 0;
|
||||
|
@ -290,26 +294,22 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doFilterDelete
|
|||
}
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doTimeshiftActivity(void) {
|
||||
const uint8_t *data = currentPacket.getApplicationData();
|
||||
size_t dataSize = currentPacket.getApplicationDataSize();
|
||||
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doTimeshiftActivity(
|
||||
const uint8_t *data, size_t size) {
|
||||
// Get relative time
|
||||
uint32_t relativeTime = 0;
|
||||
if (deserializeViaFsfwInterface<uint32_t>(relativeTime, data, dataSize) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(&relativeTime, &data, &size, DEF_END);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
if (relativeTime == 0) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
// TODO further check sanity of the relative time?
|
||||
|
||||
data += sizeof(uint32_t);
|
||||
dataSize -= sizeof(uint32_t);
|
||||
|
||||
// Get request ID
|
||||
uint64_t requestId;
|
||||
if (getRequestIdFromData(data, dataSize, requestId) != RETURN_OK) {
|
||||
if (getRequestIdFromData(data, size, requestId) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
|
@ -371,26 +371,24 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doTimeshiftAct
|
|||
}
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doFilterTimeshiftActivity(void) {
|
||||
const uint8_t *data = currentPacket.getApplicationData();
|
||||
uint32_t dataSize = currentPacket.getApplicationDataSize();
|
||||
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doFilterTimeshiftActivity(
|
||||
const uint8_t *data, size_t size) {
|
||||
// Get relative time
|
||||
uint32_t relativeTime = 0;
|
||||
if (deserializeViaFsfwInterface<uint32_t>(relativeTime, data, dataSize) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(&relativeTime, &data, &size, DEF_END);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
if (relativeTime == 0) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
data += sizeof(uint32_t);
|
||||
dataSize -= sizeof(uint32_t);
|
||||
|
||||
// Do time window
|
||||
TcMapIter itBegin;
|
||||
TcMapIter itEnd;
|
||||
if (getMapFilterFromData(data, dataSize, itBegin, itEnd) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
result = getMapFilterFromData(data, size, itBegin, itEnd);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int shiftedItemsCount = 0;
|
||||
|
@ -438,27 +436,23 @@ inline uint64_t Service11TelecommandScheduling<MAX_NUM_TCS>::getRequestIdFromDat
|
|||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::getRequestIdFromData(
|
||||
const uint8_t *data, size_t &dataSize, uint64_t &requestId) {
|
||||
const uint8_t *&data, size_t &dataSize, uint64_t &requestId) {
|
||||
uint32_t srcId = 0;
|
||||
uint16_t apid = 0;
|
||||
uint16_t ssc = 0;
|
||||
|
||||
if (deserializeViaFsfwInterface<uint32_t>(srcId, data, dataSize) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(&srcId, &data, &dataSize, DEF_END);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
data += sizeof(uint32_t);
|
||||
dataSize -= sizeof(uint32_t);
|
||||
if (deserializeViaFsfwInterface<uint16_t>(apid, data, dataSize) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
result = SerializeAdapter::deSerialize(&apid, &data, &dataSize, DEF_END);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
data += sizeof(uint32_t);
|
||||
dataSize -= sizeof(uint32_t);
|
||||
if (deserializeViaFsfwInterface<uint16_t>(ssc, data, dataSize) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
result = SerializeAdapter::deSerialize(&ssc, &data, &dataSize, DEF_END);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
requestId = buildRequestId(srcId, apid, ssc);
|
||||
|
||||
return RETURN_OK;
|
||||
|
@ -477,16 +471,17 @@ inline uint64_t Service11TelecommandScheduling<MAX_NUM_TCS>::buildRequestId(uint
|
|||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::getMapFilterFromData(
|
||||
const uint8_t *data, size_t dataSize, TcMapIter &itBegin, TcMapIter &itEnd) {
|
||||
const uint8_t *&data, size_t &dataSize, TcMapIter &itBegin, TcMapIter &itEnd) {
|
||||
// get filter type first
|
||||
uint32_t typeRaw;
|
||||
if (deserializeViaFsfwInterface(typeRaw, data, dataSize) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
uint32_t typeRaw = 0;
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(&typeRaw, &data, &dataSize, DEF_END);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
// can be modified as the uint8_t pointer is passed by value (copy of ptr is modified)
|
||||
data += sizeof(uint32_t);
|
||||
dataSize -= sizeof(uint32_t);
|
||||
|
||||
if (typeRaw > 3) {
|
||||
return INVALID_TYPE_TIME_WINDOW;
|
||||
}
|
||||
TypeOfTimeWindow type = static_cast<TypeOfTimeWindow>(typeRaw);
|
||||
|
||||
// we now have the type of delete activity - so now we set the range to delete,
|
||||
|
@ -501,9 +496,10 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::getMapFilterFr
|
|||
}
|
||||
|
||||
case TypeOfTimeWindow::FROM_TIMETAG: {
|
||||
uint32_t fromTimestamp;
|
||||
if (deserializeViaFsfwInterface<uint32_t>(fromTimestamp, data, dataSize) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
uint32_t fromTimestamp = 0;
|
||||
result = SerializeAdapter::deSerialize(&fromTimestamp, &data, &dataSize, DEF_END);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
itBegin = telecommandMap.begin();
|
||||
|
@ -517,8 +513,9 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::getMapFilterFr
|
|||
|
||||
case TypeOfTimeWindow::TO_TIMETAG: {
|
||||
uint32_t toTimestamp;
|
||||
if (deserializeViaFsfwInterface<uint32_t>(toTimestamp, data, dataSize) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
result = SerializeAdapter::deSerialize(&toTimestamp, &data, &dataSize, DEF_END);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
itBegin = telecommandMap.begin();
|
||||
itEnd = telecommandMap.begin();
|
||||
|
@ -532,14 +529,15 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::getMapFilterFr
|
|||
uint32_t fromTimestamp;
|
||||
uint32_t toTimestamp;
|
||||
|
||||
if (deserializeViaFsfwInterface<uint32_t>(fromTimestamp, data, dataSize) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
result = SerializeAdapter::deSerialize(&fromTimestamp, &data, &dataSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
data += sizeof(uint32_t);
|
||||
dataSize -= sizeof(uint32_t);
|
||||
|
||||
if (deserializeViaFsfwInterface<uint32_t>(toTimestamp, data, dataSize) != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
result = SerializeAdapter::deSerialize(&toTimestamp, &data, &dataSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
itBegin = telecommandMap.begin();
|
||||
itEnd = telecommandMap.begin();
|
||||
|
@ -568,25 +566,16 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::getMapFilterFr
|
|||
}
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
template <typename T>
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::deserializeViaFsfwInterface(
|
||||
T &output, const uint8_t *buf, size_t bufsize) {
|
||||
if (buf == nullptr) {
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::handleInvalidData(
|
||||
const char *ctx) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "Service11TelecommandScheduling::deserializeViaFsfwInterface: "
|
||||
"Invalid buffer"
|
||||
<< std::endl;
|
||||
sif::warning << "Service11TelecommandScheduling:: " << ctx << ": Invalid buffer" << std::endl;
|
||||
#else
|
||||
sif::printWarning(
|
||||
"Service11TelecommandScheduling::deserializeViaFsfwInterface: "
|
||||
"Invalid buffer\n");
|
||||
sif::printWarning("Service11TelecommandScheduling::%s: Invalid buffer\n", ctx);
|
||||
#endif
|
||||
#endif
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
return SerializeAdapter::deSerialize<T>(&output, &buf, &bufsize, SerializeIF::Endianness::BIG);
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
class Service9TimeManagement : public PusServiceBase {
|
||||
public:
|
||||
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
|
||||
static constexpr Event CLOCK_SET =
|
||||
MAKE_EVENT(0, severity::INFO); //!< Clock has been set. P1: New Uptime. P2: Old Uptime
|
||||
static constexpr Event CLOCK_SET_FAILURE =
|
||||
MAKE_EVENT(1, severity::LOW); //!< Clock could not be set. P1: Returncode.
|
||||
//!< Clock has been set. P1: New Uptime. P2: Old Uptime
|
||||
static constexpr Event CLOCK_SET = MAKE_EVENT(0, severity::INFO);
|
||||
//!< Clock could not be set. P1: Returncode.
|
||||
static constexpr Event CLOCK_SET_FAILURE = MAKE_EVENT(1, severity::LOW);
|
||||
|
||||
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ enum : uint8_t {
|
|||
DLE_ENCODER, // DLEE
|
||||
PUS_SERVICE_3, // PUS3
|
||||
PUS_SERVICE_9, // PUS9
|
||||
PUS_SERVICE_11, // PUS11
|
||||
FILE_SYSTEM, // FILS
|
||||
LINUX_OSAL, // UXOS
|
||||
HAL_SPI, // HSPI
|
||||
|
@ -82,6 +83,7 @@ enum : uint8_t {
|
|||
MGM_LIS3MDL, // MGMLIS3
|
||||
MGM_RM3100, // MGMRM3100
|
||||
SPACE_PACKET_PARSER, // SPPA
|
||||
USLP, // USLP
|
||||
FW_CLASS_ID_COUNT // [EXPORT] : [END]
|
||||
|
||||
};
|
||||
|
|
|
@ -99,6 +99,13 @@ class Clock {
|
|||
*/
|
||||
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.
|
||||
* @param time The time of day as input
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include <ctime>
|
||||
|
||||
#include "fsfw/ipc/MutexGuard.h"
|
||||
#include "fsfw/timemanager/Clock.h"
|
||||
|
||||
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval *tt) {
|
||||
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
|
||||
uint16_t leapSeconds;
|
||||
ReturnValue_t result = getLeapSeconds(&leapSeconds);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
|
@ -31,7 +33,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
|
|||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getLeapSeconds(uint16_t *leapSeconds_) {
|
||||
ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
|
||||
if (timeMutex == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
@ -42,9 +44,22 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t *leapSeconds_) {
|
|||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* to) {
|
||||
struct tm* timeInfo;
|
||||
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() {
|
||||
if (timeMutex == nullptr) {
|
||||
MutexFactory *mutexFactory = MutexFactory::instance();
|
||||
MutexFactory* mutexFactory = MutexFactory::instance();
|
||||
if (mutexFactory == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
|
|
@ -33,50 +33,47 @@ class TmStoreBackendIF : public HasParametersIF {
|
|||
static const ReturnValue_t INVALID_REQUEST = MAKE_RETURN_CODE(15);
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::MEMORY;
|
||||
static const Event STORE_SEND_WRITE_FAILED =
|
||||
MAKE_EVENT(0, severity::LOW); //!< Initiating sending data to store failed. Low, par1:
|
||||
//!< returnCode, par2: integer (debug info)
|
||||
static const Event STORE_WRITE_FAILED = MAKE_EVENT(
|
||||
1, severity::LOW); //!< Data was sent, but writing failed. Low, par1: returnCode, par2: 0
|
||||
static const Event STORE_SEND_READ_FAILED =
|
||||
MAKE_EVENT(2, severity::LOW); //!< Initiating reading data from store failed. Low, par1:
|
||||
//!< returnCode, par2: 0
|
||||
static const Event STORE_READ_FAILED = MAKE_EVENT(
|
||||
3, severity::LOW); //!< Data was requested, but access failed. Low, par1: returnCode, par2: 0
|
||||
static const Event UNEXPECTED_MSG =
|
||||
MAKE_EVENT(4, severity::LOW); //!< An unexpected TM packet or data message occurred. Low,
|
||||
//!< par1: 0, par2: integer (debug info)
|
||||
static const Event STORING_FAILED = MAKE_EVENT(
|
||||
5, severity::LOW); //!< Storing data failed. May simply be a full store. Low, par1:
|
||||
//!< returnCode, par2: integer (sequence count of failed packet).
|
||||
static const Event TM_DUMP_FAILED =
|
||||
MAKE_EVENT(6, severity::LOW); //!< Dumping retrieved data failed. Low, par1: returnCode,
|
||||
//!< par2: integer (sequence count of failed packet).
|
||||
static const Event STORE_INIT_FAILED =
|
||||
MAKE_EVENT(7, severity::LOW); //!< Corrupted init data or read error. Low, par1: returnCode,
|
||||
//!< par2: integer (debug info)
|
||||
static const Event STORE_INIT_EMPTY = MAKE_EVENT(
|
||||
8, severity::INFO); //!< Store was not initialized. Starts empty. Info, parameters both zero.
|
||||
static const Event STORE_CONTENT_CORRUPTED =
|
||||
MAKE_EVENT(9, severity::LOW); //!< Data was read out, but it is inconsistent. Low par1:
|
||||
//!< Memory address of corruption, par2: integer (debug info)
|
||||
static const Event STORE_INITIALIZE =
|
||||
MAKE_EVENT(10, severity::INFO); //!< Info event indicating the store will be initialized,
|
||||
//!< either at boot or after IOB switch. Info. pars: 0
|
||||
static const Event INIT_DONE = MAKE_EVENT(
|
||||
11, severity::INFO); //!< Info event indicating the store was successfully initialized,
|
||||
//!< either at boot or after IOB switch. Info. pars: 0
|
||||
static const Event DUMP_FINISHED = MAKE_EVENT(
|
||||
12, severity::INFO); //!< Info event indicating that dumping finished successfully. par1:
|
||||
//!< Number of dumped packets. par2: APID/SSC (16bits each)
|
||||
static const Event DELETION_FINISHED = MAKE_EVENT(
|
||||
13, severity::INFO); //!< Info event indicating that deletion finished successfully. par1:
|
||||
//!< Number of deleted packets. par2: APID/SSC (16bits each)
|
||||
static const Event DELETION_FAILED = MAKE_EVENT(
|
||||
14,
|
||||
severity::LOW); //!< Info event indicating that something went wrong during deletion. pars: 0
|
||||
static const Event AUTO_CATALOGS_SENDING_FAILED =
|
||||
MAKE_EVENT(15, severity::INFO); //!< Info that the a auto catalog report failed
|
||||
//! Initiating sending data to store failed. Low, par1:
|
||||
//! returnCode, par2: integer (debug info)
|
||||
static const Event STORE_SEND_WRITE_FAILED = MAKE_EVENT(0, severity::LOW);
|
||||
//! Data was sent, but writing failed. Low, par1: returnCode, par2: 0
|
||||
static const Event STORE_WRITE_FAILED = MAKE_EVENT(1, severity::LOW);
|
||||
//! Initiating reading data from store failed. Low, par1: returnCode, par2: 0
|
||||
static const Event STORE_SEND_READ_FAILED = MAKE_EVENT(2, severity::LOW);
|
||||
//! Data was requested, but access failed. Low, par1: returnCode, par2: 0
|
||||
static const Event STORE_READ_FAILED = MAKE_EVENT(3, severity::LOW);
|
||||
//! An unexpected TM packet or data message occurred. Low, par1: 0, par2: integer (debug info)
|
||||
static const Event UNEXPECTED_MSG = MAKE_EVENT(4, severity::LOW);
|
||||
//! Storing data failed. May simply be a full store. Low, par1: returnCode,
|
||||
//! par2: integer (sequence count of failed packet).
|
||||
static const Event STORING_FAILED = MAKE_EVENT(5, severity::LOW);
|
||||
//! Dumping retrieved data failed. Low, par1: returnCode,
|
||||
//! par2: integer (sequence count of failed packet).
|
||||
static const Event TM_DUMP_FAILED = MAKE_EVENT(6, severity::LOW);
|
||||
//! Corrupted init data or read error. Low, par1: returnCode, par2: integer (debug info)
|
||||
//! Store was not initialized. Starts empty. Info, parameters both zero.
|
||||
static const Event STORE_INIT_FAILED = MAKE_EVENT(7, severity::LOW);
|
||||
//! Data was read out, but it is inconsistent. Low par1:
|
||||
//! Memory address of corruption, par2: integer (debug info)
|
||||
static const Event STORE_INIT_EMPTY = MAKE_EVENT(8, severity::INFO);
|
||||
|
||||
static const Event STORE_CONTENT_CORRUPTED = MAKE_EVENT(9, severity::LOW);
|
||||
//! Info event indicating the store will be initialized, either at boot or after IOB switch.
|
||||
//! Info. pars: 0
|
||||
static const Event STORE_INITIALIZE = MAKE_EVENT(10, severity::INFO);
|
||||
//! Info event indicating the store was successfully initialized, either at boot or after
|
||||
//! IOB switch. Info. pars: 0
|
||||
static const Event INIT_DONE = MAKE_EVENT(11, severity::INFO);
|
||||
//! Info event indicating that dumping finished successfully.
|
||||
//! par1: Number of dumped packets. par2: APID/SSC (16bits each)
|
||||
static const Event DUMP_FINISHED = MAKE_EVENT(12, severity::INFO);
|
||||
//! Info event indicating that deletion finished successfully.
|
||||
//! par1:Number of deleted packets. par2: APID/SSC (16bits each)
|
||||
static const Event DELETION_FINISHED = MAKE_EVENT(13, severity::INFO);
|
||||
//! Info event indicating that something went wrong during deletion. pars: 0
|
||||
static const Event DELETION_FAILED = MAKE_EVENT(14, severity::LOW);
|
||||
//! Info that the a auto catalog report failed
|
||||
static const Event AUTO_CATALOGS_SENDING_FAILED = MAKE_EVENT(15, severity::INFO);
|
||||
|
||||
virtual ~TmStoreBackendIF() {}
|
||||
|
||||
|
|
|
@ -97,3 +97,15 @@ ReturnValue_t TcPacketPus::setData(uint8_t *dataPtr, size_t maxSize, void *args)
|
|||
tcData = reinterpret_cast<TcPacketPointer *>(const_cast<uint8_t *>(dataPtr));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void TcPacketPus::setApplicationData(const uint8_t *data, size_t len, bool updateSpLenField) {
|
||||
if (data == nullptr) {
|
||||
len = 0;
|
||||
}
|
||||
if (data != nullptr) {
|
||||
std::memcpy(&tcData->appData, data, len);
|
||||
}
|
||||
if (updateSpLenField) {
|
||||
setPacketDataLength(calculateFullPacketLength(len) - sizeof(CCSDSPrimaryHeader) - 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,27 @@ class TcPacketPus : public TcPacketPusBase {
|
|||
*/
|
||||
TcPacketPus(const uint8_t* setData);
|
||||
|
||||
/**
|
||||
* Initializes the Tc Packet header.
|
||||
* @param apid APID used.
|
||||
* @param sequenceCount Sequence Count in the primary header.
|
||||
* @param ack Which acknowledeges are expected from the receiver.
|
||||
* @param service PUS Service
|
||||
* @param subservice PUS Subservice
|
||||
*/
|
||||
void initializeTcPacket(uint16_t apid, uint16_t sequenceCount, uint8_t ack, uint8_t service,
|
||||
uint8_t subservice, pus::PusVersion pusVersion, uint16_t sourceId = 0);
|
||||
/**
|
||||
* Set the application data field by copying the provided data to the application data field.
|
||||
* This function can also update the space packet length
|
||||
* field. To only update the SP length field with empty application data, simply pass 0 as
|
||||
* length of nullptr as data.
|
||||
* @param data
|
||||
* @param len
|
||||
* @param updateSpLenField
|
||||
*/
|
||||
void setApplicationData(const uint8_t* data, size_t len, bool updateSpLenField);
|
||||
|
||||
// Base class overrides
|
||||
uint8_t getSecondaryHeaderFlag() const override;
|
||||
uint8_t getPusVersionNumber() const override;
|
||||
|
@ -65,17 +86,6 @@ class TcPacketPus : public TcPacketPusBase {
|
|||
protected:
|
||||
ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize, void* args = nullptr) override;
|
||||
|
||||
/**
|
||||
* Initializes the Tc Packet header.
|
||||
* @param apid APID used.
|
||||
* @param sequenceCount Sequence Count in the primary header.
|
||||
* @param ack Which acknowledeges are expected from the receiver.
|
||||
* @param service PUS Service
|
||||
* @param subservice PUS Subservice
|
||||
*/
|
||||
void initializeTcPacket(uint16_t apid, uint16_t sequenceCount, uint8_t ack, uint8_t service,
|
||||
uint8_t subservice, pus::PusVersion pusVersion, uint16_t sourceId = 0);
|
||||
|
||||
/**
|
||||
* A pointer to a structure which defines the data structure of
|
||||
* the packet's data.
|
||||
|
|
|
@ -28,8 +28,7 @@ TcPacketStoredPus::TcPacketStoredPus(uint16_t apid, uint8_t service, uint8_t sub
|
|||
pus::PusVersion pusVersion = pus::PusVersion::PUS_A_VERSION;
|
||||
#endif
|
||||
initializeTcPacket(apid, sequenceCount, ack, service, subservice, pusVersion);
|
||||
std::memcpy(&tcData->appData, data, size);
|
||||
this->setPacketDataLength(size + sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1);
|
||||
this->setApplicationData(data, size, true);
|
||||
this->setErrorControl();
|
||||
}
|
||||
|
||||
|
|
|
@ -172,15 +172,18 @@ ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage* message) {
|
|||
}
|
||||
|
||||
if (tmFifo->full()) {
|
||||
if (warningSwitch) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number "
|
||||
"of stored packet IDs reached!"
|
||||
<< std::endl;
|
||||
sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number "
|
||||
"of stored packet IDs reached!"
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printWarning(
|
||||
"TmTcBridge::storeDownlinkData: TM downlink max. number "
|
||||
"of stored packet IDs reached!\n");
|
||||
sif::printWarning(
|
||||
"TmTcBridge::storeDownlinkData: TM downlink max. number "
|
||||
"of stored packet IDs reached!\n");
|
||||
#endif
|
||||
warningSwitch = true;
|
||||
}
|
||||
if (overwriteOld) {
|
||||
tmFifo->retrieve(&storeId);
|
||||
tmStore->deleteData(storeId);
|
||||
|
|
|
@ -72,6 +72,8 @@ class TmTcBridge : public AcceptsTelemetryIF,
|
|||
virtual uint16_t getIdentifier() override;
|
||||
virtual MessageQueueId_t getRequestQueue() override;
|
||||
|
||||
bool warningSwitch = true;
|
||||
|
||||
protected:
|
||||
//! Cached for initialize function.
|
||||
object_id_t tmStoreId = objects::NO_OBJECT;
|
||||
|
|
Loading…
Reference in New Issue
Block a user