Merge pull request 'Update FSFW' (#33) from mueller/master into eive/develop

Reviewed-on: eive/fsfw#33
This commit is contained in:
Jakob Meier 2022-02-21 11:00:17 +01:00
commit 19f8e41c7f
53 changed files with 631 additions and 183 deletions

View File

@ -1,4 +1,214 @@
# Changed from ASTP 1.1.0 to 1.2.0
Change Log
=======
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased]
# [v4.0.0]
## Additions
- CFDP Packet Stack and related tests added. It also refactors the existing TMTC infastructure to
allow sending of CFDP packets to the CCSDS handlers.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/528
- added virtual function to print datasets
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/544
- doSendRead Hook
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/545
- Dockumentation for DHB
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/551
### HAL additions
- Linux Command Executor, which can execute shell commands in blocking and non-blocking mode
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/536
- uio Mapper
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/543
## Changes
- Applied the `clang-format` auto-formatter to all source code
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/534
- Updated Catch2 to v3.0.0-preview4
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/538
- Changed CI to use prebuilt docker image
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/549
## Bugfix
- CMake fixes in PR https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/533 , was problematic
if the uppermost user `CMakeLists.txt` did not have the include paths set up properly, which
could lead to compile errors that `#include "fsfw/FSFW.h"` was not found.
- Fix for build regression in Catch2 v3.0.0-preview4
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/548
- Fix in unittest which failed on CI
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/552
- Fix in helper script
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/553
## API Changes
- Aforementioned changes to existing TMTC stack
## Known bugs
-
# [v3.0.1]
## API Changes
*
## Bugfixes
* Version number was not updated for v3.0.0 #542
## Enhancement
*
## Known bugs
*
# [v3.0.0]
## API Changes
#### TCP Socket Changes
* Keep Open TCP Implementation #496
* The socket will now kept open after disconnect. This allows reconnecting.
* Only one connection is allowed
* No internal influence but clients need to change their Code.
### GPIO IF
* Add feature to open GPIO by line name #506
### Bitutil
* Unittests for Op Divider and Bitutility #510
### Filesystem IF changed
* Filesystem Base Interface: Use IF instead of void pointer #511
### STM32
* STM32 SPI Updates #518
## Bugfixes
* Small bugfix for LIS3 handler #504
* Spelling fixed for function names #509
* CMakeLists fixes #517
* Out of bound reads and writes in unittests #519
* Bug in TmPacketStoredPusC (#478)
* Windows ifdef fixed #529
## Enhancement
* FSFW.h.in more default values #491
* Minor updates for PUS services #498
* HasReturnvaluesIF naming for parameter #499
* Tests can now be built as part of FSFW and versioning moved to CMake #500
* Added integration test code #508
* More printouts for rejected TC packets #505
* Arrayprinter format improvements #514
* Adding code for CI with docker and jenkins #520
* Added new function in SerializeAdapter #513
* Enables simple deSerialize if you keep track of the buffer position yourself
* `` static ReturnValue_t deSerialize(T *object, const uint8_t* buffer,
size_t* deserSize, SerializeIF::Endianness streamEndianness) ``
* Unittest helper scripts has a new Parameter to open the coverage html in the webrowser #525
* ``'-o', '--open', Open coverage data in webbrowser``
* Documentation updated. Sphinx Documentation can now be build with python script #526
## Known bugs
* Version number was not updated for v3.0.0 #542
All Pull Requests:
Milestone: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/milestone/19
# [v2.0.0]
## API Changes
### File Structure changed to fit more common structure
* See pull request (#445)
* HAL is now part of the main project
* **See Instructions below:**
#### Instruction how to update existing / user code
* Changes in `#include`:
* Rename `internalError` in includes to `internalerror`
* Rename `fsfw/hal` to `fsfw_hal`
* Rename `fsfw/tests` to `fsfw_tests`
* Rename `osal/FreeRTOS` to `osal/freertos`
* Changes in `CMakeLists.txt`:
* Rename `OS_FSFW` to `FSFW_OSAL`
* Changes in `DleEncoder.cpp`
* Create an instance of the `DleEncoder` first before calling the `encode` and `decode` functions
### Removed osal/linux/Timer (#486)
* Was redundant to timemanager/Countdown
#### Instruction how to update existing / user code
* Use timemanager/Countdown instead
## Bugfixes
### TM Stack
* Increased TM stack robustness by introducing `nullptr` checks and more printouts (#483)
#### Host OSAL / FreeRTOS
* QueueMapManager Bugfix (NO_QUEUE was used as MessageQueueId) (#444)
#### Events
* Event output is now consistent (#447)
#### DLE Encoder
* Fixed possible out of bounds access in DLE Encoder (#492)
## Enhancment
* HAL as major new feature, also includes three MEMS devicehandlers as part of #481
* Linux HAL updates (#456)
* FreeRTOS Header cleaning update and Cmake tweaks (#442)
* Printer updates (#453)
* New returnvalue for for empty PST (#485)
* TMTC Bridge: Increase limit of packets stored (#484)
## Known bugs
* Bug in TmPacketStoredPusC (#478)
All Pull Requests:
Milestone: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/milestone/5
# [v1.2.0]
## API Changes
@ -27,7 +237,7 @@
- See API changes chapter. This change will keep the internal API consistent in the future
# Changes from ASTP 1.0.0 to 1.1.0
# [v1.1.0]
## API Changes

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.13)
set(FSFW_VERSION 2)
set(FSFW_VERSION 4)
set(FSFW_SUBVERSION 0)
set(FSFW_REVISION 0)
@ -60,6 +60,8 @@ if(FSFW_BUILD_UNITTESTS)
)
FetchContent_MakeAvailable(Catch2)
#fixes regression -preview4, to be confirmed in later releases
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
endif()
set(FSFW_CONFIG_PATH tests/src/fsfw_tests/unit/testcfg)

View File

@ -107,6 +107,42 @@ cmake --build . -- fsfw-tests_coverage -j
The `coverage.py` script located in the `script` folder can also be used to do this conveniently.
## Building the documentations
The FSFW documentation is built using the tools Sphinx, doxygen and breathe based on the
instructions provided in [this blogpost](https://devblogs.microsoft.com/cppblog/clear-functional-c-documentation-with-sphinx-breathe-doxygen-cmake/). If you
want to do this locally, set up the prerequisites first. This requires a ``python3``
installation as well. Example here is for Ubuntu.
```sh
sudo apt-get install doxygen graphviz
```
And the following Python packages
```sh
python3 -m pip install sphinx breathe
```
You can set up a documentation build system using the following commands
```sh
mkdir build-docs && cd build-docs
cmake -DFSFW_BUILD_DOCS=ON -DFSFW_OSAL=host ..
```
Then you can generate the documentation using
```sh
cmake --build . -j
```
You can find the generated documentation inside the `docs/sphinx` folder inside the build
folder. Simply open the `index.html` in the webbrowser of your choice.
The `helper.py` script located in the script` folder can also be used to create, build
and open the documentation conveniently. Try `helper.py -h for more information.
## Formatting the sources
The formatting is done by the `clang-format` tool. The configuration is contained within the

View File

@ -6,9 +6,3 @@ RUN apt-get --yes upgrade
#tzdata is a dependency, won't install otherwise
ARG DEBIAN_FRONTEND=noninteractive
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-preview4 && \
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
cmake --build build/ --target install

View File

@ -3,13 +3,7 @@ pipeline {
BUILDDIR = 'build-tests'
}
agent {
dockerfile {
dir 'automation'
//force docker to redownload base image and rebuild all steps instead of caching them
//this way, we always get an up to date docker image one each build
additionalBuildArgs '--no-cache --pull'
reuseNode true
}
docker { image 'fsfw-ci:d1'}
}
stages {
stage('Clean') {

View File

@ -1,3 +1,110 @@
.. _dhb-prim-doc:
Device Handlers
==================
Device handler components represent, control and monitor equipment, for example sensors or actuators
of a spacecraft or the payload.
Most device handlers have the same common functionality or
requirements, which are fulfilled by implementing certain interfaces:
- The handler/device needs to be commandable: :cpp:class:`HasActionsIF`
- The handler needs to communicate with the physical device via a dedicated
communication bus, for example SpaceWire, UART or SPI: :cpp:class:`DeviceCommunicationIF`
- The handler has housekeeping data which has to be exposed to the operator and/or other software
components: :cpp:class:`HasLocalDataPoolIF`
- The handler has configurable parameters: :cpp:class:`ReceivesParameterMessagesIF` which
also implements :cpp:class:`HasParametersIF`
- The handler has health states, for example to indicate a broken device:
:cpp:class:`HasHealthIF`
- The handler has modes. For example there are the core modes `MODE_ON`, `MODE_OFF`
and `MODE_NORMAL` provided by the FSFW. `MODE_ON` means that a device is physically powered
but that it is not periodically polling data from the
physical device, `MODE_NORMAL` means that it is able to do that: :cpp:class:`HasModesIF`
The device handler base therefore provides abstractions for a lot of common
functionality, which can potentially avoid high amounts or logic and code duplication.
Template Device Handler Base File
----------------------------------
This is an example template device handler header file with all necessary
functions implemented:
.. code-block:: cpp
#ifndef __TESTDEVICEHANDLER_H_
#define __TESTDEVICEHANDLER_H_
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
class TestDeviceHandler: DeviceHandlerBase {
public:
TestDeviceHandler(object_id_t objectId, object_id_t comIF, CookieIF* cookie);
private:
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t* id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t* id) override;
void fillCommandAndReplyMap() override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t* commandData,
size_t commandDataLen) override;
ReturnValue_t scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId,
size_t* foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) override;
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
};
#endif /* __TESTDEVICEHANDLER_H_ */
and the respective source file with sensible default return values:
.. code-block:: cpp
#include "TestDeviceHandler.h"
TestDeviceHandler::TestDeviceHandler(object_id_t objectId, object_id_t comIF, CookieIF* cookie)
: DeviceHandlerBase(objectId, comIF, cookie) {}
void TestDeviceHandler::doStartUp() {}
void TestDeviceHandler::doShutDown() {}
ReturnValue_t TestDeviceHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t TestDeviceHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
return HasReturnvaluesIF::RETURN_OK;
}
void TestDeviceHandler::fillCommandAndReplyMap() {}
ReturnValue_t TestDeviceHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t* commandData,
size_t commandDataLen) {
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t TestDeviceHandler::scanForReply(const uint8_t* start, size_t remainingSize,
DeviceCommandId_t* foundId, size_t* foundLen) {
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t TestDeviceHandler::interpretDeviceReply(DeviceCommandId_t id,
const uint8_t* packet) {
return HasReturnvaluesIF::RETURN_OK;
}
uint32_t TestDeviceHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) {
return 10000;
}
ReturnValue_t TestDeviceHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -90,8 +90,21 @@ Building the documentation
----------------------------
The FSFW documentation is built using the tools Sphinx, doxygen and breathe based on the
instructions provided in `this blogpost <https://devblogs.microsoft.com/cppblog/clear-functional-c-documentation-with-sphinx-breathe-doxygen-cmake/>`_. You can set up a
documentation build system using the following commands
instructions provided in `this blogpost <https://devblogs.microsoft.com/cppblog/clear-functional-c-documentation-with-sphinx-breathe-doxygen-cmake/>`_. If you
want to do this locally, set up the prerequisites first. This requires a ``python3``
installation as well. Example here is for Ubuntu.
.. code-block:: console
sudo apt-get install doxygen graphviz
And the following Python packages
.. code-block:: console
python3 -m pip install sphinx breathe
You can set up a documentation build system using the following commands
.. code-block:: bash
@ -110,6 +123,14 @@ folder. Simply open the ``index.html`` in the webbrowser of your choice.
The ``helper.py`` script located in the ``script`` folder can also be used to create, build
and open the documentation conveniently. Try ``helper.py -h`` for more information.
Formatting the source
-----------------------
The formatting is done by the ``clang-format`` tool. The configuration is contained within the
``.clang-format`` file in the repository root. As long as ``clang-format`` is installed, you
can run the ``apply-clang-format.sh`` helper script to format all source files consistently.
.. _`Hosted FSFW example`: https://egit.irs.uni-stuttgart.de/fsfw/fsfw-example-hosted
.. _`Catch2 library`: https://github.com/catchorg/Catch2
.. _`Code coverage`: https://github.com/bilke/cmake-modules/tree/master

View File

@ -118,7 +118,7 @@ The DH has mechanisms to monitor the communication with the physical device whic
for FDIR reaction. Device Handlers can be created by implementing ``DeviceHandlerBase``.
A standard FDIR component for the DH will be created automatically but can
be overwritten by the user. More information on DeviceHandlers can be found in the
related [documentation section](doc/README-devicehandlers.md#top).
related :ref:`documentation section <dhb-prim-doc>`.
Modes and Health
--------------------

View File

@ -9,9 +9,6 @@ GyroHandlerL3GD20H::GyroHandlerL3GD20H(object_id_t objectId, object_id_t deviceC
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
transitionDelayMs(transitionDelayMs),
dataset(this) {
#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1
debugDivider = new PeriodicOperationDivider(10);
#endif
}
GyroHandlerL3GD20H::~GyroHandlerL3GD20H() {}
@ -193,22 +190,23 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id,
int8_t temperaturOffset = (-1) * packet[L3GD20H::TEMPERATURE_IDX];
float temperature = 25.0 + temperaturOffset;
#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1
if (debugDivider->checkAndIncrement()) {
/* Set terminal to utf-8 if there is an issue with micro printout. */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "GyroHandlerL3GD20H: Angular velocities (deg/s):" << std::endl;
sif::info << "X: " << angVelocX << std::endl;
sif::info << "Y: " << angVelocY << std::endl;
sif::info << "Z: " << angVelocZ << std::endl;
#else
sif::printInfo("GyroHandlerL3GD20H: Angular velocities (deg/s):\n");
sif::printInfo("X: %f\n", angVelocX);
sif::printInfo("Y: %f\n", angVelocY);
sif::printInfo("Z: %f\n", angVelocZ);
#endif
if(periodicPrintout) {
if (debugDivider.checkAndIncrement()) {
/* Set terminal to utf-8 if there is an issue with micro printout. */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "GyroHandlerL3GD20H: Angular velocities (deg/s):" << std::endl;
sif::info << "X: " << angVelocX << std::endl;
sif::info << "Y: " << angVelocY << std::endl;
sif::info << "Z: " << angVelocZ << std::endl;
#else
sif::printInfo("GyroHandlerL3GD20H: Angular velocities (deg/s):\n");
sif::printInfo("X: %f\n", angVelocX);
sif::printInfo("Y: %f\n", angVelocY);
sif::printInfo("Z: %f\n", angVelocZ);
#endif
}
}
#endif
PoolReadGuard readSet(&dataset);
if (readSet.getReadResult() == HasReturnvaluesIF::RETURN_OK) {
@ -272,3 +270,8 @@ void GyroHandlerL3GD20H::setAbsoluteLimits(float limitX, float limitY, float lim
this->absLimitY = limitY;
this->absLimitZ = limitZ;
}
void GyroHandlerL3GD20H::enablePeriodicPrintouts(bool enable, uint8_t divider) {
periodicPrintout = enable;
debugDivider.setDivider(divider);
}

View File

@ -1,12 +1,11 @@
#ifndef MISSION_DEVICES_GYROL3GD20HANDLER_H_
#define MISSION_DEVICES_GYROL3GD20HANDLER_H_
#include "devicedefinitions/GyroL3GD20Definitions.h"
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
#include "devicedefinitions/GyroL3GD20Definitions.h"
#include "fsfw/FSFW.h"
/**
* @brief Device Handler for the L3GD20H gyroscope sensor
* (https://www.st.com/en/mems-and-sensors/l3gd20h.html)
@ -22,6 +21,8 @@ class GyroHandlerL3GD20H : public DeviceHandlerBase {
uint32_t transitionDelayMs);
virtual ~GyroHandlerL3GD20H();
void enablePeriodicPrintouts(bool enable, uint8_t divider);
/**
* Set the absolute limit for the values on the axis in degrees per second.
* The dataset values will be marked as invalid if that limit is exceeded
@ -58,6 +59,7 @@ class GyroHandlerL3GD20H : public DeviceHandlerBase {
uint32_t transitionDelayMs = 0;
GyroPrimaryDataset dataset;
float absLimitX = L3GD20H::RANGE_DPS_00;
float absLimitY = L3GD20H::RANGE_DPS_00;
float absLimitZ = L3GD20H::RANGE_DPS_00;
@ -80,9 +82,8 @@ class GyroHandlerL3GD20H : public DeviceHandlerBase {
// Set default value
float sensitivity = L3GD20H::SENSITIVITY_00;
#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1
PeriodicOperationDivider *debugDivider = nullptr;
#endif
bool periodicPrintout = false;
PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3);
};
#endif /* MISSION_DEVICES_GYROL3GD20HANDLER_H_ */

View File

@ -12,9 +12,6 @@ MgmLIS3MDLHandler::MgmLIS3MDLHandler(object_id_t objectId, object_id_t deviceCom
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
dataset(this),
transitionDelay(transitionDelay) {
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
debugDivider = new PeriodicOperationDivider(10);
#endif
// Set to default values right away
registers[0] = MGMLIS3MDL::CTRL_REG1_DEFAULT;
registers[1] = MGMLIS3MDL::CTRL_REG2_DEFAULT;
@ -272,23 +269,25 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons
float mgmZ = static_cast<float>(mgmMeasurementRawZ) * sensitivityFactor *
MGMLIS3MDL::GAUSS_TO_MICROTESLA_FACTOR;
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
if (debugDivider->checkAndIncrement()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "MGMHandlerLIS3: Magnetic field strength in"
" microtesla:"
<< std::endl;
sif::info << "X: " << mgmX << " uT" << std::endl;
sif::info << "Y: " << mgmY << " uT" << std::endl;
sif::info << "Z: " << mgmZ << " uT" << std::endl;
#else
sif::printInfo("MGMHandlerLIS3: Magnetic field strength in microtesla:\n");
sif::printInfo("X: %f uT\n", mgmX);
sif::printInfo("Y: %f uT\n", mgmY);
sif::printInfo("Z: %f uT\n", mgmZ);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 0 */
if(periodicPrintout) {
if (debugDivider.checkAndIncrement()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "MGMHandlerLIS3: Magnetic field strength in"
" microtesla:"
<< std::endl;
sif::info << "X: " << mgmX << " uT" << std::endl;
sif::info << "Y: " << mgmY << " uT" << std::endl;
sif::info << "Z: " << mgmZ << " uT" << std::endl;
#else
sif::printInfo("MGMHandlerLIS3: Magnetic field strength in microtesla:\n");
sif::printInfo("X: %f uT\n", mgmX);
sif::printInfo("Y: %f uT\n", mgmY);
sif::printInfo("Z: %f uT\n", mgmZ);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 0 */
}
}
#endif /* OBSW_VERBOSE_LEVEL >= 1 */
PoolReadGuard readHelper(&dataset);
if (readHelper.getReadResult() == HasReturnvaluesIF::RETURN_OK) {
if (std::abs(mgmX) < absLimitX) {
@ -318,15 +317,16 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons
case MGMLIS3MDL::READ_TEMPERATURE: {
int16_t tempValueRaw = packet[2] << 8 | packet[1];
float tempValue = 25.0 + ((static_cast<float>(tempValueRaw)) / 8.0);
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
if (debugDivider->check()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "MGMHandlerLIS3: Temperature: " << tempValue << " C" << std::endl;
#else
sif::printInfo("MGMHandlerLIS3: Temperature: %f C\n");
#endif
if(periodicPrintout) {
if (debugDivider.check()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "MGMHandlerLIS3: Temperature: " << tempValue << " C" << std::endl;
#else
sif::printInfo("MGMHandlerLIS3: Temperature: %f C\n");
#endif
}
}
#endif
ReturnValue_t result = dataset.read();
if (result == HasReturnvaluesIF::RETURN_OK) {
dataset.temperature = tempValue;
@ -484,3 +484,9 @@ void MgmLIS3MDLHandler::setAbsoluteLimits(float xLimit, float yLimit, float zLim
this->absLimitY = yLimit;
this->absLimitZ = zLimit;
}
void MgmLIS3MDLHandler::enablePeriodicPrintouts(bool enable, uint8_t divider) {
periodicPrintout = enable;
debugDivider.setDivider(divider);
}

View File

@ -1,9 +1,10 @@
#ifndef MISSION_DEVICES_MGMLIS3MDLHANDLER_H_
#define MISSION_DEVICES_MGMLIS3MDLHANDLER_H_
#include "devicedefinitions/MgmLIS3HandlerDefs.h"
#include "events/subsystemIdRanges.h"
#include "fsfw/FSFW.h"
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
class PeriodicOperationDivider;
@ -30,6 +31,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
uint32_t transitionDelay);
virtual ~MgmLIS3MDLHandler();
void enablePeriodicPrintouts(bool enable, uint8_t divider);
/**
* Set the absolute limit for the values on the axis in microtesla. The dataset values will
* be marked as invalid if that limit is exceeded
@ -167,9 +169,8 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
*/
ReturnValue_t prepareCtrlRegisterWrite();
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
PeriodicOperationDivider *debugDivider;
#endif
bool periodicPrintout = false;
PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3);
};
#endif /* MISSION_DEVICES_MGMLIS3MDLHANDLER_H_ */

View File

@ -11,9 +11,6 @@ MgmRM3100Handler::MgmRM3100Handler(object_id_t objectId, object_id_t deviceCommu
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
primaryDataset(this),
transitionDelay(transitionDelay) {
#if FSFW_HAL_RM3100_MGM_DEBUG == 1
debugDivider = new PeriodicOperationDivider(10);
#endif
}
MgmRM3100Handler::~MgmRM3100Handler() {}
@ -337,23 +334,24 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) {
float fieldStrengthY = fieldStrengthRawY * scaleFactorX;
float fieldStrengthZ = fieldStrengthRawZ * scaleFactorX;
#if FSFW_HAL_RM3100_MGM_DEBUG == 1
if (debugDivider->checkAndIncrement()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "MgmRM3100Handler: Magnetic field strength in"
" microtesla:"
<< std::endl;
sif::info << "X: " << fieldStrengthX << " uT" << std::endl;
sif::info << "Y: " << fieldStrengthY << " uT" << std::endl;
sif::info << "Z: " << fieldStrengthZ << " uT" << std::endl;
#else
sif::printInfo("MgmRM3100Handler: Magnetic field strength in microtesla:\n");
sif::printInfo("X: %f uT\n", fieldStrengthX);
sif::printInfo("Y: %f uT\n", fieldStrengthY);
sif::printInfo("Z: %f uT\n", fieldStrengthZ);
#endif
if(periodicPrintout) {
if (debugDivider.checkAndIncrement()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "MgmRM3100Handler: Magnetic field strength in"
" microtesla:"
<< std::endl;
sif::info << "X: " << fieldStrengthX << " uT" << std::endl;
sif::info << "Y: " << fieldStrengthY << " uT" << std::endl;
sif::info << "Z: " << fieldStrengthZ << " uT" << std::endl;
#else
sif::printInfo("MgmRM3100Handler: Magnetic field strength in microtesla:\n");
sif::printInfo("X: %f uT\n", fieldStrengthX);
sif::printInfo("Y: %f uT\n", fieldStrengthY);
sif::printInfo("Z: %f uT\n", fieldStrengthZ);
#endif
}
}
#endif
// TODO: Sanity check on values?
PoolReadGuard readGuard(&primaryDataset);
@ -365,3 +363,8 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) {
}
return RETURN_OK;
}
void MgmRM3100Handler::enablePeriodicPrintouts(bool enable, uint8_t divider) {
periodicPrintout = enable;
debugDivider.setDivider(divider);
}

View File

@ -2,12 +2,8 @@
#define MISSION_DEVICES_MGMRM3100HANDLER_H_
#include "devicedefinitions/MgmRM3100HandlerDefs.h"
#include "fsfw/FSFW.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#if FSFW_HAL_RM3100_MGM_DEBUG == 1
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"
#endif
/**
* @brief Device Handler for the RM3100 geomagnetic magnetometer sensor
@ -33,6 +29,7 @@ class MgmRM3100Handler : public DeviceHandlerBase {
uint32_t transitionDelay);
virtual ~MgmRM3100Handler();
void enablePeriodicPrintouts(bool enable, uint8_t divider);
/**
* Configure device handler to go to normal mode after startup immediately
* @param enable
@ -98,9 +95,9 @@ class MgmRM3100Handler : public DeviceHandlerBase {
size_t commandDataLen);
ReturnValue_t handleDataReadout(const uint8_t *packet);
#if FSFW_HAL_RM3100_MGM_DEBUG == 1
PeriodicOperationDivider *debugDivider;
#endif
bool periodicPrintout = false;
PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3);
};
#endif /* MISSION_DEVICEHANDLING_MGMRM3100HANDLER_H_ */

View File

@ -22,7 +22,7 @@ ReturnValue_t UioMapper::getMappedAdress(uint32_t** address, Permissions permiss
int fd = open(uioFile.c_str(), O_RDWR);
if (fd < 1) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "PtmeAxiConfig::initialize: Invalid UIO device file" << std::endl;
sif::error << "PtmeAxiConfig::initialize: Invalid UIO device file" << std::endl;
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
@ -36,8 +36,8 @@ ReturnValue_t UioMapper::getMappedAdress(uint32_t** address, Permissions permiss
if (*address == MAP_FAILED) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UioMapper::getMappedAdress: Failed to map physical address of uio device "
<< uioFile.c_str() << " and map" << static_cast<int>(mapNum) << std::endl;
sif::error << "UioMapper::getMappedAdress: Failed to map physical address of uio device "
<< uioFile.c_str() << " and map" << static_cast<int>(mapNum) << std::endl;
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
@ -52,7 +52,7 @@ ReturnValue_t UioMapper::getMapSize(size_t* size) {
fp = fopen(namestream.str().c_str(), "r");
if (fp == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UioMapper::getMapSize: Failed to open file " << namestream.str() << std::endl;
sif::error << "UioMapper::getMapSize: Failed to open file " << namestream.str() << std::endl;
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
@ -60,11 +60,12 @@ ReturnValue_t UioMapper::getMapSize(size_t* size) {
int items = fscanf(fp, "%s", hexstring);
if (items != 1) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UioMapper::getMapSize: Failed with error code " << errno
<< " to read size "
"string from file "
<< namestream.str() << std::endl;
sif::error << "UioMapper::getMapSize: Failed with error code " << errno
<< " to read size "
"string from file "
<< namestream.str() << std::endl;
#endif
fclose(fp);
return HasReturnvaluesIF::RETURN_FAILED;
}
uint32_t sizeTmp = 0;
@ -74,9 +75,10 @@ ReturnValue_t UioMapper::getMapSize(size_t* size) {
}
if (items != 1) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UioMapper::getMapSize: Failed with error code " << errno << "to convert "
<< "size of map" << mapNum << " to integer" << std::endl;
sif::error << "UioMapper::getMapSize: Failed with error code " << errno << "to convert "
<< "size of map" << mapNum << " to integer" << std::endl;
#endif
fclose(fp);
return HasReturnvaluesIF::RETURN_FAILED;
}
fclose(fp);

View File

@ -143,7 +143,10 @@ def handle_tests_type(args, build_dir_list: list):
if which("valgrind") is None:
print("Please install valgrind first")
sys.exit(1)
os.chdir(UNITTEST_FOLDER_NAME)
if os.path.split(os.getcwd())[1] != UNITTEST_FOLDER_NAME:
# If we are in a different directory we try to switch into it but
# this might fail
os.chdir(UNITTEST_FOLDER_NAME)
os.system("valgrind --leak-check=full ./fsfw-tests")
os.chdir("..")

View File

@ -62,16 +62,4 @@
#define FSFW_HAL_I2C_WIRETAPPING 0
#endif
#ifndef FSFW_HAL_L3GD20_GYRO_DEBUG
#define FSFW_HAL_L3GD20_GYRO_DEBUG 0
#endif /* FSFW_HAL_L3GD20_GYRO_DEBUG */
#ifndef FSFW_HAL_RM3100_MGM_DEBUG
#define FSFW_HAL_RM3100_MGM_DEBUG 0
#endif /* FSFW_HAL_RM3100_MGM_DEBUG */
#ifndef FSFW_HAL_LIS3MDL_MGM_DEBUG
#define FSFW_HAL_LIS3MDL_MGM_DEBUG 0
#endif /* FSFW_HAL_LIS3MDL_MGM_DEBUG */
#endif /* FSFW_FSFW_H_ */

View File

@ -12,7 +12,9 @@ object_id_t CFDPHandler::packetDestination = 0;
CFDPHandler::CFDPHandler(object_id_t setObjectId, CFDPDistributor* dist)
: SystemObject(setObjectId) {
requestQueue = QueueFactory::instance()->createMessageQueue(CFDP_HANDLER_MAX_RECEPTION);
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
requestQueue = QueueFactory::instance()->createMessageQueue(CFDP_HANDLER_MAX_RECEPTION,
MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
distributor = dist;
}

View File

@ -13,7 +13,9 @@ ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
submode(SUBMODE_NONE),
modeHelper(this),
healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth,
MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }

View File

@ -39,8 +39,9 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
childTransitionDelay(5000),
transitionSourceMode(_MODE_POWER_DOWN),
transitionSourceSubMode(SUBMODE_NONE) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE);
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
insertInCommandMap(RAW_COMMAND_ID);
cookieInfo.state = COOKIE_UNUSED;
cookieInfo.pendingCommand = deviceCommandMap.end();

View File

@ -8,7 +8,8 @@ HealthDevice::HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue
parentQueue(parentQueue),
commandQueue(),
healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(3);
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
HealthDevice::~HealthDevice() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }

View File

@ -18,8 +18,10 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
EventManager::EventManager(object_id_t setObjectId)
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
eventReportQueue = QueueFactory::instance()->createMessageQueue(MAX_EVENTS_PER_CYCLE,
EventMessage::EVENT_MESSAGE_SIZE);
EventMessage::EVENT_MESSAGE_SIZE,
&mqArgs);
}
EventManager::~EventManager() {
@ -46,9 +48,20 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
void EventManager::notifyListeners(EventMessage* message) {
lockMutex();
for (auto iter = listenerList.begin(); iter != listenerList.end(); ++iter) {
if (iter->second.match(message)) {
MessageQueueSenderIF::sendMessage(iter->first, message, message->getSender());
for (auto& listener : listenerList) {
if (listener.second.match(message)) {
ReturnValue_t result =
MessageQueueSenderIF::sendMessage(listener.first, message, message->getSender());
if (result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0')
<< std::setw(8) << listener.first << " failed with result 0x" << std::setw(4)
<< result << std::setfill(' ') << std::endl;
#else
sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
listener.first, result);
#endif
}
}
}
unlockMutex();
@ -189,4 +202,19 @@ void EventManager::printUtility(sif::OutputTypes printType, EventMessage* messag
}
}
void EventManager::printListeners() {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Event manager listener MQ IDs:" << std::setfill('0') << std::hex << std::endl;
for (auto& listener : listenerList) {
sif::info << "0x" << std::setw(8) << listener.first << std::endl;
}
sif::info << std::dec << std::setfill(' ');
#else
sif::printInfo("Event manager listener MQ IDs:\n");
for (auto& listener : listenerList) {
sif::printInfo("0x%08x\n", listener.first);
}
#endif
}
#endif /* FSFW_OBJ_EVENT_TRANSLATION == 1 */

View File

@ -42,6 +42,7 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
bool reporterInverted = false);
ReturnValue_t performOperation(uint8_t opCode);
void printListeners();
protected:
MessageQueueIF* eventReportQueue = nullptr;

View File

@ -9,8 +9,9 @@
FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent,
uint8_t messageDepth, uint8_t parameterDomainBase)
: ownerId(owner), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) {
auto mqArgs = MqArgs(owner, static_cast<void*>(this));
eventQueue =
QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE);
QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
}
FailureIsolationBase::~FailureIsolationBase() {

View File

@ -7,11 +7,12 @@
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
: SystemObject(setObjectId),
commandQueue(QueueFactory::instance()->createMessageQueue(messageQueueDepth)),
poolManager(this, commandQueue),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) {
mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); }
@ -36,15 +37,14 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
if ((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "InternalErrorReporter::performOperation: Errors "
<< "occured!" << std::endl;
sif::debug << "Queue errors: " << newQueueHits << std::endl;
sif::debug << "TM errors: " << newTmHits << std::endl;
sif::debug << "Store errors: " << newStoreHits << std::endl;
<< "occured: Queue | TM | Store : " << newQueueHits << " | " << newTmHits << " | "
<< newStoreHits << std::endl;
#else
sif::printDebug("InternalErrorReporter::performOperation: Errors occured!\n");
sif::printDebug("Queue errors: %lu\n", static_cast<unsigned int>(newQueueHits));
sif::printDebug("TM errors: %lu\n", static_cast<unsigned int>(newTmHits));
sif::printDebug("Store errors: %lu\n", static_cast<unsigned int>(newStoreHits));
sif::printDebug(
"InternalErrorReporter::performOperation: Errors occured: Queue | TM | Store: %lu | %lu "
"| %lu\n",
static_cast<unsigned int>(newQueueHits), static_cast<unsigned int>(newTmHits),
static_cast<unsigned int>(newStoreHits));
#endif
}
}

View File

@ -5,6 +5,7 @@
#include "MessageQueueIF.h"
#include "MessageQueueMessage.h"
#include "definitions.h"
/**
* Creates message queues.
@ -22,7 +23,8 @@ class QueueFactory {
static QueueFactory* instance();
MessageQueueIF* createMessageQueue(uint32_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
void deleteMessageQueue(MessageQueueIF* queue);

View File

@ -0,0 +1,12 @@
#ifndef FSFW_SRC_FSFW_IPC_DEFINITIONS_H_
#define FSFW_SRC_FSFW_IPC_DEFINITIONS_H_
#include <fsfw/objectmanager/SystemObjectIF.h>
struct MqArgs {
MqArgs(){};
MqArgs(object_id_t objectId, void* args = nullptr) : objectId(objectId), args(args) {}
object_id_t objectId = 0;
void* args = nullptr;
};
#endif /* FSFW_SRC_FSFW_IPC_DEFINITIONS_H_ */

View File

@ -4,7 +4,7 @@
#include "fsfw/osal/freertos/QueueMapManager.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* args)
: maxMessageSize(maxMessageSize) {
handle = xQueueCreate(messageDepth, maxMessageSize);
if (handle == nullptr) {

View File

@ -7,6 +7,7 @@
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/MessageQueueMessageIF.h"
#include "fsfw/ipc/definitions.h"
#include "queue.h"
/**
@ -53,7 +54,8 @@ class MessageQueue : public MessageQueueIF {
* This should be left default.
*/
MessageQueue(size_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
/** Copying message queues forbidden */
MessageQueue(const MessageQueue&) = delete;

View File

@ -22,8 +22,9 @@ QueueFactory::QueueFactory() {}
QueueFactory::~QueueFactory() {}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
return new MessageQueue(messageDepth, maxMessageSize);
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
MqArgs* args) {
return new MessageQueue(messageDepth, maxMessageSize, args);
}
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }

View File

@ -8,7 +8,7 @@
#include "fsfw/osal/host/QueueMapManager.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* args)
: messageSize(maxMessageSize), messageDepth(messageDepth) {
queueLock = MutexFactory::instance()->createMutex();
auto result = QueueMapManager::instance()->addMessageQueue(this, &mqId);

View File

@ -8,6 +8,7 @@
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/MutexIF.h"
#include "fsfw/ipc/definitions.h"
#include "fsfw/timemanager/Clock.h"
/**
@ -54,7 +55,8 @@ class MessageQueue : public MessageQueueIF {
* This should be left default.
*/
MessageQueue(size_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
/** Copying message queues forbidden */
MessageQueue(const MessageQueue&) = delete;

View File

@ -27,12 +27,13 @@ QueueFactory::QueueFactory() {}
QueueFactory::~QueueFactory() {}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
MqArgs* args) {
// A thread-safe queue can be implemented by using a combination
// of std::queue and std::mutex. This uses dynamic memory allocation
// which could be alleviated by using a custom allocator, external library
// (etl::queue) or simply using std::queue, we're on a host machine anyway.
return new MessageQueue(messageDepth, maxMessageSize);
return new MessageQueue(messageDepth, maxMessageSize, args);
}
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }

View File

@ -11,7 +11,7 @@
#include "fsfw/osal/linux/unixUtility.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize)
MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs* args)
: id(MessageQueueIF::NO_QUEUE),
lastPartner(MessageQueueIF::NO_QUEUE),
defaultDestination(MessageQueueIF::NO_QUEUE),
@ -37,6 +37,9 @@ MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize)
// Successful mq_open call
this->id = tempId;
}
if (args != nullptr) {
this->mqArgs = *args;
}
}
MessageQueue::~MessageQueue() {
@ -240,9 +243,9 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
bool ignoreFault) {
if (message == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message is nullptr!" << std::endl;
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message is nullptr" << std::endl;
#else
sif::printError("MessageQueue::sendMessageFromMessageQueue: Message is nullptr!\n");
sif::printError("MessageQueue::sendMessageFromMessageQueue: Message is nullptr\n");
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
@ -256,7 +259,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
if (!ignoreFault) {
InternalErrorReporterIF* internalErrorReporter =
ObjectManager::instance()->get<InternalErrorReporterIF>(objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != NULL) {
if (internalErrorReporter != nullptr) {
internalErrorReporter->queueMessageNotSent();
}
}

View File

@ -6,6 +6,7 @@
#include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/definitions.h"
/**
* @brief This class manages sending and receiving of message queue messages.
*
@ -42,7 +43,8 @@ class MessageQueue : public MessageQueueIF {
* This should be left default.
*/
MessageQueue(uint32_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
/**
* @brief The destructor deletes the formerly created message queue.
* @details This is accomplished by using the delete call provided by the operating system.
@ -184,6 +186,8 @@ class MessageQueue : public MessageQueueIF {
*/
char name[16];
MqArgs mqArgs = {};
static uint16_t queueCounter;
const size_t maxMessageSize;

View File

@ -28,8 +28,9 @@ QueueFactory::QueueFactory() {}
QueueFactory::~QueueFactory() {}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
return new MessageQueue(messageDepth, maxMessageSize);
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
MqArgs* args) {
return new MessageQueue(messageDepth, maxMessageSize, args);
}
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }

View File

@ -6,7 +6,7 @@
#include "fsfw/osal/rtems/RtemsBasic.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size)
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size, MqArgs* args)
: id(0), lastPartner(0), defaultDestination(NO_QUEUE), internalErrorReporter(nullptr) {
rtems_name name = ('Q' << 24) + (queueCounter++ << 8);
rtems_status_code status =

View File

@ -5,6 +5,7 @@
#include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/definitions.h"
/**
* @brief This class manages sending and receiving of message queue messages.
@ -34,7 +35,8 @@ class MessageQueue : public MessageQueueIF {
* This should be left default.
*/
MessageQueue(size_t message_depth = 3,
size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
/**
* @brief The destructor deletes the formerly created message queue.
* @details This is accomplished by using the delete call provided by the operating system.

View File

@ -49,8 +49,9 @@ QueueFactory::QueueFactory() {}
QueueFactory::~QueueFactory() {}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
return new MessageQueue(messageDepth, maxMessageSize);
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
MqArgs* args) {
return new MessageQueue(messageDepth, maxMessageSize, args);
}
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }

View File

@ -15,7 +15,8 @@ PowerSensor::PowerSensor(object_id_t objectId, sid_t setId, VariableIds ids, Def
limits.currentMin, limits.currentMax, events.currentLow, events.currentHigh),
voltageLimit(objectId, MODULE_ID_VOLTAGE, ids.pidVoltage, confirmationCount,
limits.voltageMin, limits.voltageMax, events.voltageLow, events.voltageHigh) {
commandQueue = QueueFactory::instance()->createMessageQueue();
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
PowerSensor::~PowerSensor() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }

View File

@ -16,7 +16,8 @@ Service1TelecommandVerification::Service1TelecommandVerification(object_id_t obj
apid(apid),
serviceId(serviceId),
targetDestination(targetDestination) {
tmQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
tmQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
Service1TelecommandVerification::~Service1TelecommandVerification() {

View File

@ -12,7 +12,9 @@ Service5EventReporting::Service5EventReporting(object_id_t objectId, uint16_t ap
uint32_t messageQueueDepth)
: PusServiceBase(objectId, apid, serviceId),
maxNumberReportsPerCycle(maxNumberReportsPerCycle) {
eventQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
eventQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
sif::info << eventQueue->getId() << std::endl;
}
Service5EventReporting::~Service5EventReporting() {

View File

@ -8,11 +8,13 @@ SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent, Mode_t
uint16_t commandQueueDepth)
: SystemObject(setObjectId),
mode(initialMode),
commandQueue(QueueFactory::instance()->createMessageQueue(commandQueueDepth,
CommandMessage::MAX_MESSAGE_SIZE)),
healthHelper(this, setObjectId),
modeHelper(this),
parentId(parent) {}
parentId(parent) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth,
CommandMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }

View File

@ -5,7 +5,8 @@
#include "fsfw/tmtcservices/TmTcMessage.h"
TcDistributor::TcDistributor(object_id_t objectId) : SystemObject(objectId) {
tcQueue = QueueFactory::instance()->createMessageQueue(DISTRIBUTER_MAX_PACKETS);
auto mqArgs = MqArgs(objectId);
tcQueue = QueueFactory::instance()->createMessageQueue(DISTRIBUTER_MAX_PACKETS, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
TcDistributor::~TcDistributor() { QueueFactory::instance()->deleteMessageQueue(tcQueue); }

View File

@ -5,13 +5,13 @@
AbstractTemperatureSensor::AbstractTemperatureSensor(object_id_t setObjectid,
ThermalModuleIF *thermalModule)
: SystemObject(setObjectid),
commandQueue(NULL),
healthHelper(this, setObjectid),
parameterHelper(this) {
if (thermalModule != NULL) {
if (thermalModule != nullptr) {
thermalModule->registerSensor(this);
}
commandQueue = QueueFactory::instance()->createMessageQueue();
auto mqArgs = MqArgs(setObjectid, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
AbstractTemperatureSensor::~AbstractTemperatureSensor() {

View File

@ -51,7 +51,7 @@ class AbstractTemperatureSensor : public HasHealthIF,
HasHealthIF::HealthState getHealth();
protected:
MessageQueueIF* commandQueue;
MessageQueueIF* commandQueue = nullptr;
HealthHelper healthHelper;
ParameterHelper parameterHelper;

View File

@ -12,7 +12,8 @@ Heater::Heater(uint32_t objectId, uint8_t switch0, uint8_t switch1)
switch1(switch1),
heaterOnCountdown(10800000) /*about two orbits*/,
parameterHelper(this) {
eventQueue = QueueFactory::instance()->createMessageQueue();
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
eventQueue = QueueFactory::instance()->createMessageQueue(3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
Heater::~Heater() { QueueFactory::instance()->deleteMessageQueue(eventQueue); }

View File

@ -20,8 +20,10 @@ CommandingServiceBase::CommandingServiceBase(object_id_t setObjectId, uint16_t a
service(service),
timeoutSeconds(commandTimeoutSeconds),
commandMap(numberOfParallelCommands) {
commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth);
requestQueue = QueueFactory::instance()->createMessageQueue(queueDepth);
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
size_t mqSz = MessageQueueMessage::MAX_MESSAGE_SIZE;
commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth, mqSz, &mqArgs);
requestQueue = QueueFactory::instance()->createMessageQueue(queueDepth, mqSz, &mqArgs);
}
void CommandingServiceBase::setPacketSource(object_id_t packetSource) {

View File

@ -13,7 +13,8 @@ object_id_t PusServiceBase::packetDestination = 0;
PusServiceBase::PusServiceBase(object_id_t setObjectId, uint16_t setApid, uint8_t setServiceId)
: SystemObject(setObjectId), apid(setApid), serviceId(setServiceId) {
requestQueue = QueueFactory::instance()->createMessageQueue(PUS_SERVICE_MAX_RECEPTION);
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
requestQueue = QueueFactory::instance()->createMessageQueue(PUS_SERVICE_MAX_RECEPTION, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
PusServiceBase::~PusServiceBase() { QueueFactory::instance()->deleteMessageQueue(requestQueue); }

View File

@ -15,7 +15,8 @@ TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination, object_i
tcDestination(tcDestination)
{
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH);
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); }

View File

@ -3,7 +3,6 @@
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
bool TestTask::oneShotAction = true;
MutexIF* TestTask::testLock = nullptr;
TestTask::TestTask(object_id_t objectId) : SystemObject(objectId), testMode(testModes::A) {

View File

@ -29,7 +29,7 @@ class TestTask : public SystemObject, public ExecutableObjectIF, public HasRetur
bool testFlag = false;
private:
static bool oneShotAction;
bool oneShotAction = true;
static MutexIF* testLock;
StorageManagerIF* IPCStore;
};

View File

@ -45,7 +45,7 @@ TEST_CASE("Command Executor", "[cmd-exec]") {
result = cmdExecutor.check(bytesHaveBeenRead);
REQUIRE(result != CommandExecutor::COMMAND_ERROR);
usleep(500);
REQUIRE(limitIdx < 5);
REQUIRE(limitIdx < 500);
}
limitIdx = 0;
@ -71,8 +71,9 @@ TEST_CASE("Command Executor", "[cmd-exec]") {
limitIdx++;
result = cmdExecutor.check(bytesHaveBeenRead);
REQUIRE(result != CommandExecutor::COMMAND_ERROR);
// This ensures that the tests do not block indefinitely
usleep(500);
REQUIRE(limitIdx < 20);
REQUIRE(limitIdx < 500);
}
limitIdx = 0;
CHECK(bytesHaveBeenRead == true);
@ -89,7 +90,7 @@ TEST_CASE("Command Executor", "[cmd-exec]") {
std::string allTheReply(reinterpret_cast<char*>(largerReadBuffer));
// I am just going to assume that this string is the same across ping implementations
// of different Linux systems
REQUIRE(allTheReply.find("localhost ping statistics") != std::string::npos);
REQUIRE(allTheReply.find("PING localhost") != std::string::npos);
// Now check failing command
result = cmdExecutor.load("false", false, false);
@ -101,8 +102,9 @@ TEST_CASE("Command Executor", "[cmd-exec]") {
limitIdx++;
result = cmdExecutor.check(bytesHaveBeenRead);
REQUIRE(result != CommandExecutor::COMMAND_ERROR);
// This ensures that the tests do not block indefinitely
usleep(500);
REQUIRE(limitIdx < 20);
REQUIRE(limitIdx < 500);
}
REQUIRE(result == HasReturnvaluesIF::RETURN_FAILED);
REQUIRE(cmdExecutor.getLastError() == 1);