diff --git a/CHANGELOG.md b/CHANGELOG.md
index cda8037cd..335c0f7bb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
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
@@ -43,6 +45,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
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
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 19fedb64a..79258db2d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,8 +1,8 @@
cmake_minimum_required(VERSION 3.13)
-set(FSFW_VERSION 3)
+set(FSFW_VERSION 4)
set(FSFW_SUBVERSION 0)
-set(FSFW_REVISION 1)
+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})
diff --git a/README.md b/README.md
index a2261c990..89a10f4bb 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/docs/devicehandlers.rst b/docs/devicehandlers.rst
index 80b9e7a3c..0008edb37 100644
--- a/docs/devicehandlers.rst
+++ b/docs/devicehandlers.rst
@@ -14,7 +14,8 @@ requirements, which are fulfilled by implementing certain interfaces:
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
+- 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`
diff --git a/docs/getting_started.rst b/docs/getting_started.rst
index 069e98cde..34547211e 100644
--- a/docs/getting_started.rst
+++ b/docs/getting_started.rst
@@ -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 `_. You can set up a
-documentation build system using the following commands
+instructions provided in `this blogpost `_. 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
diff --git a/hal/src/fsfw_hal/linux/uio/UioMapper.cpp b/hal/src/fsfw_hal/linux/uio/UioMapper.cpp
index 33c1b0f24..43ca27278 100644
--- a/hal/src/fsfw_hal/linux/uio/UioMapper.cpp
+++ b/hal/src/fsfw_hal/linux/uio/UioMapper.cpp
@@ -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(mapNum) << std::endl;
+ sif::error << "UioMapper::getMappedAdress: Failed to map physical address of uio device "
+ << uioFile.c_str() << " and map" << static_cast(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);
diff --git a/scripts/helper.py b/scripts/helper.py
index 4e8a62b49..68693c40f 100755
--- a/scripts/helper.py
+++ b/scripts/helper.py
@@ -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("..")
diff --git a/src/fsfw/globalfunctions/CRC.cpp b/src/fsfw/globalfunctions/CRC.cpp
index 033920d0f..6b8140c52 100644
--- a/src/fsfw/globalfunctions/CRC.cpp
+++ b/src/fsfw/globalfunctions/CRC.cpp
@@ -117,7 +117,7 @@ uint16_t CRC::crc16ccitt(uint8_t const input[], uint32_t length, uint16_t starti
// {
// if (xor_out[i] == true)
// crc_value = crc_value + pow(2,(15 -i)); // reverse CrC result before
- // Final XOR
+ //Final XOR
// }
//
// crc_value = 0;// for debug mode
diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.h b/src/fsfw/osal/linux/PeriodicPosixTask.h
index 1c3a52c7e..3c9a3a0d7 100644
--- a/src/fsfw/osal/linux/PeriodicPosixTask.h
+++ b/src/fsfw/osal/linux/PeriodicPosixTask.h
@@ -65,10 +65,9 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
/**
* @brief The function containing the actual functionality of the task.
* @details The method sets and starts
- * the task's period, then enters a loop that is repeated indefinitely. Within
- * the loop, all performOperation methods of the added objects are called. Afterwards the task
- * will be blocked until the next period. On missing the deadline, the deadlineMissedFunction is
- * executed.
+ * the task's period, then enters a loop that is repeated indefinitely. Within the
+ * loop, all performOperation methods of the added objects are called. Afterwards the task will be
+ * blocked until the next period. On missing the deadline, the deadlineMissedFunction is executed.
*/
virtual void taskFunctionality(void);
/**
diff --git a/src/fsfw/osal/rtems/PeriodicTask.h b/src/fsfw/osal/rtems/PeriodicTask.h
index 119329f2a..ff8617fca 100644
--- a/src/fsfw/osal/rtems/PeriodicTask.h
+++ b/src/fsfw/osal/rtems/PeriodicTask.h
@@ -13,8 +13,8 @@ class ExecutableObjectIF;
* @brief This class represents a specialized task for periodic activities of multiple objects.
*
* @details MultiObjectTask is an extension to ObjectTask in the way that it is able to execute
- * multiple objects that implement the ExecutableObjectIF interface. The
- * objects must be added prior to starting the task.
+ * multiple objects that implement the ExecutableObjectIF interface. The objects
+ * must be added prior to starting the task.
* @author baetz
* @ingroup task_handling
*/
diff --git a/src/fsfw/rmap/RMAP.h b/src/fsfw/rmap/RMAP.h
index d274fb159..42ee1ac5d 100644
--- a/src/fsfw/rmap/RMAP.h
+++ b/src/fsfw/rmap/RMAP.h
@@ -169,8 +169,8 @@ class RMAP : public HasReturnvaluesIF {
* @param buffer the data to write
* @param length length of data
* @return
- * - @c COMMAND_NULLPOINTER datalen was != 0 but data was ==
- * NULL in write command
+ * - @c COMMAND_NULLPOINTER datalen was != 0 but data was == NULL in
+ * write command
* - return codes of RMAPChannelIF::sendCommand()
*/
static ReturnValue_t sendWriteCommand(RMAPCookie *cookie, const uint8_t *buffer, size_t length);
@@ -205,8 +205,8 @@ class RMAP : public HasReturnvaluesIF {
* @param cookie to cookie to read from
* @param expLength the expected maximum length of the reply
* @return
- * - @c COMMAND_NULLPOINTER datalen was != 0 but data was ==
- * NULL in write command, or nullpointer in read command
+ * - @c COMMAND_NULLPOINTER datalen was != 0 but data was == NULL in
+ * write command, or nullpointer in read command
* - return codes of RMAPChannelIF::sendCommand()
*/
static ReturnValue_t sendReadCommand(RMAPCookie *cookie, uint32_t expLength);
diff --git a/src/fsfw/rmap/RMAPChannelIF.h b/src/fsfw/rmap/RMAPChannelIF.h
index 0c937dc82..20dfd5f80 100644
--- a/src/fsfw/rmap/RMAPChannelIF.h
+++ b/src/fsfw/rmap/RMAPChannelIF.h
@@ -75,10 +75,10 @@ class RMAPChannelIF {
* - @c RETURN_OK
* - @c COMMAND_NO_DESCRIPTORS_AVAILABLE no descriptors available for sending
* command; command was not sent
- * - @c COMMAND_BUFFER_FULL no receiver buffer available for
- * expected len; command was not sent
- * - @c COMMAND_TOO_BIG the data that was to be sent was too long for
- * the hw to handle (write command) or the expected len was bigger than maximal expected len (read
+ * - @c COMMAND_BUFFER_FULL no receiver buffer available for expected len;
+ * command was not sent
+ * - @c COMMAND_TOO_BIG the data that was to be sent was too long for the hw
+ * to handle (write command) or the expected len was bigger than maximal expected len (read
* command) command was not sent
* - @c COMMAND_CHANNEL_DEACTIVATED the channel has no port set
* - @c NOT_SUPPORTED if you dont feel like
@@ -97,8 +97,8 @@ class RMAPChannelIF {
* - @c REPLY_NO_REPLY no reply was received
* - @c REPLY_NOT_SENT command was not sent, implies no reply
* - @c REPLY_NOT_YET_SENT command is still waiting to be sent
- * - @c WRITE_REPLY_INTERFACE_BUSY Interface is busy (transmission
- * buffer still being processed)
+ * - @c WRITE_REPLY_INTERFACE_BUSY Interface is busy (transmission buffer still
+ * being processed)
* - @c WRITE_REPLY_TRANSMISSION_ERROR Interface encountered errors during last
* operation, data could not be processed. (transmission error)
* - @c WRITE_REPLY_INVALID_DATA Invalid data (amount / value)
diff --git a/tests/src/fsfw_tests/unit/hal/testCommandExecutor.cpp b/tests/src/fsfw_tests/unit/hal/testCommandExecutor.cpp
index d2a15137b..3ad26876c 100644
--- a/tests/src/fsfw_tests/unit/hal/testCommandExecutor.cpp
+++ b/tests/src/fsfw_tests/unit/hal/testCommandExecutor.cpp
@@ -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(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);