diff --git a/.gitignore b/.gitignore index d6efb9cf..eb461072 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,14 @@ +# PyCharm and CLion +/.idea/* +!/.idea/runConfigurations +!/.idea/cmake.xml +!/.idea/codeStyles + +# Eclipse .cproject .project .settings .metadata /build* +/cmake-build* diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 00000000..0f3b1a4b --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..79ee123c --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 5181a862..66e8c0d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,32 +8,347 @@ and this project adheres to [Semantic Versioning](http://semver.org/). # [unreleased] -# [v5.0.0] +## Fixes + +- The `PusTmCreator` API only accepted 255 bytes of source data. It can now accept source + data with a size limited only by the size of `size_t`. +- Important bugfix in CFDP PDU header format: The entity length field and the transaction sequence + number fields stored the actual length of the field instead of the length minus 1 like specified + in the CFDP standard. +- PUS Health Service: Size check for set health command. + Perform operation completion for announce health command. + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/746 +- Linux OSAL `getUptime` fix: Check validity of `/proc/uptime` file before reading uptime. + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/745 +- Small tweak for version getter + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/744 + +## Added + +- add CFDP subsystem ID + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742 + +## Changed +- Bump ETL version to 20.35.14 + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/748 +- Renamed `PCDU_2` subsystem ID to `POWER_SWITCH_IF`. + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743 +- Add new `PowerSwitchIF::SWITCH_UNKNOWN` returnvalue. + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743 +- Assert that `FixedArrayList` is larger than 0 at compile time. + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/740 + +## Added + +- `EventManager`: Add function to print all listeners. + +## Changed + +- `EventManager`: Queue depth is configurable now + +# [v6.0.0] 2023-02-10 + +## Fixes + +- Mode Service: Add allowed subservice + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/739 +- `CService200ModeManagement`: Various bugfixes which lead to now execution complete being generated + on mode announcements, duplicate mode reply generated on announce commands, and the mode read + subservice not working properly. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/736 +- Memory leak fixes for the TCP/IP TMTC bridge. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/737 +- `Service9TimeManagement`: Fix the time dump at the `SET_TIME` subservice: Include clock timeval + seconds instead of uptime. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/726 +- HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously, + only the X scaling factor was used. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/724 +- HAL MGM3100 Handler: Z value was previously calculated with bytes of the X value. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/733 +- DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity + to false correctly because the `read` and `write` calls were missing. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/728 +- PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead + of the correct unsegmented flags (0b11) as specified in the standard. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/727 +- TC Scheduler Service 11: Add size and CRC check for contained TC. + Bug: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/issues/719 + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/720 +- Only delete health table entry in `HealthHelper` destructor if + health table was set. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710 +- I2C Bugfixes: Do not keep iterator as member and fix some incorrect handling with the iterator. + Also properly reset the reply size for successfull transfers and erroneous transfers. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700 +- Bugfix for Serial Buffer Stream: Setting `doActive` to false now + actually fully disables printing. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/680 +- `TcpTmTcServer.cpp`: The server was actually not able to handle + CCSDS packets which were clumped together. This has been fixed now. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673 +- `CServiceHealthCommanding`: Add announce all health info implementation + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725 +- various fixes related to linux Unittests and memory leaks + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/715 +- small fix to allow teardown handling + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/713 +- fix compiler warning for fixed array list copy ctor + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/704 +- missing include + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/703 +- defaultconfig did not build anymore + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/702 +- hotfix + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/699 +- small fix for helper + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/698 +- missing retval conv + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/697 +- DHB Countdown Bug + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/693 +- doc corrections + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/687 +- better error printout + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/686 +- include correction + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/683 +- better warning for missing include paths + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/676 +- Service 11 regression + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/670 + +## Added + +- Empty constructor for `CdsShortTimeStamper` which does not do an object manager registration. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/730 +- `Service9TimeManagement`: Add `DUMP_TIME` (129) subservice. +- `TcpTmTcServer`: Allow setting the `SO_REUSEADDR` and `SO_REUSEPORT` + option on the TCP server. CTOR prototype has changed and expects an explicit + TCP configuration struct to be passed. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/722 +- `DleParser` helper class to parse DLE encoded packets from a byte stream. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/711 +- `UioMapper` is able to resolve symlinks now. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709 +- Add new `UnsignedByteField` class + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660 +- publish documentation for development and master branch + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/681 +- Add Linux HAL options + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/663 +- Expand SerializeIF + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/656 +- PUS Service 11: Additional Safety Check + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/666 +- improvements for auto-formatter script + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/665 +- provide a weak print char impl + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/674 + +## Removed + +- now that doc server is up, remove markdown files + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/688 +- remove bsp specific code + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/679 ## Changes +- `CService201HealthCommanding` renamed to `CServiceHealthCommanding`, + service ID customizable now. `CServiceHealthCommanding` expects configuration struct + `HealthServiceCfg` now + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725 +- `AcceptsTelemetryIF`: `getReportReceptionQueue` is const now + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712 +- Moved some container returnvalues to dedicated header and namespace + so they can be used without template specification. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/707 +- Remove default secondary header argument for + `uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and + `uint16_t getTmSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/689 +- Removed `HasReturnvaluesIF` class in favor of `returnvalue` namespace with `OK` and `FAILED` + constants. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/659 +- Overhaul of the TMTC stack, including various changes and improvements + for other modules + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/655 + which also includes a migration guide +- Bump Catch2 dependency to regular version `v3.1.0` + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/678 +- `SerialBufferAdapter`: Rename `setBuffer` to `setConstBuffer` and update + API to expect `const uint8_t*` accordingly. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/677 +- Remove the following user includes from `fsfw/events/Event.h` and + `fsfw/returnvalues/returnvalue.h`: + - `#include "events/subsystemIdRanges.h"` + - `#include "returnvalues/classIds.h"` + The user has to include those themselves now + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/675 +- `DeviceHandlerBase`: Set command sender before calling `buildCommandFromCommand`. + This allows finishing action commands immediately inside the function. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/672 +- `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects + a `const SerializeIF&` and additional helper variant which expects `const uint8_t*` + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671 +- Improvements for `AcceptsTelemetryIF` and `AcceptsTelecommandsIF`: + - Make functions `const` where it makes sense + - Add `const char* getName const` abstract function + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/684 +- Generic TMTC Bridge Update + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/734 +- comment tweak to event parser can read everything + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/732 +- CMakeLists file updates + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/731 +- improve srv20 error messages + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/723 +- I2C Linux: remove duplicate printout + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/718 +- printout handling improvements + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/717 +- vec getter, reset for content + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/716 +- updates for source sequence counter + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/714 +- SP reader getPacketData is const now + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/708 +- refactoring of serial drivers for linux + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/705 +- Local Pool Update Remove Add Data Ignore Fault Argument + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/701 +- Switch to new documentation server + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/694 +- Windows Tweaks + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/691 +- Refactor Local Pool API + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/667 +- group MGM data in local pool vectors + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/664 + + +## CFDP + +- Refactoring of CFDP stack which was done during implementation of the CFDP source and destination + handlers. + - New filesystem module, changes for filesystem abstraction `HasFileSystemIF` to better + fit requirements of CFDP + - New `HostFilesystem` implementation of the `HasFileSystemIF` + - New `cfdp::UserBase` class which is the abstraction for the CFDP user in an OBSW context. + - mib module for the CFDP stack + - PDU classes renamed from `...Serializer`/`...Deserializer` to `...Creator`/`...Reader` + respetively + - Renamed `TcDistributor` to `TcDistributorBase` to prevent confusion + - Refactored `TcDisitributorBase` to be more flexible and usable for CFDP distribution + - Renamed `CCSDSDistributor` to `CcsdsDistributor` and add feature which allows it + to remove the CCSDS header when routing a packet. This allows CCSDS agnostic receiver + implementation without an extra component + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682 + +# [v5.0.0] 2022-07-25 + +## Changes + +- Renamed auto-formatting script to `auto-formatter.sh` and made it more robust. + If `cmake-format` is installed, it will also auto-format the `CMakeLists.txt` files now. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/625 + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/626 +- Bump C++ required version to C++17. Every project which uses the FSFW and every modern + compiler supports it + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/622 +- New CMake option `FSFW_HAL_LINUX_ADD_LIBGPIOD` to specifically exclude `gpiod` code. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572 +- HAL Devicehandlers: Periodic printout is run-time configurable now +- `oneShotAction` flag in the `TestTask` class is not static anymore +- `SimpleRingBuffer::writeData` now checks if the amount is larger than the total size of the + Buffer and rejects such writeData calls with `returnvalue::FAILED` + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/586 +- Major update for version handling, using `git describe` to fetch version information with git. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/601 + - Add helper functions provided by [`cmake-modules`](https://github.com/bilke/cmake-modules) + manually now. Those should not change too often and only a small subset is needed + - Separate folder for easier update and for distinction + - LICENSE file included + - use `int` for version numbers to allow unset or uninitialized version + - Initialize Version object with numbers set to -1 + - Instead of hardcoding the git hash, it is now retrieved from git + - `Version` now allows specifying additional version information like the git SHA1 hash and the + versions since the last tag + - Additional information is set to the last part of the git describe output for `FSFW_VERSION` now. + - Version still need to be hand-updated if the FSFW is not included as a submodule for now. +- IPC Message Queue Handling: Allow passing an optional `MqArgs` argument into the MessageQueue + creation call. It allows passing context information and an arbitrary user argument into + the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583 +- Internal API change: Moved the `fsfw_hal` to the `src` folder and integration and internal + tests part of `fsfw_tests` to `src`. Unittests are now in a dedicated folder called `unittests` + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/653 + +### Task Module Refactoring + +PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/636 + +**Refactoring general task code** + +- There was a lot of duplicate/boilerplate code inside the individual task IF OSAL implementations. + Remove it by introducing base classes `PeriodicTaskBase` and `FixedTimeslotTaskBase`. + +**Refactor PeriodicTaskIF** + +- Convert `virtual ReturnValue_t addComponent(object_id_t object)` to + `virtual ReturnValue_t addComponent(object_id_t object, uint8_t opCode = 0)`, allowing to pass + the operation code passed to `performOperation`. Updated API taking + an `ExecutableObjectIF` accordingly + +**Refactor FixedTimeslotTaskIF** + +- Add additional `addSlot` function which takes an `ExecutableObjectIF` pointer and its Object ID + +**Refactor FixedSequenceSlot** + +- Introduce typedef `CustomCheckFunc` for `ReturnValue_t (*customCheckFunction)(const SlotList&)`. +- Convert `ReturnValue_t (*customCheckFunction)(const SlotList&)` to + `ReturnValue_t (*customCheckFunction)(const SlotList&, void*)`, allowing arbitrary user arguments + for the custom checker + +**Linux Task Module** + +- Use composition instead of inheritance for the `PeriodicPosixTask` and make the `PosixTask` a + member of the class + +### HAL + +- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585 - HAL Linux SPI: Set the Clock Default State when setting new SPI speed and mode PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573 - GPIO HAL: `Direction`, `GpioOperation` and `Levels` are enum classes now, which prevents name clashes with Windows defines. PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572 -- New CMake option `FSFW_HAL_LINUX_ADD_LIBGPIOD` to specifically exclude `gpiod` code. - PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572 -- HAL Devicehandlers: Periodic printout is run-time configurable now -- `oneShotAction` flag in the `TestTask` class is not static anymore - HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585 -- IPC Message Queue Handling: Allow passing an optional `MqArgs` argument into the MessageQueue - creation call. It allows passing context information and an arbitrary user argument into - the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs - PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583 -- Clock: - - `timeval` to `TimeOfDay_t` - - Added Mutex for gmtime calls: (compare http://www.opengate.at/blog/2020/01/timeless/) - - Moved the statics used by Clock in ClockCommon.cpp to this file - - Better check for leap seconds - - Added Unittests for Clock (only getter) + +### Time + +PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/584 and +https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593 + +- `timeval` to `TimeOfDay_t` +- Added Mutex for gmtime calls: (compare http://www.opengate.at/blog/2020/01/timeless/) +- Moved the statics used by Clock in ClockCommon.cpp to this file +- Better check for leap seconds +- Added Unittests for Clock (only getter) + +### Power + +- `PowerSwitchIF`: Remove `const` specifier from `sendSwitchCommand` and `sendFuseOnCommand` and + also specify a `ReturnValue_t` return type + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590 +- Extend `PowerSwitcher` module to optionally check current state when calling `turnOn` or + `turnOff`. Tis can be helpful to avoid commanding switches which do not need commanding + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590 ## Removed @@ -43,17 +358,57 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Additions +- New constructor for PoolEntry which allows to simply specify the length of the pool entry. + This is also the new default constructor for scalar value with 0 as an initial value +- Added options for CI/CD builds: `FSFW_CICD_BUILD`. This allows the source code to know + whether it is running in CI/CD + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/623 +- Basic `clion` support: Update `.gitignore` and add some basic run configurations + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/625 +- LTO support: Allow using LTO/IPO by setting `FSFW_ENABLE_LTO=1`. CMake is able to detect whether + the user compiler supports IPO/LPO. LTO is on by default now. Most modern compilers support it, + can make good use of it and it usually makes the code faster and/or smaller. + After some more research: + Enabling LTO will actually cause the compiler to only produce thin LTO by adding + `-flto -fno-fat-lto-objects` to the compiler options. I am not sure this is an ideal choice + because if an application linking against the FSFW does not use LTO, there can be compile + issues (e.g. observed when compiling the FSFW tests without LTO). This is a known issue as + can be seen in the multiple CMake issues for it: + - https://gitlab.kitware.com/cmake/cmake/-/issues/22913, + - https://gitlab.kitware.com/cmake/cmake/-/issues/16808, + - https://gitlab.kitware.com/cmake/cmake/-/issues/21696 + Easiest solution for now: Keep this option OFF by default. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616 - Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1 - 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 generic PUS TC Scheduler Service 11. It depends on the new added Emebeded Template Library + (ETL) dependency. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/594 - Added ETL dependency and improved library dependency management PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592 +- Add a `DummyPowerSwitcher` module which can be useful for test setups when no PCDU is available + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590 +- New typedef for switcher type + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590 +- `Subsystem`: New API to add table and sequence entries ## Fixed +- TCP TMTC Server: `MutexGuard` was not created properly in + `TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent)` call. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/618 +- Fix infinite recursion in `prepareHealthSetReply` of PUS Health Service 201. + Is not currently used right now but might be used in the future + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/617 +- Move some CMake directives further up top so they are not ignored + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/621 - Small bugfix in STM32 HAL for SPI PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/599 +- HAL GPIO: Improved error checking in `LinuxLibgpioIF::configureGpios(...)`. If a GPIO + configuration fails, the function will exit prematurely with a dedicated error code + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/602 # [v4.0.0] diff --git a/CMakeLists.txt b/CMakeLists.txt index d8ca812e..5a7319cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,47 +1,130 @@ cmake_minimum_required(VERSION 3.13) -set(FSFW_VERSION 4) -set(FSFW_SUBVERSION 0) -set(FSFW_REVISION 0) +set(MSG_PREFIX "fsfw |") # Add the cmake folder so the FindSphinx module is found -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +list(APPEND CMAKE_MODULE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake-modules/bilke") +list(APPEND CMAKE_MODULE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake-modules/rpavlik") -set(FSFW_ETL_LIB_MAJOR_VERSION 20 CACHE STRING - "ETL library major version requirement" -) -set(FSFW_ETL_LIB_VERSION ${FSFW_ETL_LIB_MAJOR_VERSION}.27.2 CACHE STRING - "ETL library exact version requirement" -) +# ############################################################################## +# Version file handling # +# ############################################################################## -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_VERSION_IF_GIT_FAILS 6) +set(FSFW_SUBVERSION_IF_GIT_FAILS 0) +set(FSFW_REVISION_IF_GIT_FAILS 0) -set(FSFW_ETL_LIB_NAME etl) - -option(FSFW_GENERATE_SECTIONS - "Generate function and data sections. Required to remove unused code" ON -) -if(FSFW_GENERATE_SECTIONS) - option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON) +set(FSFW_GIT_VER_HANDLING_OK FALSE) +# Version handling +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git) + message(STATUS "${MSG_PREFIX} Determining version information with git") + include(FsfwHelpers) + determine_version_with_git("--exclude" "docker_*") + if(GIT_INFO) + set(FSFW_GIT_INFO + ${GIT_INFO} + CACHE STRING "Version information retrieved with git describe") + list(GET FSFW_GIT_INFO 1 FSFW_VERSION) + list(GET FSFW_GIT_INFO 2 FSFW_SUBVERSION) + list(GET FSFW_GIT_INFO 3 FSFW_REVISION) + list(GET FSFW_GIT_INFO 4 FSFW_VCS_INFO) + if(NOT FSFW_VERSION) + set(FSFW_VERSION ${FSFW_VERSION_IF_GIT_FAILS}) + endif() + if(NOT FSFW_SUBVERSION) + set(FSFW_SUBVERSION ${FSFW_SUBVERSION_IF_GIT_FAILS}) + endif() + if(NOT FSFW_REVISION) + set(FSFW_REVISION ${FSFW_REVISION_IF_GIT_FAILS}) + endif() + set(FSFW_GIT_VER_HANDLING_OK TRUE) + else() + set(FSFW_GIT_VER_HANDLING_OK FALSE) + endif() +endif() +if(NOT FSFW_GIT_VER_HANDLING_OK) + set(FSFW_VERSION ${FSFW_VERSION_IF_GIT_FAILS}) + set(FSFW_SUBVERSION ${FSFW_SUBVERSION_IF_GIT_FAILS}) + set(FSFW_REVISION ${FSFW_REVISION_IF_GIT_FAILS}) endif() -option(FSFW_BUILD_UNITTESTS "Build unittest binary in addition to static library" OFF) +set(LIB_FSFW_NAME fsfw) +project(${LIB_FSFW_NAME} + VERSION ${FSFW_VERSION}.${FSFW_SUBVERSION}.${FSFW_REVISION}) + +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED True) +elseif(${CMAKE_CXX_STANDARD} LESS 17) + message( + FATAL_ERROR + "${MSG_PREFIX} Compiling the FSFW requires a minimum of C++17 support") +endif() + +set(FSFW_SOURCES_DIR "${CMAKE_SOURCE_DIR}/src/fsfw") + +set(FSFW_ETL_LIB_NAME etl) +set(FSFW_ETL_LINK_TARGET etl::etl) +set(FSFW_ETL_LIB_MAJOR_VERSION + 20 + CACHE STRING "ETL library major version requirement") +set(FSFW_ETL_LIB_VERSION + ${FSFW_ETL_LIB_MAJOR_VERSION}.36.0 + CACHE STRING "ETL library exact version requirement") +set(FSFW_ETL_LINK_TARGET etl::etl) + +set(FSFW_CATCH2_LIB_MAJOR_VERSION + 3 + CACHE STRING "Catch2 library major version requirement") +set(FSFW_CATCH2_LIB_VERSION + v${FSFW_CATCH2_LIB_MAJOR_VERSION}.3.2 + CACHE STRING "Catch2 library exact version requirement") + +# Keep this off by default for now. See PR: +# https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616 for information which +# keeping this on by default is problematic +option( + FSFW_ENABLE_IPO + "Enable interprocedural optimization or link-time optimization if available" + OFF) +if(FSFW_ENABLE_IPO) + include(CheckIPOSupported) + check_ipo_supported(RESULT IPO_SUPPORTED OUTPUT IPO_ERROR) + if(NOT IPO_SUPPORTED) + message(STATUS "FSFW | IPO/LTO not supported: ${IPO_ERROR}") + endif() +endif() + +option(FSFW_GENERATE_SECTIONS + "Generate function and data sections. Required to remove unused code" ON) +if(FSFW_GENERATE_SECTIONS) + option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON) +endif() + +option(FSFW_BUILD_TESTS + "Build unittest binary in addition to static library. Requires Catch2" + OFF) +option(FSFW_CICD_BUILD "Build for CI/CD. This can disable problematic test" OFF) option(FSFW_BUILD_DOCS "Build documentation with Sphinx and Doxygen" OFF) -if(FSFW_BUILD_UNITTESTS) - option(FSFW_TESTS_GEN_COV "Generate coverage data for unittests" ON) +if(FSFW_BUILD_TESTS) + option(FSFW_TESTS_GEN_COV "Generate coverage data for unittests" ON) endif() option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON) # Options to exclude parts of the FSFW from compilation. option(FSFW_ADD_INTERNAL_TESTS "Add internal unit tests" ON) -option(FSFW_ADD_UNITTESTS "Add regular unittests. Requires Catch2" OFF) option(FSFW_ADD_HAL "Add Hardware Abstraction Layer" ON) +if(UNIX) + option(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS "Add Linux peripheral drivers" + OFF) + option(FSFW_HAL_LINUX_ADD_LIBGPIOD "Attempt to add Linux GPIOD drivers" OFF) + option(FSFW_HAL_LINUX_ADD_SERIAL_DRIVERS "Add serial drivers" ON) +endif() + # Optional sources option(FSFW_ADD_PUS "Compile with PUS sources" ON) option(FSFW_ADD_MONITORING "Compile with monitoring components" ON) @@ -54,76 +137,95 @@ option(FSFW_ADD_TMSTORAGE "Compile with tm storage components" OFF) # Contrib sources option(FSFW_ADD_SGP4_PROPAGATOR "Add SGP4 propagator code" OFF) -set(LIB_FSFW_NAME fsfw) set(FSFW_TEST_TGT fsfw-tests) set(FSFW_DUMMY_TGT fsfw-dummy) -project(${LIB_FSFW_NAME}) 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 ${FSFW_CATCH2_LIB_MAJOR_VERSION}) - # Not installed, so use FetchContent to download and provide Catch2 - if(NOT Catch2_FOUND) - message(STATUS "Catch2 installation not found. Downloading Catch2 library with FetchContent") - include(FetchContent) - - FetchContent_Declare( - Catch2 - GIT_REPOSITORY https://github.com/catchorg/Catch2.git - GIT_TAG ${FSFW_CATCH2_LIB_VERSION} - ) - - 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) - configure_file(tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in FSFWConfig.h) - configure_file(tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in tests/TestsConfig.h) - - project(${FSFW_TEST_TGT} CXX C) - add_executable(${FSFW_TEST_TGT}) - - if(FSFW_TESTS_GEN_COV) - message(STATUS "Generating coverage data for the library") - message(STATUS "Targets linking against ${LIB_FSFW_NAME} " - "will be compiled with coverage data as well" - ) - include(FetchContent) - FetchContent_Declare( - cmake-modules - GIT_REPOSITORY https://github.com/bilke/cmake-modules.git - ) - FetchContent_MakeAvailable(cmake-modules) - set(CMAKE_BUILD_TYPE "Debug") - list(APPEND CMAKE_MODULE_PATH ${cmake-modules_SOURCE_DIR}) - include(CodeCoverage) - endif() +if(IPO_SUPPORTED AND FSFW_ENABLE_IPO) + set_property(TARGET ${LIB_FSFW_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION + TRUE) endif() -message(STATUS "Finding and/or providing ETL library") +if(FSFW_BUILD_TESTS) + message( + STATUS + "${MSG_PREFIX} Building the FSFW unittests in addition to the static library" + ) + # Check whether the user has already installed Catch2 first + find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION} QUIET) + # Not installed, so use FetchContent to download and provide Catch2 + if(NOT Catch2_FOUND) + message( + STATUS + "${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent." + ) + include(FetchContent) + + FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG ${FSFW_CATCH2_LIB_VERSION}) + + list(APPEND FSFW_FETCH_CONTENT_TARGETS Catch2) + endif() + + set(FSFW_CONFIG_PATH unittests/testcfg) + configure_file(unittests/testcfg/FSFWConfig.h.in FSFWConfig.h) + configure_file(unittests/testcfg/TestsConfig.h.in tests/TestsConfig.h) + + project(${FSFW_TEST_TGT} CXX C) + add_executable(${FSFW_TEST_TGT}) + if(IPO_SUPPORTED AND FSFW_ENABLE_IPO) + set_property(TARGET ${FSFW_TEST_TGT} PROPERTY INTERPROCEDURAL_OPTIMIZATION + TRUE) + endif() + + if(FSFW_TESTS_GEN_COV) + message(STATUS "${MSG_PREFIX} Generating coverage data for the library") + message(STATUS "${MSG_PREFIX} Targets linking against ${LIB_FSFW_NAME} " + "will be compiled with coverage data as well") + set(CMAKE_BUILD_TYPE "Debug") + include(CodeCoverage) + endif() +endif() + +message( + STATUS + "${MSG_PREFIX} Finding and/or providing etl library with version ${FSFW_ETL_LIB_MAJOR_VERSION}" +) # Check whether the user has already installed ETL first find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET) # Not installed, so use FetchContent to download and provide etl if(NOT ${FSFW_ETL_LIB_NAME}_FOUND) - message(STATUS - "No ETL installation was found with find_package. Installing and providing " - "etl with FindPackage" - ) - include(FetchContent) + message( + STATUS + "${MSG_PREFIX} ETL installation not found. Downloading ETL with FetchContent." + ) + include(FetchContent) - FetchContent_Declare( - ${FSFW_ETL_LIB_NAME} - GIT_REPOSITORY https://github.com/ETLCPP/etl - GIT_TAG ${FSFW_ETL_LIB_VERSION} - ) + FetchContent_Declare( + ${FSFW_ETL_LIB_NAME} + GIT_REPOSITORY https://github.com/ETLCPP/etl + GIT_TAG ${FSFW_ETL_LIB_VERSION}) - FetchContent_MakeAvailable(etl) + list(APPEND FSFW_FETCH_CONTENT_TARGETS ${FSFW_ETL_LIB_NAME}) +endif() + +# The documentation for FetchContent recommends declaring all the dependencies +# before making them available. We make all declared dependency available here +# after their declaration +if(FSFW_FETCH_CONTENT_TARGETS) + FetchContent_MakeAvailable(${FSFW_FETCH_CONTENT_TARGETS}) + if(TARGET ${FSFW_ETL_LIB_NAME}) + add_library(${FSFW_ETL_LINK_TARGET} ALIAS ${FSFW_ETL_LIB_NAME}) + endif() + if(TARGET Catch2) + # Fixes regression -preview4, to be confirmed in later releases Related + # GitHub issue: https://github.com/catchorg/Catch2/issues/2417 + set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "") + endif() endif() set(FSFW_CORE_INC_PATH "inc") @@ -131,275 +233,250 @@ set(FSFW_CORE_INC_PATH "inc") set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux rtems freertos) # For configure files -target_include_directories(${LIB_FSFW_NAME} PRIVATE - ${CMAKE_CURRENT_BINARY_DIR} -) -target_include_directories(${LIB_FSFW_NAME} INTERFACE - ${CMAKE_CURRENT_BINARY_DIR} -) - -if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 11) - set(CMAKE_CXX_STANDARD_REQUIRED True) -elseif(${CMAKE_CXX_STANDARD} LESS 11) - message(FATAL_ERROR "Compiling the FSFW requires a minimum of C++11 support") -endif() +target_include_directories(${LIB_FSFW_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) +target_include_directories(${LIB_FSFW_NAME} + INTERFACE ${CMAKE_CURRENT_BINARY_DIR}) # Backwards comptability if(OS_FSFW AND NOT FSFW_OSAL) - message(WARNING "Please pass the FSFW OSAL as FSFW_OSAL instead of OS_FSFW") - set(FSFW_OSAL OS_FSFW) + message( + WARNING + "${MSG_PREFIX} Please pass the FSFW OSAL as FSFW_OSAL instead of OS_FSFW") + set(FSFW_OSAL OS_FSFW) endif() if(NOT FSFW_OSAL) - message(STATUS "No OS for FSFW via FSFW_OSAL set. Assuming host OS") - # Assume host OS and autodetermine from OS_FSFW - if(UNIX) - set(FSFW_OSAL "linux" - CACHE STRING - "OS abstraction layer used in the FSFW" - ) - elseif(WIN32) - set(FSFW_OSAL "host" - CACHE STRING "OS abstraction layer used in the FSFW" - ) - endif() - + message(STATUS "No OS for FSFW via FSFW_OSAL set. Assuming host OS") + # Assume host OS and autodetermine from OS_FSFW + if(UNIX) + set(FSFW_OSAL + "linux" + CACHE STRING "OS abstraction layer used in the FSFW") + elseif(WIN32) + set(FSFW_OSAL + "host" + CACHE STRING "OS abstraction layer used in the FSFW") + endif() endif() set(FSFW_OSAL_DEFINITION FSFW_OSAL_HOST) if(FSFW_OSAL MATCHES host) - set(FSFW_OS_NAME "Host") - set(FSFW_OSAL_HOST ON) + set(FSFW_OS_NAME "Host") + set(FSFW_OSAL_HOST ON) elseif(FSFW_OSAL MATCHES linux) - set(FSFW_OS_NAME "Linux") - set(FSFW_OSAL_LINUX ON) + set(FSFW_OS_NAME "Linux") + set(FSFW_OSAL_LINUX ON) elseif(FSFW_OSAL MATCHES freertos) - set(FSFW_OS_NAME "FreeRTOS") - set(FSFW_OSAL_FREERTOS ON) - target_link_libraries(${LIB_FSFW_NAME} PRIVATE - ${LIB_OS_NAME} - ) + set(FSFW_OS_NAME "FreeRTOS") + set(FSFW_OSAL_FREERTOS ON) + target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${LIB_OS_NAME}) elseif(FSFW_OSAL STREQUAL rtems) - set(FSFW_OS_NAME "RTEMS") - set(FSFW_OSAL_RTEMS ON) + set(FSFW_OS_NAME "RTEMS") + set(FSFW_OSAL_RTEMS ON) else() - message(WARNING - "Invalid operating system for FSFW specified! Setting to host.." - ) - set(FSFW_OS_NAME "Host") - set(OS_FSFW "host") + message( + WARNING + "${MSG_PREFIX} Invalid operating system for FSFW specified! Setting to host.." + ) + set(FSFW_OS_NAME "Host") + set(OS_FSFW "host") endif() configure_file(src/fsfw/FSFW.h.in fsfw/FSFW.h) configure_file(src/fsfw/FSFWVersion.h.in fsfw/FSFWVersion.h) -message(STATUS "Compiling FSFW for the ${FSFW_OS_NAME} operating system.") +message( + STATUS "${MSG_PREFIX} Compiling FSFW for the ${FSFW_OS_NAME} operating system" +) add_subdirectory(src) -add_subdirectory(tests) -if(FSFW_ADD_HAL) - add_subdirectory(hal) -endif() add_subdirectory(contrib) +if(FSFW_BUILD_TESTS) + add_subdirectory(unittests) +endif() if(FSFW_BUILD_DOCS) - add_subdirectory(docs) + add_subdirectory(docs) endif() -if(FSFW_BUILD_UNITTESTS) - if(FSFW_TESTS_GEN_COV) - if(CMAKE_COMPILER_IS_GNUCXX) - include(CodeCoverage) +if(FSFW_BUILD_TESTS) + if(FSFW_TESTS_GEN_COV) + if(CMAKE_COMPILER_IS_GNUCXX) + include(CodeCoverage) - # Remove quotes. - separate_arguments(COVERAGE_COMPILER_FLAGS - NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}" - ) + # Remove quotes. + separate_arguments(COVERAGE_COMPILER_FLAGS NATIVE_COMMAND + "${COVERAGE_COMPILER_FLAGS}") - # Add compile options manually, we don't want coverage for Catch2 - target_compile_options(${FSFW_TEST_TGT} PRIVATE - "${COVERAGE_COMPILER_FLAGS}" - ) - target_compile_options(${LIB_FSFW_NAME} PRIVATE - "${COVERAGE_COMPILER_FLAGS}" - ) + # Add compile options manually, we don't want coverage for Catch2 + target_compile_options(${FSFW_TEST_TGT} + PRIVATE "${COVERAGE_COMPILER_FLAGS}") + target_compile_options(${LIB_FSFW_NAME} + PRIVATE "${COVERAGE_COMPILER_FLAGS}") - # Exclude directories here - if(WIN32) - set(GCOVR_ADDITIONAL_ARGS - "--exclude-throw-branches" - "--exclude-unreachable-branches" - ) - set(COVERAGE_EXCLUDES - "/c/msys64/mingw64/*" "*/fsfw_hal/*" - ) - elseif(UNIX) - set(COVERAGE_EXCLUDES - "/usr/include/*" "/usr/bin/*" "Catch2/*" - "/usr/local/include/*" "*/fsfw_tests/*" - "*/catch2-src/*" "*/fsfw_hal/*" - ) - endif() + # Exclude directories here + if(WIN32) + set(GCOVR_ADDITIONAL_ARGS "--exclude-throw-branches" + "--exclude-unreachable-branches") + set(COVERAGE_EXCLUDES "/c/msys64/mingw64/*" "*/fsfw_hal/*") + elseif(UNIX) + set(COVERAGE_EXCLUDES + "/usr/include/*" + "/usr/bin/*" + "Catch2/*" + "/usr/local/include/*" + "*/fsfw_tests/*" + "*/catch2-src/*" + "*/fsfw_hal/*" + "unittests/*") + endif() - target_link_options(${FSFW_TEST_TGT} PRIVATE - -fprofile-arcs - -ftest-coverage - ) - target_link_options(${LIB_FSFW_NAME} PRIVATE - -fprofile-arcs - -ftest-coverage - ) - # Need to specify this as an interface, otherwise there will the compile issues - target_link_options(${LIB_FSFW_NAME} INTERFACE - -fprofile-arcs - -ftest-coverage - ) + target_link_options(${FSFW_TEST_TGT} PRIVATE -fprofile-arcs + -ftest-coverage) + target_link_options(${LIB_FSFW_NAME} PRIVATE -fprofile-arcs + -ftest-coverage) + # Need to specify this as an interface, otherwise there will the compile + # issues + target_link_options(${LIB_FSFW_NAME} INTERFACE -fprofile-arcs + -ftest-coverage) - if(WIN32) - setup_target_for_coverage_gcovr_html( - NAME ${FSFW_TEST_TGT}_coverage - EXECUTABLE ${FSFW_TEST_TGT} - DEPENDENCIES ${FSFW_TEST_TGT} - ) - else() - setup_target_for_coverage_lcov( - NAME ${FSFW_TEST_TGT}_coverage - EXECUTABLE ${FSFW_TEST_TGT} - DEPENDENCIES ${FSFW_TEST_TGT} - ) - endif() - endif() + if(WIN32) + setup_target_for_coverage_gcovr_html( + NAME ${FSFW_TEST_TGT}_coverage EXECUTABLE ${FSFW_TEST_TGT} + DEPENDENCIES ${FSFW_TEST_TGT}) + else() + setup_target_for_coverage_lcov( + NAME + ${FSFW_TEST_TGT}_coverage + EXECUTABLE + ${FSFW_TEST_TGT} + DEPENDENCIES + ${FSFW_TEST_TGT} + GENHTML_ARGS + --html-epilog + ${CMAKE_SOURCE_DIR}/unittests/lcov_epilog.html) + endif() endif() - target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2 ${LIB_FSFW_NAME}) + endif() + target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2 + ${LIB_FSFW_NAME}) endif() -# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. -# If this is not given, we include the default configuration and emit a warning. +# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. If +# this is not given, we include the default configuration and emit a warning. if(NOT FSFW_CONFIG_PATH) - set(DEF_CONF_PATH misc/defaultcfg/fsfwconfig) - if(NOT FSFW_BUILD_DOCS) - message(WARNING "Flight Software Framework configuration path not set!") - message(WARNING "Setting default configuration from ${DEF_CONF_PATH} ..") - endif() - add_subdirectory(${DEF_CONF_PATH}) - set(FSFW_CONFIG_PATH ${DEF_CONF_PATH}) + set(DEF_CONF_PATH misc/defaultcfg/fsfwconfig) + if(NOT FSFW_BUILD_DOCS) + message( + WARNING + "${MSG_PREFIX} Flight Software Framework configuration path FSFW_CONFIG_PATH not set" + ) + message( + WARNING + "${MSG_PREFIX} Setting default configuration from ${DEF_CONF_PATH} ..") + endif() + add_subdirectory(${DEF_CONF_PATH}) + set(FSFW_CONFIG_PATH ${DEF_CONF_PATH}) endif() -# FSFW might be part of a possibly complicated folder structure, so we -# extract the absolute path of the fsfwconfig folder. +# FSFW might be part of a possibly complicated folder structure, so we extract +# the absolute path of the fsfwconfig folder. if(IS_ABSOLUTE ${FSFW_CONFIG_PATH}) - set(FSFW_CONFIG_PATH_ABSOLUTE ${FSFW_CONFIG_PATH}) + set(FSFW_CONFIG_PATH_ABSOLUTE ${FSFW_CONFIG_PATH}) else() - get_filename_component(FSFW_CONFIG_PATH_ABSOLUTE - ${FSFW_CONFIG_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR} - ) + get_filename_component(FSFW_CONFIG_PATH_ABSOLUTE ${FSFW_CONFIG_PATH} REALPATH + BASE_DIR ${CMAKE_SOURCE_DIR}) endif() foreach(INCLUDE_PATH ${FSFW_ADDITIONAL_INC_PATHS}) - if(IS_ABSOLUTE ${INCLUDE_PATH}) - set(CURR_ABS_INC_PATH "${INCLUDE_PATH}") - else() - get_filename_component(CURR_ABS_INC_PATH - ${INCLUDE_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR}) - endif() + if(IS_ABSOLUTE ${INCLUDE_PATH}) + set(CURR_ABS_INC_PATH "${INCLUDE_PATH}") + else() + get_filename_component(CURR_ABS_INC_PATH ${INCLUDE_PATH} REALPATH BASE_DIR + ${CMAKE_SOURCE_DIR}) + endif() - if(CMAKE_VERBOSE) - message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}") - endif() + if(CMAKE_VERBOSE) + message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}") + endif() - list(APPEND FSFW_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH}) + list(APPEND FSFW_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH}) endforeach() if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - if(NOT DEFINED FSFW_WARNING_FLAGS) - set(FSFW_WARNING_FLAGS - -Wall - -Wextra - -Wimplicit-fallthrough=1 - -Wno-unused-parameter - -Wno-psabi - -Wduplicated-cond # check for duplicate conditions - -Wduplicated-branches # check for duplicate branches - -Wlogical-op # Search for bitwise operations instead of logical - -Wnull-dereference # Search for NULL dereference - -Wundef # Warn if undefind marcos are used - -Wformat=2 # Format string problem detection - -Wformat-overflow=2 # Formatting issues in printf - -Wformat-truncation=2 # Formatting issues in printf - -Wformat-security # Search for dangerous printf operations - -Wstrict-overflow=3 # Warn if integer overflows might happen - -Warray-bounds=2 # Some array bounds violations will be found - -Wshift-overflow=2 # Search for bit left shift overflows ( for --xml and --html output respectively. +# This will allow for Multiple Output Formats at the same time by making use of GCOVR_ADDITIONAL_ARGS, e.g. GCOVR_ADDITIONAL_ARGS "--txt". +# +# USAGE: +# +# 1. Copy this file into your cmake modules path. +# +# 2. Add the following line to your CMakeLists.txt (best inside an if-condition +# using a CMake option() to enable it just optionally): +# include(CodeCoverage) +# +# 3. Append necessary compiler flags for all supported source files: +# append_coverage_compiler_flags() +# Or for specific target: +# append_coverage_compiler_flags_to_target(YOUR_TARGET_NAME) +# +# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og +# +# 4. If you need to exclude additional directories from the report, specify them +# using full paths in the COVERAGE_EXCLUDES variable before calling +# setup_target_for_coverage_*(). +# Example: +# set(COVERAGE_EXCLUDES +# '${PROJECT_SOURCE_DIR}/src/dir1/*' +# '/path/to/my/src/dir2/*') +# Or, use the EXCLUDE argument to setup_target_for_coverage_*(). +# Example: +# setup_target_for_coverage_lcov( +# NAME coverage +# EXECUTABLE testrunner +# EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*") +# +# 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set +# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR) +# Example: +# set(COVERAGE_EXCLUDES "dir1/*") +# setup_target_for_coverage_gcovr_html( +# NAME coverage +# EXECUTABLE testrunner +# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src" +# EXCLUDE "dir2/*") +# +# 5. Use the functions described below to create a custom make target which +# runs your test executable and produces a code coverage report. +# +# 6. Build a Debug build: +# cmake -DCMAKE_BUILD_TYPE=Debug .. +# make +# make my_coverage_target +# + +include(CMakeParseArguments) + +option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE) + +# Check prereqs +find_program( GCOV_PATH gcov ) +find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl) +find_program( FASTCOV_PATH NAMES fastcov fastcov.py ) +find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat ) +find_program( GCOVR_PATH gcovr ) +find_program( CPPFILT_PATH NAMES c++filt ) + +if(NOT GCOV_PATH) + message(FATAL_ERROR "gcov not found! Aborting...") +endif() # NOT GCOV_PATH + +get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) +list(GET LANGUAGES 0 LANG) + +if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3) + message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") + endif() +elseif(NOT CMAKE_COMPILER_IS_GNUCXX) + if("${CMAKE_Fortran_COMPILER_ID}" MATCHES "[Ff]lang") + # Do nothing; exit conditional without error if true + elseif("${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU") + # Do nothing; exit conditional without error if true + else() + message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") + endif() +endif() + +set(COVERAGE_COMPILER_FLAGS "-g -fprofile-arcs -ftest-coverage" + CACHE INTERNAL "") +if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag(-fprofile-abs-path HAVE_fprofile_abs_path) + if(HAVE_fprofile_abs_path) + set(COVERAGE_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path") + endif() +endif() + +set(CMAKE_Fortran_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the Fortran compiler during coverage builds." + FORCE ) +set(CMAKE_CXX_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the C++ compiler during coverage builds." + FORCE ) +set(CMAKE_C_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the C compiler during coverage builds." + FORCE ) +set(CMAKE_EXE_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used for linking binaries during coverage builds." + FORCE ) +set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used by the shared libraries linker during coverage builds." + FORCE ) +mark_as_advanced( + CMAKE_Fortran_FLAGS_COVERAGE + CMAKE_CXX_FLAGS_COVERAGE + CMAKE_C_FLAGS_COVERAGE + CMAKE_EXE_LINKER_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) + +get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)) + message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading") +endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG) + +if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") + link_libraries(gcov) +endif() + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# setup_target_for_coverage_lcov( +# NAME testrunner_coverage # New target name +# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES testrunner # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative +# # to BASE_DIRECTORY, with CMake 3.4+) +# NO_DEMANGLE # Don't demangle C++ symbols +# # even if c++filt is found +# ) +function(setup_target_for_coverage_lcov) + + set(options NO_DEMANGLE) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT LCOV_PATH) + message(FATAL_ERROR "lcov not found! Aborting...") + endif() # NOT LCOV_PATH + + if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Aborting...") + endif() # NOT GENHTML_PATH + + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(DEFINED Coverage_BASE_DIRECTORY) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (CMake 3.4+: Also compute absolute paths) + set(LCOV_EXCLUDES "") + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_LCOV_EXCLUDES}) + if(CMAKE_VERSION VERSION_GREATER 3.4) + get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR}) + endif() + list(APPEND LCOV_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES LCOV_EXCLUDES) + + # Conditional arguments + if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE}) + set(GENHTML_EXTRA_ARGS "--demangle-cpp") + endif() + + # Setting up commands which will be run to generate coverage data. + # Cleanup lcov + set(LCOV_CLEAN_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory . + -b ${BASEDIR} --zerocounters + ) + # Create baseline to make sure untouched files show up in the report + set(LCOV_BASELINE_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -b + ${BASEDIR} -o ${Coverage_NAME}.base + ) + # Run tests + set(LCOV_EXEC_TESTS_CMD + ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} + ) + # Capturing lcov counters and generating report + set(LCOV_CAPTURE_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b + ${BASEDIR} --capture --output-file ${Coverage_NAME}.capture + ) + # add baseline counters + set(LCOV_BASELINE_COUNT_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base + -a ${Coverage_NAME}.capture --output-file ${Coverage_NAME}.total + ) + # filter collected data to final coverage report + set(LCOV_FILTER_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove + ${Coverage_NAME}.total ${LCOV_EXCLUDES} --output-file ${Coverage_NAME}.info + ) + # Generate HTML output + set(LCOV_GEN_HTML_CMD + ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o + ${Coverage_NAME} ${Coverage_NAME}.info + ) + + + if(CODE_COVERAGE_VERBOSE) + message(STATUS "Executed command report") + message(STATUS "Command to clean up lcov: ") + string(REPLACE ";" " " LCOV_CLEAN_CMD_SPACED "${LCOV_CLEAN_CMD}") + message(STATUS "${LCOV_CLEAN_CMD_SPACED}") + + message(STATUS "Command to create baseline: ") + string(REPLACE ";" " " LCOV_BASELINE_CMD_SPACED "${LCOV_BASELINE_CMD}") + message(STATUS "${LCOV_BASELINE_CMD_SPACED}") + + message(STATUS "Command to run the tests: ") + string(REPLACE ";" " " LCOV_EXEC_TESTS_CMD_SPACED "${LCOV_EXEC_TESTS_CMD}") + message(STATUS "${LCOV_EXEC_TESTS_CMD_SPACED}") + + message(STATUS "Command to capture counters and generate report: ") + string(REPLACE ";" " " LCOV_CAPTURE_CMD_SPACED "${LCOV_CAPTURE_CMD}") + message(STATUS "${LCOV_CAPTURE_CMD_SPACED}") + + message(STATUS "Command to add baseline counters: ") + string(REPLACE ";" " " LCOV_BASELINE_COUNT_CMD_SPACED "${LCOV_BASELINE_COUNT_CMD}") + message(STATUS "${LCOV_BASELINE_COUNT_CMD_SPACED}") + + message(STATUS "Command to filter collected data: ") + string(REPLACE ";" " " LCOV_FILTER_CMD_SPACED "${LCOV_FILTER_CMD}") + message(STATUS "${LCOV_FILTER_CMD_SPACED}") + + message(STATUS "Command to generate lcov HTML output: ") + string(REPLACE ";" " " LCOV_GEN_HTML_CMD_SPACED "${LCOV_GEN_HTML_CMD}") + message(STATUS "${LCOV_GEN_HTML_CMD_SPACED}") + endif() + + # Setup target + add_custom_target(${Coverage_NAME} + COMMAND ${LCOV_CLEAN_CMD} + COMMAND ${LCOV_BASELINE_CMD} + COMMAND ${LCOV_EXEC_TESTS_CMD} + COMMAND ${LCOV_CAPTURE_CMD} + COMMAND ${LCOV_BASELINE_COUNT_CMD} + COMMAND ${LCOV_FILTER_CMD} + COMMAND ${LCOV_GEN_HTML_CMD} + + # Set output files as GENERATED (will be removed on 'make clean') + BYPRODUCTS + ${Coverage_NAME}.base + ${Coverage_NAME}.capture + ${Coverage_NAME}.total + ${Coverage_NAME}.info + ${Coverage_NAME}/index.html + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + VERBATIM # Protect arguments to commands + COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." + ) + + # Show where to find the lcov info report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." + ) + +endfunction() # setup_target_for_coverage_lcov + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# setup_target_for_coverage_gcovr_xml( +# NAME ctest_coverage # New target name +# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES executable_target # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative +# # to BASE_DIRECTORY, with CMake 3.4+) +# ) +# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the +# GCVOR command. +function(setup_target_for_coverage_gcovr_xml) + + set(options NONE) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT GCOVR_PATH) + message(FATAL_ERROR "gcovr not found! Aborting...") + endif() # NOT GCOVR_PATH + + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(DEFINED Coverage_BASE_DIRECTORY) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (CMake 3.4+: Also compute absolute paths) + set(GCOVR_EXCLUDES "") + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES}) + if(CMAKE_VERSION VERSION_GREATER 3.4) + get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR}) + endif() + list(APPEND GCOVR_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES GCOVR_EXCLUDES) + + # Combine excludes to several -e arguments + set(GCOVR_EXCLUDE_ARGS "") + foreach(EXCLUDE ${GCOVR_EXCLUDES}) + list(APPEND GCOVR_EXCLUDE_ARGS "-e") + list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}") + endforeach() + + # Set up commands which will be run to generate coverage data + # Run tests + set(GCOVR_XML_EXEC_TESTS_CMD + ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} + ) + # Running gcovr + set(GCOVR_XML_CMD + ${GCOVR_PATH} --xml ${Coverage_NAME}.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS} + ${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR} + ) + + if(CODE_COVERAGE_VERBOSE) + message(STATUS "Executed command report") + + message(STATUS "Command to run tests: ") + string(REPLACE ";" " " GCOVR_XML_EXEC_TESTS_CMD_SPACED "${GCOVR_XML_EXEC_TESTS_CMD}") + message(STATUS "${GCOVR_XML_EXEC_TESTS_CMD_SPACED}") + + message(STATUS "Command to generate gcovr XML coverage data: ") + string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}") + message(STATUS "${GCOVR_XML_CMD_SPACED}") + endif() + + add_custom_target(${Coverage_NAME} + COMMAND ${GCOVR_XML_EXEC_TESTS_CMD} + COMMAND ${GCOVR_XML_CMD} + + BYPRODUCTS ${Coverage_NAME}.xml + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + VERBATIM # Protect arguments to commands + COMMENT "Running gcovr to produce Cobertura code coverage report." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml." + ) +endfunction() # setup_target_for_coverage_gcovr_xml + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# setup_target_for_coverage_gcovr_html( +# NAME ctest_coverage # New target name +# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES executable_target # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative +# # to BASE_DIRECTORY, with CMake 3.4+) +# ) +# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the +# GCVOR command. +function(setup_target_for_coverage_gcovr_html) + + set(options NONE) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT GCOVR_PATH) + message(FATAL_ERROR "gcovr not found! Aborting...") + endif() # NOT GCOVR_PATH + + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(DEFINED Coverage_BASE_DIRECTORY) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (CMake 3.4+: Also compute absolute paths) + set(GCOVR_EXCLUDES "") + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES}) + if(CMAKE_VERSION VERSION_GREATER 3.4) + get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR}) + endif() + list(APPEND GCOVR_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES GCOVR_EXCLUDES) + + # Combine excludes to several -e arguments + set(GCOVR_EXCLUDE_ARGS "") + foreach(EXCLUDE ${GCOVR_EXCLUDES}) + list(APPEND GCOVR_EXCLUDE_ARGS "-e") + list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}") + endforeach() + + # Set up commands which will be run to generate coverage data + # Run tests + set(GCOVR_HTML_EXEC_TESTS_CMD + ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} + ) + # Create folder + set(GCOVR_HTML_FOLDER_CMD + ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME} + ) + # Running gcovr + set(GCOVR_HTML_CMD + ${GCOVR_PATH} --html ${Coverage_NAME}/index.html --html-details -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS} + ${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR} + ) + + if(CODE_COVERAGE_VERBOSE) + message(STATUS "Executed command report") + + message(STATUS "Command to run tests: ") + string(REPLACE ";" " " GCOVR_HTML_EXEC_TESTS_CMD_SPACED "${GCOVR_HTML_EXEC_TESTS_CMD}") + message(STATUS "${GCOVR_HTML_EXEC_TESTS_CMD_SPACED}") + + message(STATUS "Command to create a folder: ") + string(REPLACE ";" " " GCOVR_HTML_FOLDER_CMD_SPACED "${GCOVR_HTML_FOLDER_CMD}") + message(STATUS "${GCOVR_HTML_FOLDER_CMD_SPACED}") + + message(STATUS "Command to generate gcovr HTML coverage data: ") + string(REPLACE ";" " " GCOVR_HTML_CMD_SPACED "${GCOVR_HTML_CMD}") + message(STATUS "${GCOVR_HTML_CMD_SPACED}") + endif() + + add_custom_target(${Coverage_NAME} + COMMAND ${GCOVR_HTML_EXEC_TESTS_CMD} + COMMAND ${GCOVR_HTML_FOLDER_CMD} + COMMAND ${GCOVR_HTML_CMD} + + BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html # report directory + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + VERBATIM # Protect arguments to commands + COMMENT "Running gcovr to produce HTML code coverage report." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." + ) + +endfunction() # setup_target_for_coverage_gcovr_html + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# setup_target_for_coverage_fastcov( +# NAME testrunner_coverage # New target name +# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES testrunner # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/" "src/dir2/" # Patterns to exclude. +# NO_DEMANGLE # Don't demangle C++ symbols +# # even if c++filt is found +# SKIP_HTML # Don't create html report +# POST_CMD perl -i -pe s!${PROJECT_SOURCE_DIR}/!!g ctest_coverage.json # E.g. for stripping source dir from file paths +# ) +function(setup_target_for_coverage_fastcov) + + set(options NO_DEMANGLE SKIP_HTML) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES FASTCOV_ARGS GENHTML_ARGS POST_CMD) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT FASTCOV_PATH) + message(FATAL_ERROR "fastcov not found! Aborting...") + endif() + + if(NOT Coverage_SKIP_HTML AND NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Aborting...") + endif() + + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(Coverage_BASE_DIRECTORY) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (Patterns, not paths, for fastcov) + set(FASTCOV_EXCLUDES "") + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_FASTCOV_EXCLUDES}) + list(APPEND FASTCOV_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES FASTCOV_EXCLUDES) + + # Conditional arguments + if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE}) + set(GENHTML_EXTRA_ARGS "--demangle-cpp") + endif() + + # Set up commands which will be run to generate coverage data + set(FASTCOV_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}) + + set(FASTCOV_CAPTURE_CMD ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH} + --search-directory ${BASEDIR} + --process-gcno + --output ${Coverage_NAME}.json + --exclude ${FASTCOV_EXCLUDES} + --exclude ${FASTCOV_EXCLUDES} + ) + + set(FASTCOV_CONVERT_CMD ${FASTCOV_PATH} + -C ${Coverage_NAME}.json --lcov --output ${Coverage_NAME}.info + ) + + if(Coverage_SKIP_HTML) + set(FASTCOV_HTML_CMD ";") + else() + set(FASTCOV_HTML_CMD ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} + -o ${Coverage_NAME} ${Coverage_NAME}.info + ) + endif() + + set(FASTCOV_POST_CMD ";") + if(Coverage_POST_CMD) + set(FASTCOV_POST_CMD ${Coverage_POST_CMD}) + endif() + + if(CODE_COVERAGE_VERBOSE) + message(STATUS "Code coverage commands for target ${Coverage_NAME} (fastcov):") + + message(" Running tests:") + string(REPLACE ";" " " FASTCOV_EXEC_TESTS_CMD_SPACED "${FASTCOV_EXEC_TESTS_CMD}") + message(" ${FASTCOV_EXEC_TESTS_CMD_SPACED}") + + message(" Capturing fastcov counters and generating report:") + string(REPLACE ";" " " FASTCOV_CAPTURE_CMD_SPACED "${FASTCOV_CAPTURE_CMD}") + message(" ${FASTCOV_CAPTURE_CMD_SPACED}") + + message(" Converting fastcov .json to lcov .info:") + string(REPLACE ";" " " FASTCOV_CONVERT_CMD_SPACED "${FASTCOV_CONVERT_CMD}") + message(" ${FASTCOV_CONVERT_CMD_SPACED}") + + if(NOT Coverage_SKIP_HTML) + message(" Generating HTML report: ") + string(REPLACE ";" " " FASTCOV_HTML_CMD_SPACED "${FASTCOV_HTML_CMD}") + message(" ${FASTCOV_HTML_CMD_SPACED}") + endif() + if(Coverage_POST_CMD) + message(" Running post command: ") + string(REPLACE ";" " " FASTCOV_POST_CMD_SPACED "${FASTCOV_POST_CMD}") + message(" ${FASTCOV_POST_CMD_SPACED}") + endif() + endif() + + # Setup target + add_custom_target(${Coverage_NAME} + + # Cleanup fastcov + COMMAND ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH} + --search-directory ${BASEDIR} + --zerocounters + + COMMAND ${FASTCOV_EXEC_TESTS_CMD} + COMMAND ${FASTCOV_CAPTURE_CMD} + COMMAND ${FASTCOV_CONVERT_CMD} + COMMAND ${FASTCOV_HTML_CMD} + COMMAND ${FASTCOV_POST_CMD} + + # Set output files as GENERATED (will be removed on 'make clean') + BYPRODUCTS + ${Coverage_NAME}.info + ${Coverage_NAME}.json + ${Coverage_NAME}/index.html # report directory + + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + VERBATIM # Protect arguments to commands + COMMENT "Resetting code coverage counters to zero. Processing code coverage counters and generating report." + ) + + set(INFO_MSG "fastcov code coverage info report saved in ${Coverage_NAME}.info and ${Coverage_NAME}.json.") + if(NOT Coverage_SKIP_HTML) + string(APPEND INFO_MSG " Open ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html in your browser to view the coverage report.") + endif() + # Show where to find the fastcov info report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo ${INFO_MSG} + ) + +endfunction() # setup_target_for_coverage_fastcov + +function(append_coverage_compiler_flags) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}") +endfunction() # append_coverage_compiler_flags + +# Setup coverage for specific library +function(append_coverage_compiler_flags_to_target name) + target_compile_options(${name} + PRIVATE ${COVERAGE_COMPILER_FLAGS}) +endfunction() diff --git a/cmake/cmake-modules/bilke/LICENSE_1_0.txt b/cmake/cmake-modules/bilke/LICENSE_1_0.txt new file mode 100644 index 00000000..36b7cd93 --- /dev/null +++ b/cmake/cmake-modules/bilke/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/cmake/cmake-modules/rpavlik/GetGitRevisionDescription.cmake b/cmake/cmake-modules/rpavlik/GetGitRevisionDescription.cmake new file mode 100644 index 00000000..69ef78b2 --- /dev/null +++ b/cmake/cmake-modules/rpavlik/GetGitRevisionDescription.cmake @@ -0,0 +1,284 @@ +# - Returns a version string from Git +# +# These functions force a re-configure on each git commit so that you can +# trust the values of the variables in your build system. +# +# get_git_head_revision( [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR]) +# +# Returns the refspec and sha hash of the current head revision +# +# git_describe( [ ...]) +# +# Returns the results of git describe on the source tree, and adjusting +# the output so that it tests false if an error occurs. +# +# git_describe_working_tree( [ ...]) +# +# Returns the results of git describe on the working tree (--dirty option), +# and adjusting the output so that it tests false if an error occurs. +# +# git_get_exact_tag( [ ...]) +# +# Returns the results of git describe --exact-match on the source tree, +# and adjusting the output so that it tests false if there was no exact +# matching tag. +# +# git_local_changes() +# +# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes. +# Uses the return code of "git diff-index --quiet HEAD --". +# Does not regard untracked files. +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2020 Ryan Pavlik +# http://academic.cleardefinition.com +# +# Copyright 2009-2013, Iowa State University. +# Copyright 2013-2020, Ryan Pavlik +# Copyright 2013-2020, Contributors +# SPDX-License-Identifier: BSL-1.0 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if(__get_git_revision_description) + return() +endif() +set(__get_git_revision_description YES) + +# We must run the following at "include" time, not at function call time, +# to find the path to this module rather than the path to a calling list file +get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) + +# Function _git_find_closest_git_dir finds the next closest .git directory +# that is part of any directory in the path defined by _start_dir. +# The result is returned in the parent scope variable whose name is passed +# as variable _git_dir_var. If no .git directory can be found, the +# function returns an empty string via _git_dir_var. +# +# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and +# neither foo nor bar contain a file/directory .git. This wil return +# C:/bla/.git +# +function(_git_find_closest_git_dir _start_dir _git_dir_var) + set(cur_dir "${_start_dir}") + set(git_dir "${_start_dir}/.git") + while(NOT EXISTS "${git_dir}") + # .git dir not found, search parent directories + set(git_previous_parent "${cur_dir}") + get_filename_component(cur_dir "${cur_dir}" DIRECTORY) + if(cur_dir STREQUAL git_previous_parent) + # We have reached the root directory, we are not in git + set(${_git_dir_var} + "" + PARENT_SCOPE) + return() + endif() + set(git_dir "${cur_dir}/.git") + endwhile() + set(${_git_dir_var} + "${git_dir}" + PARENT_SCOPE) +endfunction() + +function(get_git_head_revision _refspecvar _hashvar) + _git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR) + + if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR") + set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE) + else() + set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE) + endif() + if(NOT "${GIT_DIR}" STREQUAL "") + file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}" + "${GIT_DIR}") + if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR) + # We've gone above the CMake root dir. + set(GIT_DIR "") + endif() + endif() + if("${GIT_DIR}" STREQUAL "") + set(${_refspecvar} + "GITDIR-NOTFOUND" + PARENT_SCOPE) + set(${_hashvar} + "GITDIR-NOTFOUND" + PARENT_SCOPE) + return() + endif() + + # Check if the current source dir is a git submodule or a worktree. + # In both cases .git is a file instead of a directory. + # + if(NOT IS_DIRECTORY ${GIT_DIR}) + # The following git command will return a non empty string that + # points to the super project working tree if the current + # source dir is inside a git submodule. + # Otherwise the command will return an empty string. + # + execute_process( + COMMAND "${GIT_EXECUTABLE}" rev-parse + --show-superproject-working-tree + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + OUTPUT_VARIABLE out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT "${out}" STREQUAL "") + # If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule + file(READ ${GIT_DIR} submodule) + string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE + ${submodule}) + string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE) + get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) + get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} + ABSOLUTE) + set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD") + else() + # GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree + file(READ ${GIT_DIR} worktree_ref) + # The .git directory contains a path to the worktree information directory + # inside the parent git repo of the worktree. + # + string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir + ${worktree_ref}) + string(STRIP ${git_worktree_dir} git_worktree_dir) + _git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR) + set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD") + endif() + else() + set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD") + endif() + set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") + if(NOT EXISTS "${GIT_DATA}") + file(MAKE_DIRECTORY "${GIT_DATA}") + endif() + + if(NOT EXISTS "${HEAD_SOURCE_FILE}") + return() + endif() + set(HEAD_FILE "${GIT_DATA}/HEAD") + configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY) + + configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" + "${GIT_DATA}/grabRef.cmake" @ONLY) + include("${GIT_DATA}/grabRef.cmake") + + set(${_refspecvar} + "${HEAD_REF}" + PARENT_SCOPE) + set(${_hashvar} + "${HEAD_HASH}" + PARENT_SCOPE) +endfunction() + +function(git_describe _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} + "GIT-NOTFOUND" + PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} + "HEAD-HASH-NOTFOUND" + PARENT_SCOPE) + return() + endif() + + # TODO sanitize + #if((${ARGN}" MATCHES "&&") OR + # (ARGN MATCHES "||") OR + # (ARGN MATCHES "\\;")) + # message("Please report the following error to the project!") + # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") + #endif() + + #message(STATUS "Arguments to execute_process: ${ARGN}") + + execute_process( + COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE res + OUTPUT_VARIABLE out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${_var} + "${out}" + PARENT_SCOPE) +endfunction() + +function(git_describe_working_tree _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + if(NOT GIT_FOUND) + set(${_var} + "GIT-NOTFOUND" + PARENT_SCOPE) + return() + endif() + + execute_process( + COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE res + OUTPUT_VARIABLE out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${_var} + "${out}" + PARENT_SCOPE) +endfunction() + +function(git_get_exact_tag _var) + git_describe(out --exact-match ${ARGN}) + set(${_var} + "${out}" + PARENT_SCOPE) +endfunction() + +function(git_local_changes _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} + "GIT-NOTFOUND" + PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} + "HEAD-HASH-NOTFOUND" + PARENT_SCOPE) + return() + endif() + + execute_process( + COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD -- + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE res + OUTPUT_VARIABLE out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(res EQUAL 0) + set(${_var} + "CLEAN" + PARENT_SCOPE) + else() + set(${_var} + "DIRTY" + PARENT_SCOPE) + endif() +endfunction() diff --git a/cmake/cmake-modules/rpavlik/GetGitRevisionDescription.cmake.in b/cmake/cmake-modules/rpavlik/GetGitRevisionDescription.cmake.in new file mode 100644 index 00000000..66eee637 --- /dev/null +++ b/cmake/cmake-modules/rpavlik/GetGitRevisionDescription.cmake.in @@ -0,0 +1,43 @@ +# +# Internal file for GetGitRevisionDescription.cmake +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright 2009-2012, Iowa State University +# Copyright 2011-2015, Contributors +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# SPDX-License-Identifier: BSL-1.0 + +set(HEAD_HASH) + +file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) + +string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) +if(HEAD_CONTENTS MATCHES "ref") + # named branch + string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") + if(EXISTS "@GIT_DIR@/${HEAD_REF}") + configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) + else() + configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) + file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) + if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") + set(HEAD_HASH "${CMAKE_MATCH_1}") + endif() + endif() +else() + # detached HEAD + configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) +endif() + +if(NOT HEAD_HASH) + file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) + string(STRIP "${HEAD_HASH}" HEAD_HASH) +endif() diff --git a/cmake/cmake-modules/rpavlik/LICENSES/BSD-3-Clause.txt b/cmake/cmake-modules/rpavlik/LICENSES/BSD-3-Clause.txt new file mode 100644 index 00000000..0741db78 --- /dev/null +++ b/cmake/cmake-modules/rpavlik/LICENSES/BSD-3-Clause.txt @@ -0,0 +1,26 @@ +Copyright (c) . All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/cmake/cmake-modules/rpavlik/LICENSES/BSL-1.0.txt b/cmake/cmake-modules/rpavlik/LICENSES/BSL-1.0.txt new file mode 100644 index 00000000..cff35365 --- /dev/null +++ b/cmake/cmake-modules/rpavlik/LICENSES/BSL-1.0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, execute, +and transmit the Software, and to prepare derivative works of the Software, +and to permit third-parties to whom the Software is furnished to do so, all +subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, must +be included in all copies of the Software, in whole or in part, and all derivative +works of the Software, unless such copies or derivative works are solely in +the form of machine-executable object code generated by a source language +processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES +OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/cmake/cmake-modules/rpavlik/LICENSE_1_0.txt b/cmake/cmake-modules/rpavlik/LICENSE_1_0.txt new file mode 100644 index 00000000..36b7cd93 --- /dev/null +++ b/cmake/cmake-modules/rpavlik/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/docs/README-config.md b/docs/README-config.md deleted file mode 100644 index d71feb97..00000000 --- a/docs/README-config.md +++ /dev/null @@ -1,40 +0,0 @@ -Configuring the FSFW -====== - -The FSFW can be configured via the `fsfwconfig` folder. A template folder has -been provided to have a starting point for this. The folder should be added -to the include path. The primary configuration file is the `FSFWConfig.h` folder. Some -of the available options will be explained in more detail here. - -# Auto-Translation of Events - -The FSFW allows the automatic translation of events, which allows developers to track triggered -events directly via console output. Using this feature requires: - -1. `FSFW_OBJ_EVENT_TRANSLATION` set to 1 in the configuration file. -2. Special auto-generated translation files which translate event IDs and object IDs into - human readable strings. These files can be generated using the - [modgen Python scripts](https://git.ksat-stuttgart.de/source/modgen.git). -3. The generated translation files for the object IDs should be named `translatesObjects.cpp` - and `translateObjects.h` and should be copied to the `fsfwconfig/objects` folder -4. The generated translation files for the event IDs should be named `translateEvents.cpp` and - `translateEvents.h` and should be copied to the `fsfwconfig/events` folder - -An example implementations of these translation file generators can be found as part -of the [SOURCE project here](https://git.ksat-stuttgart.de/source/sourceobsw/-/tree/development/generators) -or the [FSFW example](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_example_public/src/branch/master/generators) - -## Configuring the Event Manager - -The number of allowed subscriptions can be modified with the following -parameters: - -``` c++ -namespace fsfwconfig { -//! Configure the allocated pool sizes for the event manager. -static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240; -static constexpr size_t FSFW_EVENTMGMT_EVENTIDMATCHERS = 120; -static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120; -} -``` - diff --git a/docs/README-controllers.md b/docs/README-controllers.md deleted file mode 100644 index 7af0652d..00000000 --- a/docs/README-controllers.md +++ /dev/null @@ -1 +0,0 @@ -## Controllers diff --git a/docs/README-core.md b/docs/README-core.md deleted file mode 100644 index e34890ae..00000000 --- a/docs/README-core.md +++ /dev/null @@ -1,55 +0,0 @@ -## FSFW Core Modules - -These core modules provide the most important functionalities of the -Flight Software Framework - -### Clock - - * This is a class of static functions that can be used at anytime - * Leap Seconds must be set if any time conversions from UTC to other times is used - -### ObjectManager - -* Must be created during program startup -* The component which handles all references. All SystemObjects register at this component. -* Any SystemObject needs to have a unique ObjectId. Those can be managed like objects::framework_objects. -* A reference to an object can be get by calling the following function. T must be the specific Interface you want to call. -A nullptr check of the returning Pointer must be done. This function is based on Run-time type information. - -```cpp -template T* ObjectManagerIF::get( object_id_t id ) -``` -* A typical way to create all objects on startup is a handing a static produce function to the - ObjectManager on creation. By calling objectManager->initialize() the produce function will be - called and all SystemObjects will be initialized afterwards. - -### Event Manager - -* Component which allows routing of events -* Other objects can subscribe to specific events, ranges of events or all events of an object. -* Subscriptions can be done during runtime but should be done during initialization -* Amounts of allowed subscriptions can be configured in `FSFWConfig.h` - -### Health Table - -* A component which holds every health state -* Provides a thread safe way to access all health states without the need of message exchanges - -### Stores - -* The message based communication can only exchange a few bytes of information inside the message - itself. Therefore, additional information can be exchanged with Stores. With this, only the - store address must be exchanged in the message. -* Internally, the FSFW uses an IPC Store to exchange data between processes. For incoming TCs a TC - Store is used. For outgoing TM a TM store is used. -* All of them should use the Thread Safe Class storagemanager/PoolManager - -### Tasks - -There are two different types of tasks: - * The PeriodicTask just executes objects that are of type ExecutableObjectIF in the order of the - insertion to the Tasks. - * FixedTimeslotTask executes a list of calls in the order of the given list. This is intended for - DeviceHandlers, where polling should be in a defined order. An example can be found in - `defaultcfg/fsfwconfig/pollingSequence` folder - diff --git a/docs/README-devicehandlers.md b/docs/README-devicehandlers.md deleted file mode 100644 index 8b6551aa..00000000 --- a/docs/README-devicehandlers.md +++ /dev/null @@ -1 +0,0 @@ -## Device Handlers diff --git a/docs/README-highlevel.md b/docs/README-highlevel.md deleted file mode 100644 index 262138a7..00000000 --- a/docs/README-highlevel.md +++ /dev/null @@ -1,135 +0,0 @@ -High-level overview -====== - -# Structure - -The general structure is driven by the usage of interfaces provided by objects. -The FSFW uses C++11 as baseline. The intention behind this is that this C++ Standard should be -widely available, even with older compilers. -The FSFW uses dynamic allocation during the initialization but provides static containers during runtime. -This simplifies the instantiation of objects and allows the usage of some standard containers. -Dynamic Allocation after initialization is discouraged and different solutions are provided in the -FSFW to achieve that. The fsfw uses run-time type information but exceptions are not allowed. - -# Failure Handling - -Functions should return a defined `ReturnValue_t` to signal to the caller that something has -gone wrong. Returnvalues must be unique. For this the function `HasReturnvaluesIF::makeReturnCode` -or the macro `MAKE_RETURN` can be used. The `CLASS_ID` is a unique id for that type of object. -See `returnvalues/FwClassIds` folder. The user can add custom `CLASS_ID`s via the -`fsfwconfig` folder. - -# OSAL - -The FSFW provides operation system abstraction layers for Linux, FreeRTOS and RTEMS. -The OSAL provides periodic tasks, message queues, clocks and semaphores as well as mutexes. -The [OSAL README](doc/README-osal.md#top) provides more detailed information on provided components -and how to use them. - -# Core Components - -The FSFW has following core components. More detailed informations can be found in the -[core component section](doc/README-core.md#top): - -1. Tasks: Abstraction for different (periodic) task types like periodic tasks or tasks - with fixed timeslots -2. ObjectManager: This module stores all `SystemObjects` by mapping a provided unique object ID - to the object handles. -3. Static Stores: Different stores are provided to store data of variable size (like telecommands - or small telemetry) in a pool structure without using dynamic memory allocation. - These pools are allocated up front. -3. Clock: This module provided common time related functions -4. EventManager: This module allows routing of events generated by `SystemObjects` -5. HealthTable: A component which stores the health states of objects - -# Static IDs in the framework - -Some parts of the framework use a static routing address for communication. -An example setup of ids can be found in the example config in `defaultcft/fsfwconfig/objects` - inside the function `Factory::setStaticFrameworkObjectIds()`. - -# Events - -Events are tied to objects. EventIds can be generated by calling the Macro MAKE_EVENT. -This works analog to the returnvalues. Every object that needs own EventIds has to get a -unique SUBSYSTEM_ID. Every SystemObject can call triggerEvent from the parent class. -Therefore, event messages contain the specific EventId and the objectId of the object that -has triggered. - -# Internal Communication - -Components communicate mostly via Messages through Queues. -Those queues are created by calling the singleton `QueueFactory::instance()->create()` which -will create `MessageQueue` instances for the used OSAL. - -# External Communication - -The external communication with the mission control system is mostly up to the user implementation. -The FSFW provides PUS Services which can be used to but don't need to be used. -The services can be seen as a conversion from a TC to a message based communication and back. - -## TMTC Communication - -The FSFW provides some components to facilitate TMTC handling via the PUS commands. -For example, a UDP or TCP PUS server socket can be opened on a specific port using the -files located in `osal/common`. The FSFW example uses this functionality to allow sending telecommands -and receiving telemetry using the [TMTC commander application](https://github.com/spacefisch/tmtccmd). -Simple commands like the PUS Service 17 ping service can be tested by simply running the -`tmtc_client_cli.py` or `tmtc_client_gui.py` utility in -the [example tmtc folder](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_example_public/src/branch/master/tmtc) -while the `fsfw_example` application is running. - -More generally, any class responsible for handling incoming telecommands and sending telemetry -can implement the generic `TmTcBridge` class located in `tmtcservices`. Many applications -also use a dedicated polling task for reading telecommands which passes telecommands -to the `TmTcBridge` implementation. - -## CCSDS Frames, CCSDS Space Packets and PUS - -If the communication is based on CCSDS Frames and Space Packets, several classes can be used to -distributed the packets to the corresponding services. Those can be found in `tcdistribution`. -If Space Packets are used, a timestamper has to be provided by the user. -An example can be found in the `timemanager` folder, which uses `CCSDSTime::CDS_short`. - -# Device Handlers - -DeviceHandlers are another important component of the FSFW. -The idea is, to have a software counterpart of every physical device to provide a simple mode, -health and commanding interface. By separating the underlying Communication Interface with -`DeviceCommunicationIF`, a device handler (DH) can be tested on different hardware. -The DH has mechanisms to monitor the communication with the physical device which allow -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). - -# Modes and Health - -The two interfaces `HasModesIF` and `HasHealthIF` provide access for commanding and monitoring -of components. On-board Mode Management is implement in hierarchy system. -DeviceHandlers and Controllers are the lowest part of the hierarchy. -The next layer are Assemblies. Those assemblies act as a component which handle -redundancies of handlers. Assemblies share a common core with the next level which -are the Subsystems. - -Those Assemblies are intended to act as auto-generated components from a database which describes -the subsystem modes. The definitions contain transition and target tables which contain the DH, -Assembly and Controller Modes to be commanded. -Transition tables contain as many steps as needed to reach the mode from any other mode, e.g. a -switch into any higher AOCS mode might first turn on the sensors, than the actuators and the -controller as last component. -The target table is used to describe the state that is checked continuously by the subsystem. -All of this allows System Modes to be generated as Subsystem object as well from the same database. -This System contains list of subsystem modes in the transition and target tables. -Therefore, it allows a modular system to create system modes and easy commanding of those, because -only the highest components must be commanded. - -The health state represents if the component is able to perform its tasks. -This can be used to signal the system to avoid using this component instead of a redundant one. -The on-board FDIR uses the health state for isolation and recovery. - -# Unit Tests - -Unit Tests are provided in the unittest folder. Those use the catch2 framework but do not include -catch2 itself. More information on how to run these tests can be found in the separate -[`fsfw_tests` reposoitory](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_tests) diff --git a/docs/README-localpools.md b/docs/README-localpools.md deleted file mode 100644 index 2ee75189..00000000 --- a/docs/README-localpools.md +++ /dev/null @@ -1,174 +0,0 @@ -## Local Data Pools Developer Information - -The following text is targeted towards mission software developers which would like -to use the local data pools provided by the FSFW to store data like sensor values so they can be -used by other software objects like controllers as well. If a custom class should have a local -pool which can be used by other software objects as well, following steps have to be performed: - -1. Create a `LocalDataPoolManager` member object in the custom class -2. Implement the `HasLocalDataPoolIF` with specifies the interface between the local pool manager -and the class owning the local pool. - -The local data pool manager is also able to process housekeeping service requests in form -of messages, generate periodic housekeeping packet, generate notification and snapshots of changed -variables and datasets and process notifications and snapshots coming from other objects. -The two former tasks are related to the external interface using telemetry and telecommands (TMTC) -while the later two are related to data consumers like controllers only acting on data change -detected by the data creator instead of checking the data manually each cycle. Two important -framework classes `DeviceHandlerBase` and `ExtendedControllerBase` already perform the two steps -shown above so the steps required are altered slightly. - -### Storing and Accessing pool data - -The pool manager is responsible for thread-safe access of the pool data, but the actual -access to the pool data from the point of view of a mission software developer happens via proxy -classes like pool variable classes. These classes store a copy -of the pool variable with the matching datatype and copy the actual data from the local pool -on a `read` call. Changed variables can then be written to the local pool with a `commit` call. -The `read` and `commit` calls are thread-safe and can be called concurrently from data creators -and data consumers. Generally, a user will create a dataset class which in turn groups all -cohesive pool variables. These sets simply iterator over the list of variables and call the -`read` and `commit` functions of each variable. The following diagram shows the -high-level architecture of the local data pools. - -.. image:: ../misc/logo/FSFW_Logo_V3_bw.png - :alt: FSFW Logo - - -An example is shown for using the local data pools with a Gyroscope. -For example, the following code shows an implementation to access data from a Gyroscope taken -from the SOURCE CubeSat project: - -```cpp -class GyroPrimaryDataset: public StaticLocalDataSet<3 * sizeof(float)> { -public: - /** - * Constructor for data users - * @param gyroId - */ - GyroPrimaryDataset(object_id_t gyroId): - StaticLocalDataSet(sid_t(gyroId, gyrodefs::GYRO_DATA_SET_ID)) { - setAllVariablesReadOnly(); - } - - lp_var_t angVelocityX = lp_var_t(sid.objectId, - gyrodefs::ANGULAR_VELOCITY_X, this); - lp_var_t angVelocityY = lp_var_t(sid.objectId, - gyrodefs::ANGULAR_VELOCITY_Y, this); - lp_var_t angVelocityZ = lp_var_t(sid.objectId, - gyrodefs::ANGULAR_VELOCITY_Z, this); -private: - - friend class GyroHandler; - /** - * Constructor for data creator - * @param hkOwner - */ - GyroPrimaryDataset(HasLocalDataPoolIF* hkOwner): - StaticLocalDataSet(hkOwner, gyrodefs::GYRO_DATA_SET_ID) {} -}; -``` - -There is a public constructor for users which sets all variables to read-only and there is a -constructor for the GyroHandler data creator by marking it private and declaring the `GyroHandler` -as a friend class. Both the atittude controller and the `GyroHandler` can now -use the same class definition to access the pool variables with `read` and `commit` semantics -in a thread-safe way. Generally, each class requiring access will have the set class as a member -class. The data creator will also be generally a `DeviceHandlerBase` subclass and some additional -steps are necessary to expose the set for housekeeping purposes. - -### Using the local data pools in a `DeviceHandlerBase` subclass - -It is very common to store data generated by devices like a sensor into a pool which can -then be used by other objects. Therefore, the `DeviceHandlerBase` already has a -local pool. Using the aforementioned example, our `GyroHandler` will now have the set class -as a member: - -```cpp -class GyroHandler: ... { - -public: - ... -private: - ... - GyroPrimaryDataset gyroData; - ... -}; -``` - -The constructor used for the creators expects the owner class as a parameter, so we initialize -the object in the `GyroHandler` constructor like this: - -```cpp -GyroHandler::GyroHandler(object_id_t objectId, object_id_t comIF, - CookieIF *comCookie, uint8_t switchId): - DeviceHandlerBase(objectId, comIF, comCookie), switchId(switchId), - gyroData(this) {} -``` - -We need to assign the set to a reply ID used in the `DeviceHandlerBase`. -The combination of the `GyroHandler` object ID and the reply ID will be the 64-bit structure ID -`sid_t` and is used to globally identify the set, for example when requesting housekeeping data or -generating update messages. We need to assign our custom set class in some way so that the local -pool manager can access the custom data sets as well. -By default, the `getDataSetHandle` will take care of this tasks. The default implementation for a -`DeviceHandlerBase` subclass will use the internal command map to retrieve -a handle to a dataset from a given reply ID. Therefore, -we assign the set in the `fillCommandAndReplyMap` function: - -```cpp -void GyroHandler::fillCommandAndReplyMap() { - ... - this->insertInCommandAndReplyMap(gyrodefs::GYRO_DATA, 3, &gyroData); - ... -} -``` - -Now, we need to create the actual pool entries as well, using the `initializeLocalDataPool` -function. Here, we also immediately subscribe for periodic housekeeping packets -with an interval of 4 seconds. They are still disabled in this example and can be enabled -with a housekeeping service command. - -```cpp -ReturnValue_t GyroHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, - LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(gyrodefs::ANGULAR_VELOCITY_X, - new PoolEntry({0.0})); - localDataPoolMap.emplace(gyrodefs::ANGULAR_VELOCITY_Y, - new PoolEntry({0.0})); - localDataPoolMap.emplace(gyrodefs::ANGULAR_VELOCITY_Z, - new PoolEntry({0.0})); - localDataPoolMap.emplace(gyrodefs::GENERAL_CONFIG_REG42, - new PoolEntry({0})); - localDataPoolMap.emplace(gyrodefs::RANGE_CONFIG_REG43, - new PoolEntry({0})); - - poolManager.subscribeForPeriodicPacket(gyroData.getSid(), false, 4.0, false); - return HasReturnvaluesIF::RETURN_OK; -} -``` - -Now, if we receive some sensor data and converted them into the right format, -we can write it into the pool like this, using a guard class to ensure the set is commited back -in any case: - -```cpp -PoolReadGuard readHelper(&gyroData); -if(readHelper.getReadResult() == HasReturnvaluesIF::RETURN_OK) { - if(not gyroData.isValid()) { - gyroData.setValidity(true, true); - } - - gyroData.angVelocityX = angularVelocityX; - gyroData.angVelocityY = angularVelocityY; - gyroData.angVelocityZ = angularVelocityZ; -} -``` - -The guard class will commit the changed data on destruction automatically. - -### Using the local data pools in a `ExtendedControllerBase` subclass - -Coming soon - - diff --git a/docs/README-osal.md b/docs/README-osal.md deleted file mode 100644 index 6f8ce60f..00000000 --- a/docs/README-osal.md +++ /dev/null @@ -1,32 +0,0 @@ -# Operating System Abstraction Layer (OSAL) - -Some specific information on the provided OSALs are provided. - -## Linux OSAL - -This OSAL can be used to compile for Linux host systems like Ubuntu 20.04 or for -embedded Linux targets like the Raspberry Pi. This OSAL generally requires threading support -and real-time functionalities. For most UNIX systems, this is done by adding `-lrt` and `-lpthread` to the linked libraries in the compilation process. The CMake build support provided will do this automatically for the `fsfw` target. It should be noted that most UNIX systems need to be configured specifically to allow the real-time functionalities required by the FSFW. - -More information on how to set up a Linux system accordingly can be found in the -[Linux README of the FSFW example application](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_example/src/branch/master/doc/README-linux.md#top) - -## Hosted OSAL - -This is the newest OSAL. Support for Semaphores has not been implemented yet and will propably be implemented as soon as C++20 with Semaphore support has matured. This OSAL can be used to run the FSFW on any host system, but currently has only been tested on Windows 10 and Ubuntu 20.04. Unlike the other OSALs, it uses dynamic memory allocation (e.g. for the message queue implementation). Cross-platform serial port (USB) support might be added soon. - -## FreeRTOS OSAL - -FreeRTOS is not included and the developer needs to take care of compiling the FreeRTOS sources and adding the `FreeRTOSConfig.h` file location to the include path. This OSAL has only been tested extensively with the pre-emptive scheduler configuration so far but it should in principle also be possible to use a cooperative scheduler. It is recommended to use the `heap_4` allocation scheme. When using newlib (nano), it is also recommended to add `#define configUSE_NEWLIB_REENTRANT` to the FreeRTOS configuration file to ensure thread-safety. - -When using this OSAL, developers also need to provide an implementation for the `vRequestContextSwitchFromISR` function. This has been done because the call to request a context switch from an ISR is generally located in the `portmacro.h` header and is different depending on the target architecture or device. - -## RTEMS OSAL - -The RTEMS OSAL was the first implemented OSAL which is also used on the active satellite Flying Laptop. - -## TCP/IP socket abstraction - -The Linux and Host OSAL provide abstraction layers for the socket API. Currently, only UDP sockets have been imlemented. This is very useful to test TMTC handling either on the host computer directly (targeting localhost with a TMTC application) or on embedded Linux devices, sending TMTC packets via Ethernet. - - diff --git a/docs/README-pus.md b/docs/README-pus.md deleted file mode 100644 index 928d2eda..00000000 --- a/docs/README-pus.md +++ /dev/null @@ -1 +0,0 @@ -## PUS Services diff --git a/docs/api.rst b/docs/api.rst index d2ee6c69..dc73c2c7 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -4,6 +4,7 @@ API .. toctree:: :maxdepth: 4 + api/cfdp api/objectmanager api/task api/ipc diff --git a/docs/api/cfdp.rst b/docs/api/cfdp.rst new file mode 100644 index 00000000..335a2025 --- /dev/null +++ b/docs/api/cfdp.rst @@ -0,0 +1,8 @@ +CFDP API +================= + +``UserBase`` +----------------- + +.. doxygenclass:: cfdp::UserBase + :members: \ No newline at end of file diff --git a/docs/api/returnvalue.rst b/docs/api/returnvalue.rst index b0d43916..da65c141 100644 --- a/docs/api/returnvalue.rst +++ b/docs/api/returnvalue.rst @@ -3,7 +3,7 @@ Returnvalue API ================== -.. doxygenfile:: HasReturnvaluesIF.h +.. doxygenfile:: returnvalue.h .. _fwclassids: diff --git a/docs/conf.py b/docs/conf.py index 62b17192..a4232026 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -17,12 +17,12 @@ # -- Project information ----------------------------------------------------- -project = 'Flight Software Framework' -copyright = '2021, Institute of Space Systems (IRS)' -author = 'Institute of Space Systems (IRS)' +project = "Flight Software Framework" +copyright = "2021, Institute of Space Systems (IRS)" +author = "Institute of Space Systems (IRS)" # The full version, including alpha/beta/rc tags -release = '2.0.1' +release = "5.0.0" # -- General configuration --------------------------------------------------- @@ -30,17 +30,17 @@ release = '2.0.1' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = [ "breathe" ] +extensions = ["breathe"] breathe_default_project = "fsfw" # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # -- Options for HTML output ------------------------------------------------- @@ -48,9 +48,14 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = "alabaster" + +html_theme_options = { + "extra_nav_links": {"Impressum" : "https://www.uni-stuttgart.de/impressum", "Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html"} +} + # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = [] \ No newline at end of file +html_static_path = [] diff --git a/docs/devicehandlers.rst b/docs/devicehandlers.rst index 0008edb3..9c6929e8 100644 --- a/docs/devicehandlers.rst +++ b/docs/devicehandlers.rst @@ -75,11 +75,11 @@ and the respective source file with sensible default return values: void TestDeviceHandler::doShutDown() {} ReturnValue_t TestDeviceHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t TestDeviceHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void TestDeviceHandler::fillCommandAndReplyMap() {} @@ -87,17 +87,17 @@ and the respective source file with sensible default return values: ReturnValue_t TestDeviceHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t* commandData, size_t commandDataLen) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t TestDeviceHandler::scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId, size_t* foundLen) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t TestDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } uint32_t TestDeviceHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { @@ -106,5 +106,5 @@ and the respective source file with sensible default return values: ReturnValue_t TestDeviceHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/docs/getting_started.rst b/docs/getting_started.rst index 01724b3a..4f8ae543 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -106,7 +106,7 @@ You can use the following commands inside the ``fsfw`` folder to set up the buil .. code-block:: console mkdir build-tests && cd build-tests - cmake -DFSFW_BUILD_UNITTESTS=ON -DFSFW_OSAL=host .. + cmake -DFSFW_BUILD_TESTS=ON -DFSFW_OSAL=host .. You can also use ``-DFSFW_OSAL=linux`` on Linux systems. diff --git a/docs/highlevel.rst b/docs/highlevel.rst index 04eb5e7b..ee35c549 100644 --- a/docs/highlevel.rst +++ b/docs/highlevel.rst @@ -6,19 +6,20 @@ High-level overview Structure ---------- -The general structure is driven by the usage of interfaces provided by objects. -The FSFW uses C++11 as baseline. The intention behind this is that this C++ Standard should be -widely available, even with older compilers. -The FSFW uses dynamic allocation during the initialization but provides static containers during runtime. -This simplifies the instantiation of objects and allows the usage of some standard containers. -Dynamic Allocation after initialization is discouraged and different solutions are provided in the -FSFW to achieve that. The fsfw uses run-time type information but exceptions are not allowed. +The general structure is driven by the usage of interfaces provided by objects. +The FSFW uses C++17 as baseline. Most modern compilers like GCC should have support for this +standard, even for micocontrollers. + +The FSFW might use dynamic allocation during program initialization but not during runtime. +It offers pool objects, static containers and it also exposes the +`Embedded Template Library `_ to allow writing code which does not perform +allocation during runtime. The fsfw uses run-time type information but will not throw exceptions. Failure Handling ----------------- Functions should return a defined :cpp:type:`ReturnValue_t` to signal to the caller that something has -gone wrong. Returnvalues must be unique. For this the function :cpp:func:`HasReturnvaluesIF::makeReturnCode` +gone wrong. Returnvalues must be unique. For this the function :cpp:func:`returnvalue::makeCode` or the :ref:`macro MAKE_RETURN_CODE ` can be used. The ``CLASS_ID`` is a unique ID for that type of object. See the :ref:`FSFW Class IDs file `. The user can add custom ``CLASS_ID``\s via the ``fsfwconfig`` folder. diff --git a/docs/localpools.rst b/docs/localpools.rst index d2afd0a0..f7e1ca47 100644 --- a/docs/localpools.rst +++ b/docs/localpools.rst @@ -150,7 +150,7 @@ with a housekeeping service command. new PoolEntry({0})); poolManager.subscribeForPeriodicPacket(gyroData.getSid(), false, 4.0, false); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } Now, if we receive some sensor data and converted them into the right format, @@ -160,7 +160,7 @@ in any case: .. code-block:: cpp PoolReadGuard readHelper(&gyroData); - if(readHelper.getReadResult() == HasReturnvaluesIF::RETURN_OK) { + if(readHelper.getReadResult() == returnvalue::OK) { if(not gyroData.isValid()) { gyroData.setValidity(true, true); } diff --git a/hal/CMakeLists.txt b/hal/CMakeLists.txt deleted file mode 100644 index 7a97ae0f..00000000 --- a/hal/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -# Can also be changed by upper CMakeLists.txt file -find_library(LIB_FSFW_NAME fsfw REQUIRED) - -option(FSFW_HAL_ADD_LINUX "Add the Linux HAL to the sources. Requires gpiod library" OFF) -# On by default for now because I did not have an issue including and compiling those files -# and libraries on a Desktop Linux system and the primary target of the FSFW is still embedded -# Linux. The only exception from this is the gpiod library which requires a dedicated installation, -# but CMake is able to determine whether this library is installed with find_library. -option(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS "Add peripheral drivers for embedded Linux" ON) -option(FSFW_HAL_LINUX_ADD_LIBGPIOD "Target implements libgpiod" ON) - -option(FSFW_HAL_ADD_RASPBERRY_PI "Add Raspberry Pi specific code to the sources" OFF) -option(FSFW_HAL_ADD_STM32H7 "Add the STM32H7 HAL to the sources" OFF) -option(FSFW_HAL_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON) - -set(LINUX_HAL_PATH_NAME linux) -set(STM32H7_PATH_NAME stm32h7) - -add_subdirectory(src) - -foreach(INCLUDE_PATH ${FSFW_HAL_ADDITIONAL_INC_PATHS}) - if(IS_ABSOLUTE ${INCLUDE_PATH}) - set(CURR_ABS_INC_PATH "${INCLUDE_PATH}") - else() - get_filename_component(CURR_ABS_INC_PATH - ${INCLUDE_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR}) - endif() - - if(CMAKE_VERBOSE) - message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}") - endif() - - list(APPEND FSFW_HAL_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH}) -endforeach() - -target_include_directories(${LIB_FSFW_NAME} PRIVATE - ${FSFW_HAL_ADD_INC_PATHS_ABS} -) - -target_compile_definitions(${LIB_FSFW_NAME} PRIVATE - ${FSFW_HAL_DEFINES} -) - -target_link_libraries(${LIB_FSFW_NAME} PRIVATE - ${FSFW_HAL_LINK_LIBS} -) diff --git a/hal/src/CMakeLists.txt b/hal/src/CMakeLists.txt deleted file mode 100644 index 76ee45c6..00000000 --- a/hal/src/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -target_include_directories(${LIB_FSFW_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} -) - -target_include_directories(${LIB_FSFW_NAME} INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR} -) - -add_subdirectory(fsfw_hal) diff --git a/hal/src/fsfw_hal/common/CMakeLists.txt b/hal/src/fsfw_hal/common/CMakeLists.txt deleted file mode 100644 index f1cfec52..00000000 --- a/hal/src/fsfw_hal/common/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(gpio) diff --git a/hal/src/fsfw_hal/common/gpio/CMakeLists.txt b/hal/src/fsfw_hal/common/gpio/CMakeLists.txt deleted file mode 100644 index 098c05fa..00000000 --- a/hal/src/fsfw_hal/common/gpio/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - GpioCookie.cpp -) \ No newline at end of file diff --git a/hal/src/fsfw_hal/devicehandlers/CMakeLists.txt b/hal/src/fsfw_hal/devicehandlers/CMakeLists.txt deleted file mode 100644 index 94e67c72..00000000 --- a/hal/src/fsfw_hal/devicehandlers/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - GyroL3GD20Handler.cpp - MgmRM3100Handler.cpp - MgmLIS3MDLHandler.cpp -) diff --git a/hal/src/fsfw_hal/host/CMakeLists.txt b/hal/src/fsfw_hal/host/CMakeLists.txt deleted file mode 100644 index 8b137891..00000000 --- a/hal/src/fsfw_hal/host/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/hal/src/fsfw_hal/linux/CMakeLists.txt b/hal/src/fsfw_hal/linux/CMakeLists.txt deleted file mode 100644 index 56d4bf48..00000000 --- a/hal/src/fsfw_hal/linux/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -if(FSFW_HAL_ADD_RASPBERRY_PI) - add_subdirectory(rpi) -endif() - -target_sources(${LIB_FSFW_NAME} PRIVATE - UnixFileGuard.cpp - CommandExecutor.cpp - utility.cpp -) - -if(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS) -if(FSFW_HAL_LINUX_ADD_LIBGPIOD) - add_subdirectory(gpio) -endif() - add_subdirectory(spi) - add_subdirectory(i2c) - add_subdirectory(uart) -endif() - -add_subdirectory(uio) diff --git a/hal/src/fsfw_hal/linux/gpio/CMakeLists.txt b/hal/src/fsfw_hal/linux/gpio/CMakeLists.txt deleted file mode 100644 index b1609850..00000000 --- a/hal/src/fsfw_hal/linux/gpio/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -# This abstraction layer requires the gpiod library. You can install this library -# with "sudo apt-get install -y libgpiod-dev". If you are cross-compiling, you need -# to install the package before syncing the sysroot to your host computer. -find_library(LIB_GPIO gpiod) - -if(${LIB_GPIO} MATCHES LIB_GPIO-NOTFOUND) - message(STATUS "gpiod library not found, not linking against it") -else() - target_sources(${LIB_FSFW_NAME} PRIVATE - LinuxLibgpioIF.cpp - ) - target_link_libraries(${LIB_FSFW_NAME} PRIVATE - ${LIB_GPIO} - ) -endif() - diff --git a/hal/src/fsfw_hal/linux/i2c/CMakeLists.txt b/hal/src/fsfw_hal/linux/i2c/CMakeLists.txt deleted file mode 100644 index 3eb0882c..00000000 --- a/hal/src/fsfw_hal/linux/i2c/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PUBLIC - I2cComIF.cpp - I2cCookie.cpp -) - - - - diff --git a/hal/src/fsfw_hal/linux/rpi/CMakeLists.txt b/hal/src/fsfw_hal/linux/rpi/CMakeLists.txt deleted file mode 100644 index 47be218c..00000000 --- a/hal/src/fsfw_hal/linux/rpi/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - GpioRPi.cpp -) \ No newline at end of file diff --git a/hal/src/fsfw_hal/linux/spi/CMakeLists.txt b/hal/src/fsfw_hal/linux/spi/CMakeLists.txt deleted file mode 100644 index 404e1f47..00000000 --- a/hal/src/fsfw_hal/linux/spi/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PUBLIC - SpiComIF.cpp - SpiCookie.cpp -) - - - - diff --git a/hal/src/fsfw_hal/linux/uart/CMakeLists.txt b/hal/src/fsfw_hal/linux/uart/CMakeLists.txt deleted file mode 100644 index 21ed0278..00000000 --- a/hal/src/fsfw_hal/linux/uart/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PUBLIC - UartComIF.cpp - UartCookie.cpp -) diff --git a/hal/src/fsfw_hal/linux/uart/UartCookie.cpp b/hal/src/fsfw_hal/linux/uart/UartCookie.cpp deleted file mode 100644 index aa2dd214..00000000 --- a/hal/src/fsfw_hal/linux/uart/UartCookie.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "UartCookie.h" - -#include - -UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode, - UartBaudRate baudrate, size_t maxReplyLen) - : handlerId(handlerId), - deviceFile(deviceFile), - uartMode(uartMode), - baudrate(baudrate), - maxReplyLen(maxReplyLen) {} - -UartCookie::~UartCookie() {} - -UartBaudRate UartCookie::getBaudrate() const { return baudrate; } - -size_t UartCookie::getMaxReplyLen() const { return maxReplyLen; } - -std::string UartCookie::getDeviceFile() const { return deviceFile; } - -void UartCookie::setParityOdd() { parity = Parity::ODD; } - -void UartCookie::setParityEven() { parity = Parity::EVEN; } - -Parity UartCookie::getParity() const { return parity; } - -void UartCookie::setBitsPerWord(BitsPerWord bitsPerWord_) { - bitsPerWord = bitsPerWord_; -} - -BitsPerWord UartCookie::getBitsPerWord() const { return bitsPerWord; } - -StopBits UartCookie::getStopBits() const { return stopBits; } - -void UartCookie::setTwoStopBits() { stopBits = StopBits::TWO_STOP_BITS; } - -void UartCookie::setOneStopBit() { stopBits = StopBits::ONE_STOP_BIT; } - -UartModes UartCookie::getUartMode() const { return uartMode; } - -void UartCookie::setReadCycles(uint8_t readCycles) { this->readCycles = readCycles; } - -void UartCookie::setToFlushInput(bool enable) { this->flushInput = enable; } - -uint8_t UartCookie::getReadCycles() const { return readCycles; } - -bool UartCookie::getInputShouldBeFlushed() { return this->flushInput; } - -object_id_t UartCookie::getHandlerId() const { return this->handlerId; } - -void UartCookie::setNoFixedSizeReply() { replySizeFixed = false; } - -bool UartCookie::isReplySizeFixed() { return replySizeFixed; } diff --git a/hal/src/fsfw_hal/linux/uio/CMakeLists.txt b/hal/src/fsfw_hal/linux/uio/CMakeLists.txt deleted file mode 100644 index e98a0865..00000000 --- a/hal/src/fsfw_hal/linux/uio/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PUBLIC - UioMapper.cpp -) diff --git a/hal/src/fsfw_hal/stm32h7/devicetest/CMakeLists.txt b/hal/src/fsfw_hal/stm32h7/devicetest/CMakeLists.txt deleted file mode 100644 index 7bd4c3a9..00000000 --- a/hal/src/fsfw_hal/stm32h7/devicetest/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - GyroL3GD20H.cpp -) \ No newline at end of file diff --git a/hal/src/fsfw_hal/stm32h7/gpio/CMakeLists.txt b/hal/src/fsfw_hal/stm32h7/gpio/CMakeLists.txt deleted file mode 100644 index 35245b25..00000000 --- a/hal/src/fsfw_hal/stm32h7/gpio/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - gpio.cpp -) diff --git a/hal/src/fsfw_hal/stm32h7/i2c/CMakeLists.txt b/hal/src/fsfw_hal/stm32h7/i2c/CMakeLists.txt deleted file mode 100644 index 5ecb0990..00000000 --- a/hal/src/fsfw_hal/stm32h7/i2c/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE -) diff --git a/hal/src/fsfw_hal/stm32h7/spi/CMakeLists.txt b/hal/src/fsfw_hal/stm32h7/spi/CMakeLists.txt deleted file mode 100644 index aa5541bc..00000000 --- a/hal/src/fsfw_hal/stm32h7/spi/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - spiCore.cpp - spiDefinitions.cpp - spiInterrupts.cpp - mspInit.cpp - SpiCookie.cpp - SpiComIF.cpp - stm32h743zi.cpp -) diff --git a/hal/src/fsfw_hal/stm32h7/uart/CMakeLists.txt b/hal/src/fsfw_hal/stm32h7/uart/CMakeLists.txt deleted file mode 100644 index 5ecb0990..00000000 --- a/hal/src/fsfw_hal/stm32h7/uart/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE -) diff --git a/misc/defaultcfg/fsfwconfig/FSFWConfig.h b/misc/defaultcfg/fsfwconfig/FSFWConfig.h index adf9912f..e80abf24 100644 --- a/misc/defaultcfg/fsfwconfig/FSFWConfig.h +++ b/misc/defaultcfg/fsfwconfig/FSFWConfig.h @@ -4,6 +4,10 @@ #include #include +// It is assumed the user has a subsystem and class ID list in some user header files. +// #include "events/subsystemIdRanges.h" +// #include "returnvalues/classIds.h" + //! Used to determine whether C++ ostreams are used which can increase //! the binary size significantly. If this is disabled, //! the C stdio functions can be used alternatively diff --git a/misc/defaultcfg/fsfwconfig/objects/FsfwFactory.cpp b/misc/defaultcfg/fsfwconfig/objects/FsfwFactory.cpp index 5aef4980..85a733b4 100644 --- a/misc/defaultcfg/fsfwconfig/objects/FsfwFactory.cpp +++ b/misc/defaultcfg/fsfwconfig/objects/FsfwFactory.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -35,19 +34,15 @@ void Factory::produceFsfwObjects(void) { } void Factory::setStaticFrameworkObjectIds() { - PusServiceBase::packetSource = objects::NO_OBJECT; - PusServiceBase::packetDestination = objects::NO_OBJECT; + PusServiceBase::PUS_DISTRIBUTOR = objects::NO_OBJECT; + PusServiceBase::PACKET_DESTINATION = objects::NO_OBJECT; CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT; CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT; - VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION; - DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT; DeviceHandlerBase::rawDataReceiverId = objects::PUS_SERVICE_2_DEVICE_ACCESS; DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT; - - TmPacketBase::timeStamperId = objects::NO_OBJECT; } diff --git a/misc/defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp b/misc/defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp index b7f1fb3e..81b927dd 100644 --- a/misc/defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp +++ b/misc/defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp @@ -11,15 +11,15 @@ ReturnValue_t pst::pollingSequenceInitDefault( /* Add polling sequence table here */ - if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { - return HasReturnvaluesIF::RETURN_OK; + if (thisSequence->checkSequence() == returnvalue::OK) { + return returnvalue::OK; } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "pst::pollingSequenceInitDefault: Sequence invalid!" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } diff --git a/misc/defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.h b/misc/defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.h index c5d41b7d..622cc49a 100644 --- a/misc/defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.h +++ b/misc/defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.h @@ -1,7 +1,7 @@ #ifndef POLLINGSEQUENCEFACTORY_H_ #define POLLINGSEQUENCEFACTORY_H_ -#include +#include class FixedTimeslotTaskIF; diff --git a/scripts/apply-clang-format.sh b/scripts/apply-clang-format.sh deleted file mode 100755 index 27202324..00000000 --- a/scripts/apply-clang-format.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -if [[ ! -f README.md ]]; then - cd .. -fi - -find ./src -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i -find ./hal -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i -find ./tests -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i diff --git a/scripts/auto-formatter.sh b/scripts/auto-formatter.sh new file mode 100755 index 00000000..f7507c55 --- /dev/null +++ b/scripts/auto-formatter.sh @@ -0,0 +1,30 @@ +#!/bin/bash +if [[ ! -f README.md ]]; then + cd .. +fi + +folder_list=( + "./src" + "./unittests" +) + +cmake_fmt="cmake-format" +file_selectors="-iname CMakeLists.txt" +if command -v ${cmake_fmt} &> /dev/null; then + ${cmake_fmt} -i CMakeLists.txt + find ./src ${file_selectors} | xargs ${cmake_fmt} -i + find ./unittests ${file_selectors} | xargs ${cmake_fmt} -i +else + echo "No ${cmake_fmt} tool found, not formatting CMake files" +fi + +cpp_format="clang-format" +file_selectors="-iname *.h -o -iname *.cpp -o -iname *.c -o -iname *.tpp" +if command -v ${cpp_format} &> /dev/null; then + for dir in ${folder_list[@]}; do + echo "Auto-formatting ${dir} recursively" + find ${dir} ${file_selectors} | xargs clang-format --style=file -i + done +else + echo "No ${cpp_format} tool found, not formatting C++/C files" +fi diff --git a/scripts/check_release.py b/scripts/check_release.py new file mode 100755 index 00000000..eb5c89f9 --- /dev/null +++ b/scripts/check_release.py @@ -0,0 +1,110 @@ +#! /bin/python + + +import argparse +import json +import urllib.request +import re +from pathlib import Path + +def main() -> None: + parser = argparse.ArgumentParser( + description="List undocumented PRs" + ) + parser.add_argument("-v", "--version", type=str, required=True) + args = parser.parse_args() + + match = re.search("([0-9]+\.[0-9]+\.[0-9]+)", args.version) + + if not match: + print("invalid version") + exit(1) + + version = "v" + match.group(1) + + print("looking for milestone for " + version + " ...") + + + with urllib.request.urlopen("https://egit.irs.uni-stuttgart.de/api/v1/repos/fsfw/fsfw/milestones?name=" + version) as milestone_json: + milestones = json.load(milestone_json) + if (len(milestones) == 0): + print("did not find any milestone") + exit(1) + if (len(milestones) > 1): + print("found multiple milestons") + milestone_title = milestones[0]['title'] + milestone = str(milestones[0]['id']) + print("Using Milestone \""+ milestone_title + "\" with id " + milestone) + + milestone_prs = [] + + page = 1 + last_count = 1; + while last_count != 0: + with urllib.request.urlopen("https://egit.irs.uni-stuttgart.de/api/v1/repos/fsfw/fsfw/pulls?state=closed&milestone=" + str(milestone) + "&limit=100&page=" + str(page)) as pull_requests_json: + pull_requests = json.load(pull_requests_json) + for pr in pull_requests: + milestone_prs.append({'number': str(pr['number']), 'title' : pr['title']}) + page += 1 + last_count = len(pull_requests) + + print("Found " + str(len(milestone_prs)) + " closed PRs in Milestone") + + print("looking for CHANGELOG.md ...") + + path = Path(".") + + files = list(path.glob("CHANGELOG.md")) + + if (len(files) != 1): + files = list(path.glob("../CHANGELOG.md")) + + if (len(files) != 1): + print("did not find CHANGELOG.md. Run script in either root directory or scripts subfolder.") + exit(1) + + print("Scanning CHANGELOG.md ...") + + changelog_prs = [] + + with open(files[0]) as changelog: + line = changelog.readline() + while (line): + #print("line: " + line) + match = re.search("\#.+(v[0-9]+\.[0-9]+\.[0-9]+)", line) + if (match): + if match.group(1) == version: + #print("found version") + line = changelog.readline() + continue + else: + #print("done with " + match.group(1)) + break + + match = re.search("PR: https://egit\.irs\.uni-stuttgart\.de/fsfw/fsfw/pulls/([0-9]+)", line) + if match: + changelog_prs.append(match.group(1)) + + line = changelog.readline() + + print("Found " + str(len(changelog_prs)) + " PRs in CHANGELOG.md") + + print("") + + copy_array = changelog_prs.copy() + print("PRs in CHANGELOG.md that are not in Milestone:") + for pr in milestone_prs: + if pr['number'] in copy_array: + copy_array.remove(pr['number']) + for pr in copy_array: + print("https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/" + pr) + + print("") + + print("PRs in milestone that are not in CHANGELOG.md:") + + for pr in milestone_prs: + if pr['number'] not in changelog_prs: + print("- " + pr['title'] + "\n PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/" + pr['number']) + +main() diff --git a/scripts/helper.py b/scripts/helper.py index 4dff908d..59a1b783 100755 --- a/scripts/helper.py +++ b/scripts/helper.py @@ -13,7 +13,7 @@ from shutil import which from typing import List -UNITTEST_FOLDER_NAME = "build-tests" +UNITTEST_FOLDER_NAME = "cmake-build-tests" DOCS_FOLDER_NAME = "build-docs" @@ -48,6 +48,20 @@ def main(): action="store_true", help="Run valgrind on generated test binary", ) + parser.add_argument( + "-g", + "--generators", + default="Ninja", + action="store", + help="CMake generators", + ) + parser.add_argument( + "-w", + "--windows", + default=False, + action="store_true", + help="Run on windows", + ) args = parser.parse_args() if args.all: @@ -115,14 +129,14 @@ def handle_tests_type(args, build_dir_list: list): if args.create: if os.path.exists(UNITTEST_FOLDER_NAME): shutil.rmtree(UNITTEST_FOLDER_NAME) - create_tests_build_cfg() + create_tests_build_cfg(args) build_directory = UNITTEST_FOLDER_NAME elif len(build_dir_list) == 0: print( "No valid CMake tests build directory found. " "Trying to set up test build system" ) - create_tests_build_cfg() + create_tests_build_cfg(args) build_directory = UNITTEST_FOLDER_NAME elif len(build_dir_list) == 1: build_directory = build_dir_list[0] @@ -147,10 +161,23 @@ def handle_tests_type(args, build_dir_list: list): os.chdir("..") -def create_tests_build_cfg(): +def create_tests_build_cfg(args): os.mkdir(UNITTEST_FOLDER_NAME) os.chdir(UNITTEST_FOLDER_NAME) - cmd_runner("cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON ..") + if args.windows: + cmake_cmd = ( + 'cmake -G "' + + args.generators + + '" -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON \ + -DGCOVR_PATH="py -m gcovr" ..' + ) + else: + cmake_cmd = ( + 'cmake -G "' + + args.generators + + '" -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON ..' + ) + cmd_runner(cmake_cmd) os.chdir("..") @@ -180,7 +207,7 @@ def check_for_cmake_build_dir(build_dir_list: list) -> list: def perform_lcov_operation(directory: str, chdir: bool): if chdir: os.chdir(directory) - cmd_runner("cmake --build . -- fsfw-tests_coverage -j") + cmd_runner("cmake --build . -j -- fsfw-tests_coverage") def determine_build_dir(build_dir_list: List[str]): diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ed2f2522..57b24bd5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,9 +1,11 @@ -target_include_directories(${LIB_FSFW_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} -) +target_include_directories(${LIB_FSFW_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(${LIB_FSFW_NAME} INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR} -) +target_include_directories(${LIB_FSFW_NAME} + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(fsfw) +if(FSFW_ADD_HAL) + add_subdirectory(fsfw_hal) +endif() + +add_subdirectory(fsfw_tests) diff --git a/src/fsfw/CMakeLists.txt b/src/fsfw/CMakeLists.txt index efb9f6c7..e645d34f 100644 --- a/src/fsfw/CMakeLists.txt +++ b/src/fsfw/CMakeLists.txt @@ -1,6 +1,4 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - version.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE version.cpp) # Core @@ -33,26 +31,27 @@ add_subdirectory(thermal) add_subdirectory(timemanager) add_subdirectory(tmtcpacket) add_subdirectory(tmtcservices) +add_subdirectory(filesystem) # Optional if(FSFW_ADD_MONITORING) -add_subdirectory(monitoring) + add_subdirectory(monitoring) endif() if(FSFW_ADD_PUS) - add_subdirectory(pus) + add_subdirectory(pus) endif() if(FSFW_ADD_TMSTORAGE) - add_subdirectory(tmstorage) + add_subdirectory(tmstorage) endif() if(FSFW_ADD_COORDINATES) - add_subdirectory(coordinates) + add_subdirectory(coordinates) endif() if(FSFW_ADD_RMAP) - add_subdirectory(rmap) + add_subdirectory(rmap) endif() if(FSFW_ADD_DATALINKLAYER) - add_subdirectory(datalinklayer) + add_subdirectory(datalinklayer) endif() # OSAL diff --git a/src/fsfw/FSFWVersion.h.in b/src/fsfw/FSFWVersion.h.in index 19a56214..caff1efb 100644 --- a/src/fsfw/FSFWVersion.h.in +++ b/src/fsfw/FSFWVersion.h.in @@ -1,9 +1,11 @@ #ifndef FSFW_VERSION_H_ #define FSFW_VERSION_H_ -// Versioning is kept in project CMakeLists.txt file -#define FSFW_VERSION_MAJOR @FSFW_VERSION@ -#define FSFW_VERSION_MINOR @FSFW_SUBVERSION@ -#define FSFW_VERSION_REVISION @FSFW_REVISION@ +// Versioning is managed in project CMakeLists.txt file +static constexpr int FSFW_VERSION_MAJOR = @FSFW_VERSION@; +static constexpr int FSFW_VERSION_MINOR = @FSFW_SUBVERSION@; +static constexpr int FSFW_VERSION_REVISION = @FSFW_REVISION@; +// Also contains CST (Commits since tag) information +static const char FSFW_VCS_INFO[] = "@FSFW_VCS_INFO@"; #endif /* FSFW_VERSION_H_ */ diff --git a/src/fsfw/action/ActionHelper.cpp b/src/fsfw/action/ActionHelper.cpp index d41c78b4..fd6c8afb 100644 --- a/src/fsfw/action/ActionHelper.cpp +++ b/src/fsfw/action/ActionHelper.cpp @@ -6,13 +6,13 @@ ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) : owner(setOwner), queueToUse(useThisQueue) {} -ActionHelper::~ActionHelper() {} +ActionHelper::~ActionHelper() = default; ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) { if (command->getCommand() == ActionMessage::EXECUTE_ACTION) { ActionId_t currentAction = ActionMessage::getActionId(command); prepareExecution(command->getSender(), currentAction, ActionMessage::getStoreId(command)); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { return CommandMessage::UNKNOWN_COMMAND; } @@ -21,7 +21,7 @@ ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) { ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) { ipcStore = ObjectManager::instance()->get(objects::IPC_STORE); if (ipcStore == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (queueToUse_ != nullptr) { setQueueToUse(queueToUse_); @@ -35,10 +35,10 @@ ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) { sif::printWarning("ActionHelper::initialize: No queue set\n"); #endif #endif /* FSFW_VERBOSE_LEVEL >= 1 */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, @@ -59,10 +59,10 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; } void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress) { - const uint8_t* dataPtr = NULL; + const uint8_t* dataPtr = nullptr; size_t size = 0; ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { CommandMessage reply; ActionMessage::setStepReply(&reply, actionId, 0, result); queueToUse->sendMessage(commandedBy, &reply); @@ -75,7 +75,7 @@ void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t act ActionMessage::setCompletionReply(&reply, actionId, true, result); queueToUse->sendMessage(commandedBy, &reply); } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { CommandMessage reply; ActionMessage::setStepReply(&reply, actionId, 0, result); queueToUse->sendMessage(commandedBy, &reply); @@ -91,11 +91,11 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep size_t maxSize = data->getSerializedSize(); if (maxSize == 0) { /* No error, there's simply nothing to report. */ - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } size_t size = 0; ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize, &dataPtr); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "ActionHelper::reportData: Getting free element from IPC store failed!" << std::endl; @@ -107,7 +107,7 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep return result; } result = data->serialize(&dataPtr, &size, maxSize, SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { ipcStore->deleteData(storeAddress); return result; } @@ -124,7 +124,7 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep result = queueToUse->sendMessage(reportTo, &reply); } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { ipcStore->deleteData(storeAddress); } return result; @@ -137,7 +137,7 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep CommandMessage reply; store_address_t storeAddress; ReturnValue_t result = ipcStore->addData(&storeAddress, data, dataSize); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "ActionHelper::reportData: Adding data to IPC store failed!" << std::endl; #else @@ -158,7 +158,7 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep result = queueToUse->sendMessage(reportTo, &reply); } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { ipcStore->deleteData(storeAddress); } return result; diff --git a/src/fsfw/action/ActionHelper.h b/src/fsfw/action/ActionHelper.h index d86e87d2..4bcecbae 100644 --- a/src/fsfw/action/ActionHelper.h +++ b/src/fsfw/action/ActionHelper.h @@ -1,9 +1,9 @@ #ifndef FSFW_ACTION_ACTIONHELPER_H_ #define FSFW_ACTION_ACTIONHELPER_H_ -#include "../ipc/MessageQueueIF.h" -#include "../serialize/SerializeIF.h" #include "ActionMessage.h" +#include "fsfw/ipc/MessageQueueIF.h" +#include "fsfw/serialize/SerializeIF.h" /** * @brief Action Helper is a helper class which handles action messages * @@ -36,7 +36,7 @@ class ActionHelper { * send to the sender of the message automatically. * * @param command Pointer to a command message received by the owner - * @return HasReturnvaluesIF::RETURN_OK if the message is a action message, + * @return returnvalue::OK if the message is a action message, * CommandMessage::UNKNOW_COMMAND if this message ID is unkown */ ReturnValue_t handleActionMessage(CommandMessage* command); @@ -45,7 +45,7 @@ class ActionHelper { * helper function * @param queueToUse_ Pointer to the messageQueue to be used, optional * if queue was set in constructor - * @return Returns RETURN_OK if successful + * @return Returns returnvalue::OK if successful */ ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr); /** @@ -58,7 +58,7 @@ class ActionHelper { * @param result Result of the execution */ void step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); + ReturnValue_t result = returnvalue::OK); /** * Function to be called by the owner to send a action completion message * @param success Specify whether action was completed successfully or not. @@ -67,7 +67,7 @@ class ActionHelper { * @param result Result of the execution */ void finish(bool success, MessageQueueId_t reportTo, ActionId_t commandId, - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); + ReturnValue_t result = returnvalue::OK); /** * Function to be called by the owner if an action does report data. * Takes a SerializeIF* pointer and serializes it into the IPC store. @@ -75,7 +75,7 @@ class ActionHelper { * message to * @param replyId ID of the executed command * @param data Pointer to the data - * @return Returns RETURN_OK if successful, otherwise failure code + * @return Returns returnvalue::OK if successful, otherwise failure code */ ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender = false); @@ -86,7 +86,7 @@ class ActionHelper { * message to * @param replyId ID of the executed command * @param data Pointer to the data - * @return Returns RETURN_OK if successful, otherwise failure code + * @return Returns returnvalue::OK if successful, otherwise failure code */ ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, const uint8_t* data, size_t dataSize, bool hideSender = false); diff --git a/src/fsfw/action/ActionMessage.cpp b/src/fsfw/action/ActionMessage.cpp index 40a516b1..33088055 100644 --- a/src/fsfw/action/ActionMessage.cpp +++ b/src/fsfw/action/ActionMessage.cpp @@ -2,9 +2,9 @@ #include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/storagemanager/StorageManagerIF.h" -ActionMessage::ActionMessage() {} +ActionMessage::ActionMessage() = default; -ActionMessage::~ActionMessage() {} +ActionMessage::~ActionMessage() = default; void ActionMessage::setCommand(CommandMessage* message, ActionId_t fid, store_address_t parameters) { @@ -25,7 +25,7 @@ store_address_t ActionMessage::getStoreId(const CommandMessage* message) { void ActionMessage::setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step, ReturnValue_t result) { - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { message->setCommand(STEP_SUCCESS); } else { message->setCommand(STEP_FAILED); @@ -64,9 +64,8 @@ void ActionMessage::clear(CommandMessage* message) { switch (message->getCommand()) { case EXECUTE_ACTION: case DATA_REPLY: { - StorageManagerIF* ipcStore = - ObjectManager::instance()->get(objects::IPC_STORE); - if (ipcStore != NULL) { + auto* ipcStore = ObjectManager::instance()->get(objects::IPC_STORE); + if (ipcStore != nullptr) { ipcStore->deleteData(getStoreId(message)); } break; diff --git a/src/fsfw/action/ActionMessage.h b/src/fsfw/action/ActionMessage.h index bd12cc19..38e3aa99 100644 --- a/src/fsfw/action/ActionMessage.h +++ b/src/fsfw/action/ActionMessage.h @@ -33,12 +33,12 @@ class ActionMessage { static store_address_t getStoreId(const CommandMessage* message); static void setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step, - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); + ReturnValue_t result = returnvalue::OK); static uint8_t getStep(const CommandMessage* message); static ReturnValue_t getReturnCode(const CommandMessage* message); static void setDataReply(CommandMessage* message, ActionId_t actionId, store_address_t data); static void setCompletionReply(CommandMessage* message, ActionId_t fid, bool success, - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); + ReturnValue_t result = returnvalue::OK); static void clear(CommandMessage* message); }; diff --git a/src/fsfw/action/CMakeLists.txt b/src/fsfw/action/CMakeLists.txt index f9ac451d..7fb397af 100644 --- a/src/fsfw/action/CMakeLists.txt +++ b/src/fsfw/action/CMakeLists.txt @@ -1,7 +1,3 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - ActionHelper.cpp - ActionMessage.cpp - CommandActionHelper.cpp - SimpleActionHelper.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} PRIVATE ActionHelper.cpp ActionMessage.cpp + CommandActionHelper.cpp SimpleActionHelper.cpp) diff --git a/src/fsfw/action/CommandActionHelper.cpp b/src/fsfw/action/CommandActionHelper.cpp index 19d8e9b8..831cd862 100644 --- a/src/fsfw/action/CommandActionHelper.cpp +++ b/src/fsfw/action/CommandActionHelper.cpp @@ -2,26 +2,26 @@ #include "fsfw/objectmanager/ObjectManager.h" CommandActionHelper::CommandActionHelper(CommandsActionsIF *setOwner) - : owner(setOwner), queueToUse(NULL), ipcStore(NULL), commandCount(0), lastTarget(0) {} + : owner(setOwner), queueToUse(nullptr), ipcStore(nullptr), commandCount(0), lastTarget(0) {} -CommandActionHelper::~CommandActionHelper() {} +CommandActionHelper::~CommandActionHelper() = default; ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF *data) { - HasActionsIF *receiver = ObjectManager::instance()->get(commandTo); - if (receiver == NULL) { + auto *receiver = ObjectManager::instance()->get(commandTo); + if (receiver == nullptr) { return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS; } store_address_t storeId; uint8_t *storePointer; size_t maxSize = data->getSerializedSize(); ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize, &storePointer); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } size_t size = 0; result = data->serialize(&storePointer, &size, maxSize, SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return sendCommand(receiver->getCommandQueue(), actionId, storeId); @@ -29,16 +29,13 @@ ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, ActionId ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, ActionId_t actionId, const uint8_t *data, uint32_t size) { - // if (commandCount != 0) { - // return CommandsFunctionsIF::ALREADY_COMMANDING; - // } - HasActionsIF *receiver = ObjectManager::instance()->get(commandTo); - if (receiver == NULL) { + auto *receiver = ObjectManager::instance()->get(commandTo); + if (receiver == nullptr) { return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS; } store_address_t storeId; ReturnValue_t result = ipcStore->addData(&storeId, data, size); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return sendCommand(receiver->getCommandQueue(), actionId, storeId); @@ -49,7 +46,7 @@ ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId, ActionI CommandMessage command; ActionMessage::setCommand(&command, actionId, storeId); ReturnValue_t result = queueToUse->sendMessage(queueId, &command); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { ipcStore->deleteData(storeId); } lastTarget = queueId; @@ -59,55 +56,55 @@ ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId, ActionI ReturnValue_t CommandActionHelper::initialize() { ipcStore = ObjectManager::instance()->get(objects::IPC_STORE); - if (ipcStore == NULL) { - return HasReturnvaluesIF::RETURN_FAILED; + if (ipcStore == nullptr) { + return returnvalue::FAILED; } queueToUse = owner->getCommandQueuePtr(); - if (queueToUse == NULL) { - return HasReturnvaluesIF::RETURN_FAILED; + if (queueToUse == nullptr) { + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) { if (reply->getSender() != lastTarget) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } switch (reply->getCommand()) { case ActionMessage::COMPLETION_SUCCESS: commandCount--; owner->completionSuccessfulReceived(ActionMessage::getActionId(reply)); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; case ActionMessage::COMPLETION_FAILED: commandCount--; owner->completionFailedReceived(ActionMessage::getActionId(reply), ActionMessage::getReturnCode(reply)); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; case ActionMessage::STEP_SUCCESS: owner->stepSuccessfulReceived(ActionMessage::getActionId(reply), ActionMessage::getStep(reply)); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; case ActionMessage::STEP_FAILED: commandCount--; owner->stepFailedReceived(ActionMessage::getActionId(reply), ActionMessage::getStep(reply), ActionMessage::getReturnCode(reply)); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; case ActionMessage::DATA_REPLY: extractDataForOwner(ActionMessage::getActionId(reply), ActionMessage::getStoreId(reply)); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } uint8_t CommandActionHelper::getCommandCount() const { return commandCount; } void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) { - const uint8_t *data = NULL; + const uint8_t *data = nullptr; size_t size = 0; ReturnValue_t result = ipcStore->getData(storeId, &data, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return; } owner->dataReceived(actionId, data, size); diff --git a/src/fsfw/action/CommandActionHelper.h b/src/fsfw/action/CommandActionHelper.h index dd8ad7f1..55176e09 100644 --- a/src/fsfw/action/CommandActionHelper.h +++ b/src/fsfw/action/CommandActionHelper.h @@ -4,7 +4,7 @@ #include "ActionMessage.h" #include "fsfw/ipc/MessageQueueIF.h" #include "fsfw/objectmanager/ObjectManagerIF.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/serialize/SerializeIF.h" #include "fsfw/storagemanager/StorageManagerIF.h" @@ -14,14 +14,14 @@ class CommandActionHelper { friend class CommandsActionsIF; public: - CommandActionHelper(CommandsActionsIF* owner); + explicit CommandActionHelper(CommandsActionsIF* owner); virtual ~CommandActionHelper(); ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, const uint8_t* data, uint32_t size); ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data); ReturnValue_t initialize(); ReturnValue_t handleReply(CommandMessage* reply); - uint8_t getCommandCount() const; + [[nodiscard]] uint8_t getCommandCount() const; private: CommandsActionsIF* owner; diff --git a/src/fsfw/action/CommandsActionsIF.h b/src/fsfw/action/CommandsActionsIF.h index 5870a9f2..a183051d 100644 --- a/src/fsfw/action/CommandsActionsIF.h +++ b/src/fsfw/action/CommandsActionsIF.h @@ -1,9 +1,9 @@ #ifndef FSFW_ACTION_COMMANDSACTIONSIF_H_ #define FSFW_ACTION_COMMANDSACTIONSIF_H_ -#include "../ipc/MessageQueueIF.h" -#include "../returnvalues/HasReturnvaluesIF.h" #include "CommandActionHelper.h" +#include "fsfw/ipc/MessageQueueIF.h" +#include "fsfw/returnvalues/returnvalue.h" /** * Interface to separate commanding actions of other objects. @@ -21,7 +21,7 @@ class CommandsActionsIF { static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF; static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1); static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2); - virtual ~CommandsActionsIF() {} + virtual ~CommandsActionsIF() = default; virtual MessageQueueIF* getCommandQueuePtr() = 0; protected: diff --git a/src/fsfw/action/HasActionsIF.h b/src/fsfw/action/HasActionsIF.h index acc502d7..29e267a0 100644 --- a/src/fsfw/action/HasActionsIF.h +++ b/src/fsfw/action/HasActionsIF.h @@ -1,11 +1,11 @@ #ifndef FSFW_ACTION_HASACTIONSIF_H_ #define FSFW_ACTION_HASACTIONSIF_H_ -#include "../ipc/MessageQueueIF.h" -#include "../returnvalues/HasReturnvaluesIF.h" #include "ActionHelper.h" #include "ActionMessage.h" #include "SimpleActionHelper.h" +#include "fsfw/ipc/MessageQueueIF.h" +#include "fsfw/returnvalues/returnvalue.h" /** * @brief @@ -40,12 +40,12 @@ class HasActionsIF { static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2); static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3); static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4); - virtual ~HasActionsIF() {} + virtual ~HasActionsIF() = default; /** * Function to get the MessageQueueId_t of the implementing object * @return MessageQueueId_t of the object */ - virtual MessageQueueId_t getCommandQueue() const = 0; + [[nodiscard]] virtual MessageQueueId_t getCommandQueue() const = 0; /** * Execute or initialize the execution of a certain function. * The ActionHelpers will execute this function and behave differently @@ -53,7 +53,7 @@ class HasActionsIF { * * @return * -@c EXECUTION_FINISHED Finish reply will be generated - * -@c Not RETURN_OK Step failure reply will be generated + * -@c Not returnvalue::OK Step failure reply will be generated */ virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0; diff --git a/src/fsfw/action/SimpleActionHelper.cpp b/src/fsfw/action/SimpleActionHelper.cpp index 894f0df6..b9b9922e 100644 --- a/src/fsfw/action/SimpleActionHelper.cpp +++ b/src/fsfw/action/SimpleActionHelper.cpp @@ -3,13 +3,13 @@ SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) : ActionHelper(setOwner, useThisQueue), isExecuting(false) {} -SimpleActionHelper::~SimpleActionHelper() {} +SimpleActionHelper::~SimpleActionHelper() = default; void SimpleActionHelper::step(ReturnValue_t result) { // STEP_OFFESET is subtracted to compensate for adding offset in base // method, which is not necessary here. ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction, result); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { resetHelper(); } } @@ -38,10 +38,10 @@ void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::IS_BUSY); queueToUse->sendMessage(commandedBy, &reply); } - const uint8_t* dataPtr = NULL; + const uint8_t* dataPtr = nullptr; size_t size = 0; ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { ActionMessage::setStepReply(&reply, actionId, 0, result); queueToUse->sendMessage(commandedBy, &reply); return; @@ -51,12 +51,12 @@ void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId result = owner->executeAction(actionId, commandedBy, dataPtr, size); ipcStore->deleteData(dataAddress); switch (result) { - case HasReturnvaluesIF::RETURN_OK: + case returnvalue::OK: isExecuting = true; stepCount++; break; case HasActionsIF::EXECUTION_FINISHED: - ActionMessage::setCompletionReply(&reply, actionId, true, HasReturnvaluesIF::RETURN_OK); + ActionMessage::setCompletionReply(&reply, actionId, true, returnvalue::OK); queueToUse->sendMessage(commandedBy, &reply); break; default: diff --git a/src/fsfw/action/SimpleActionHelper.h b/src/fsfw/action/SimpleActionHelper.h index 5cb85fbd..cfe05231 100644 --- a/src/fsfw/action/SimpleActionHelper.h +++ b/src/fsfw/action/SimpleActionHelper.h @@ -11,15 +11,15 @@ class SimpleActionHelper : public ActionHelper { public: SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue); - virtual ~SimpleActionHelper(); - void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); - void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); + ~SimpleActionHelper() override; + void step(ReturnValue_t result = returnvalue::OK); + void finish(ReturnValue_t result = returnvalue::OK); ReturnValue_t reportData(SerializeIF* data); protected: void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, - store_address_t dataAddress); - virtual void resetHelper(); + store_address_t dataAddress) override; + void resetHelper() override; private: bool isExecuting; @@ -28,4 +28,4 @@ class SimpleActionHelper : public ActionHelper { uint8_t stepCount = 0; }; -#endif /* SIMPLEACTIONHELPER_H_ */ +#endif /* FSFW_ACTION_SIMPLEACTIONHELPER_H_ */ diff --git a/src/fsfw/cfdp.h b/src/fsfw/cfdp.h new file mode 100644 index 00000000..86086432 --- /dev/null +++ b/src/fsfw/cfdp.h @@ -0,0 +1,10 @@ +#ifndef FSFW_CFDP_H +#define FSFW_CFDP_H + +#include "cfdp/definitions.h" +#include "cfdp/handler/FaultHandlerBase.h" +#include "cfdp/tlv/Lv.h" +#include "cfdp/tlv/StringLv.h" +#include "cfdp/tlv/Tlv.h" + +#endif // FSFW_CFDP_H diff --git a/src/fsfw/cfdp/CFDPHandler.cpp b/src/fsfw/cfdp/CFDPHandler.cpp deleted file mode 100644 index 96baa98c..00000000 --- a/src/fsfw/cfdp/CFDPHandler.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "fsfw/cfdp/CFDPHandler.h" - -#include "fsfw/cfdp/CFDPMessage.h" -#include "fsfw/ipc/CommandMessage.h" -#include "fsfw/ipc/QueueFactory.h" -#include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/storagemanager/storeAddress.h" -#include "fsfw/tmtcservices/AcceptsTelemetryIF.h" - -object_id_t CFDPHandler::packetSource = 0; -object_id_t CFDPHandler::packetDestination = 0; - -CFDPHandler::CFDPHandler(object_id_t setObjectId, CFDPDistributor* dist) - : SystemObject(setObjectId) { - requestQueue = QueueFactory::instance()->createMessageQueue(CFDP_HANDLER_MAX_RECEPTION); - distributor = dist; -} - -CFDPHandler::~CFDPHandler() {} - -ReturnValue_t CFDPHandler::initialize() { - ReturnValue_t result = SystemObject::initialize(); - if (result != RETURN_OK) { - return result; - } - this->distributor->registerHandler(this); - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t CFDPHandler::handleRequest(store_address_t storeId) { -#if FSFW_VERBOSE_LEVEL >= 1 -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "CFDPHandler::handleRequest" << std::endl; -#else - sif::printDebug("CFDPHandler::handleRequest\n"); -#endif /* !FSFW_CPP_OSTREAM_ENABLED == 1 */ -#endif - - // TODO read out packet from store using storeId - - return RETURN_OK; -} - -ReturnValue_t CFDPHandler::performOperation(uint8_t opCode) { - ReturnValue_t status = RETURN_OK; - CommandMessage currentMessage; - for (status = this->requestQueue->receiveMessage(¤tMessage); status == RETURN_OK; - status = this->requestQueue->receiveMessage(¤tMessage)) { - store_address_t storeId = CFDPMessage::getStoreId(¤tMessage); - this->handleRequest(storeId); - } - return RETURN_OK; -} - -uint16_t CFDPHandler::getIdentifier() { return 0; } - -MessageQueueId_t CFDPHandler::getRequestQueue() { return this->requestQueue->getId(); } diff --git a/src/fsfw/cfdp/CFDPHandler.h b/src/fsfw/cfdp/CFDPHandler.h deleted file mode 100644 index abbac6b6..00000000 --- a/src/fsfw/cfdp/CFDPHandler.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef FSFW_CFDP_CFDPHANDLER_H_ -#define FSFW_CFDP_CFDPHANDLER_H_ - -#include "fsfw/ipc/MessageQueueIF.h" -#include "fsfw/objectmanager/SystemObject.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" -#include "fsfw/tasks/ExecutableObjectIF.h" -#include "fsfw/tcdistribution/CFDPDistributor.h" -#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h" - -namespace Factory { -void setStaticFrameworkObjectIds(); -} - -class CFDPHandler : public ExecutableObjectIF, - public AcceptsTelecommandsIF, - public SystemObject, - public HasReturnvaluesIF { - friend void(Factory::setStaticFrameworkObjectIds)(); - - public: - CFDPHandler(object_id_t setObjectId, CFDPDistributor* distributor); - /** - * The destructor is empty. - */ - virtual ~CFDPHandler(); - - virtual ReturnValue_t handleRequest(store_address_t storeId); - - virtual ReturnValue_t initialize() override; - virtual uint16_t getIdentifier() override; - MessageQueueId_t getRequestQueue() override; - ReturnValue_t performOperation(uint8_t opCode) override; - - protected: - /** - * This is a complete instance of the telecommand reception queue - * of the class. It is initialized on construction of the class. - */ - MessageQueueIF* requestQueue = nullptr; - - CFDPDistributor* distributor = nullptr; - - /** - * The current CFDP packet to be processed. - * It is deleted after handleRequest was executed. - */ - CFDPPacketStored currentPacket; - - static object_id_t packetSource; - - static object_id_t packetDestination; - - private: - /** - * This constant sets the maximum number of packets accepted per call. - * Remember that one packet must be completely handled in one - * #handleRequest call. - */ - static const uint8_t CFDP_HANDLER_MAX_RECEPTION = 100; -}; - -#endif /* FSFW_CFDP_CFDPHANDLER_H_ */ diff --git a/src/fsfw/cfdp/CFDPMessage.cpp b/src/fsfw/cfdp/CFDPMessage.cpp deleted file mode 100644 index fee55715..00000000 --- a/src/fsfw/cfdp/CFDPMessage.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "CFDPMessage.h" - -CFDPMessage::CFDPMessage() {} - -CFDPMessage::~CFDPMessage() {} - -void CFDPMessage::setCommand(CommandMessage *message, store_address_t cfdpPacket) { - message->setParameter(cfdpPacket.raw); -} - -store_address_t CFDPMessage::getStoreId(const CommandMessage *message) { - store_address_t storeAddressCFDPPacket; - storeAddressCFDPPacket = message->getParameter(); - return storeAddressCFDPPacket; -} - -void CFDPMessage::clear(CommandMessage *message) {} diff --git a/src/fsfw/cfdp/CMakeLists.txt b/src/fsfw/cfdp/CMakeLists.txt index 908dc32a..f4d60201 100644 --- a/src/fsfw/cfdp/CMakeLists.txt +++ b/src/fsfw/cfdp/CMakeLists.txt @@ -1,7 +1,6 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - CFDPHandler.cpp - CFDPMessage.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE CfdpMessage.cpp CfdpDistributor.cpp + VarLenFields.cpp helpers.cpp) add_subdirectory(pdu) add_subdirectory(tlv) +add_subdirectory(handler) diff --git a/src/fsfw/cfdp/CfdpDistributor.cpp b/src/fsfw/cfdp/CfdpDistributor.cpp new file mode 100644 index 00000000..b233e67e --- /dev/null +++ b/src/fsfw/cfdp/CfdpDistributor.cpp @@ -0,0 +1,55 @@ +#include "CfdpDistributor.h" + +#include "fsfw/tcdistribution/definitions.h" + +CfdpDistributor::CfdpDistributor(CfdpDistribCfg cfg) + : TcDistributorBase(cfg.objectId, cfg.tcQueue), cfg(cfg) {} + +ReturnValue_t CfdpDistributor::registerTcDestination(const cfdp::EntityId& address, + AcceptsTelecommandsIF& tcDest) { + for (const auto& dest : tcDestinations) { + if (dest.id == address) { + return returnvalue::FAILED; + } + } + tcDestinations.emplace_back(address, tcDest.getName(), tcDest.getRequestQueue()); + return returnvalue::OK; +} + +ReturnValue_t CfdpDistributor::selectDestination(MessageQueueId_t& destId) { + auto accessorPair = cfg.tcStore.getData(currentMessage.getStorageId()); + if (accessorPair.first != returnvalue::OK) { + return accessorPair.first; + } + ReturnValue_t result = + pduReader.setReadOnlyData(accessorPair.second.data(), accessorPair.second.size()); + if (result != returnvalue::OK) { + return result; + } + result = pduReader.parseData(); + if (result != returnvalue::OK) { + return result; + } + cfdp::EntityId foundId; + pduReader.getDestId(foundId); + bool destFound = false; + for (const auto& dest : tcDestinations) { + if (dest.id == foundId) { + destId = dest.queueId; + destFound = true; + } + } + if (not destFound) { + // TODO: Warning and event? + return tmtcdistrib::NO_DESTINATION_FOUND; + } + // Packet was forwarded successfully, so do not delete it. + accessorPair.second.release(); + return returnvalue::OK; +} + +const char* CfdpDistributor::getName() const { return "CFDP Distributor"; } + +uint32_t CfdpDistributor::getIdentifier() const { return 0; } + +MessageQueueId_t CfdpDistributor::getRequestQueue() const { return tcQueue->getId(); } diff --git a/src/fsfw/cfdp/CfdpDistributor.h b/src/fsfw/cfdp/CfdpDistributor.h new file mode 100644 index 00000000..13d000eb --- /dev/null +++ b/src/fsfw/cfdp/CfdpDistributor.h @@ -0,0 +1,76 @@ +#ifndef FSFW_TCDISTRIBUTION_CFDPDISTRIBUTOR_H_ +#define FSFW_TCDISTRIBUTION_CFDPDISTRIBUTOR_H_ + +#include +#include + +#include "fsfw/cfdp/pdu/PduHeaderReader.h" +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/tcdistribution/CfdpPacketChecker.h" +#include "fsfw/tcdistribution/TcDistributorBase.h" +#include "fsfw/tmtcpacket/cfdp/CfdpPacketStored.h" +#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h" +#include "fsfw/tmtcservices/VerificationReporter.h" + +struct CfdpDistribCfg { + CfdpDistribCfg(object_id_t objectId, StorageManagerIF& tcStore, MessageQueueIF* tcQueue) + : objectId(objectId), tcStore(tcStore), tcQueue(tcQueue) {} + + object_id_t objectId; + StorageManagerIF& tcStore; + MessageQueueIF* tcQueue; +}; + +/** + * This will be the primary component to perform PDU forwading procedures. This includes forwarding + * CFDP TC packets to registered source or destination handlers, and forwarding all telemetry + * generated by them to registered TM sinks. + * @ingroup tc_distribution + */ +class CfdpDistributor : public TcDistributorBase, public AcceptsTelecommandsIF { + public: + /** + * The ctor passes @c set_apid to the checker class and calls the + * TcDistribution ctor with a certain object id. + * @param setApid The APID of this receiving Application. + * @param setObjectId Object ID of the distributor itself + * @param setPacketSource Object ID of the source of TC packets. + * Must implement CcsdsDistributorIF. + */ + explicit CfdpDistributor(CfdpDistribCfg cfg); + + [[nodiscard]] const char* getName() const override; + [[nodiscard]] uint32_t getIdentifier() const override; + [[nodiscard]] MessageQueueId_t getRequestQueue() const override; + + /** + * Register a new CFDP entity which can receive PDUs. + * @param address + * @param tcDest + * @return + * - @c RETURN_FAILED: Entry already exists for the given address + */ + ReturnValue_t registerTcDestination(const cfdp::EntityId& address, AcceptsTelecommandsIF& tcDest); + + protected: + struct EntityInfo { + EntityInfo(cfdp::EntityId id, const char* name, MessageQueueId_t queueId) + : id(std::move(id)), name(name), queueId(queueId) {} + cfdp::EntityId id; + const char* name; + MessageQueueId_t queueId; + }; + PduHeaderReader pduReader; + ReturnValue_t lastTcError = returnvalue::OK; + ReturnValue_t lastTmError = returnvalue::OK; + // I don't think a regular OBSW will have more than 1 or 2 of these destinations, so I think + // it is okay to accept the overhead here + std::vector tcDestinations; + CfdpDistribCfg cfg; + + ReturnValue_t selectDestination(MessageQueueId_t& destId) override; + + private: +}; + +#endif /* FSFW_TCDISTRIBUTION_CFDPDISTRIBUTOR_H_ */ diff --git a/src/fsfw/cfdp/CfdpMessage.cpp b/src/fsfw/cfdp/CfdpMessage.cpp new file mode 100644 index 00000000..ea4e2c98 --- /dev/null +++ b/src/fsfw/cfdp/CfdpMessage.cpp @@ -0,0 +1,17 @@ +#include "CfdpMessage.h" + +CfdpMessage::CfdpMessage() = default; + +CfdpMessage::~CfdpMessage() = default; + +void CfdpMessage::setCommand(CommandMessage *message, store_address_t cfdpPacket) { + message->setParameter(cfdpPacket.raw); +} + +store_address_t CfdpMessage::getStoreId(const CommandMessage *message) { + store_address_t storeId; + storeId = static_cast(message->getParameter()); + return storeId; +} + +void CfdpMessage::clear(CommandMessage *message) {} diff --git a/src/fsfw/cfdp/CFDPMessage.h b/src/fsfw/cfdp/CfdpMessage.h similarity index 89% rename from src/fsfw/cfdp/CFDPMessage.h rename to src/fsfw/cfdp/CfdpMessage.h index 3de723eb..a3ee9421 100644 --- a/src/fsfw/cfdp/CFDPMessage.h +++ b/src/fsfw/cfdp/CfdpMessage.h @@ -5,14 +5,14 @@ #include "fsfw/objectmanager/ObjectManagerIF.h" #include "fsfw/storagemanager/StorageManagerIF.h" -class CFDPMessage { +class CfdpMessage { private: - CFDPMessage(); + CfdpMessage(); public: static const uint8_t MESSAGE_ID = messagetypes::CFDP; - virtual ~CFDPMessage(); + virtual ~CfdpMessage(); static void setCommand(CommandMessage* message, store_address_t cfdpPacket); static store_address_t getStoreId(const CommandMessage* message); diff --git a/src/fsfw/cfdp/FileSize.h b/src/fsfw/cfdp/FileSize.h index 6dae9683..b0b48452 100644 --- a/src/fsfw/cfdp/FileSize.h +++ b/src/fsfw/cfdp/FileSize.h @@ -1,5 +1,7 @@ -#ifndef FSFW_SRC_FSFW_CFDP_FILESIZE_H_ -#define FSFW_SRC_FSFW_CFDP_FILESIZE_H_ +#ifndef FSFW_CFDP_FILESIZE_H_ +#define FSFW_CFDP_FILESIZE_H_ + +#include #include "fsfw/serialize/SerializeAdapter.h" #include "fsfw/serialize/SerializeIF.h" @@ -8,9 +10,11 @@ namespace cfdp { struct FileSize : public SerializeIF { public: - FileSize() : largeFile(false){}; + FileSize() = default; - FileSize(uint64_t fileSize, bool isLarge = false) { setFileSize(fileSize, isLarge); }; + explicit FileSize(uint64_t fileSize, bool isLarge = false) { setFileSize(fileSize, isLarge); }; + + [[nodiscard]] uint64_t value() const { return fileSize; } ReturnValue_t serialize(bool isLarge, uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) { @@ -27,7 +31,7 @@ struct FileSize : public SerializeIF { return SerializeAdapter::serialize(&fileSize, buffer, size, maxSize, streamEndianness); } - size_t getSerializedSize() const override { + [[nodiscard]] size_t getSerializedSize() const override { if (largeFile) { return 8; } else { @@ -43,27 +47,29 @@ struct FileSize : public SerializeIF { uint32_t sizeTmp = 0; ReturnValue_t result = SerializeAdapter::deSerialize(&sizeTmp, buffer, size, streamEndianness); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { fileSize = sizeTmp; } return result; } } - ReturnValue_t setFileSize(uint64_t fileSize, bool largeFile) { + ReturnValue_t setFileSize(uint64_t fileSize_, std::optional largeFile_) { + if (largeFile_) { + largeFile = largeFile_.value(); + } if (not largeFile and fileSize > UINT32_MAX) { // TODO: emit warning here - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - this->fileSize = fileSize; - this->largeFile = largeFile; - return HasReturnvaluesIF::RETURN_OK; + this->fileSize = fileSize_; + return returnvalue::OK; } - bool isLargeFile() const { return largeFile; } - uint64_t getSize(bool *largeFile = nullptr) const { - if (largeFile != nullptr) { - *largeFile = this->largeFile; + [[nodiscard]] bool isLargeFile() const { return largeFile; } + uint64_t getSize(bool *largeFile_ = nullptr) const { + if (largeFile_ != nullptr) { + *largeFile_ = this->largeFile; } return fileSize; } @@ -75,4 +81,4 @@ struct FileSize : public SerializeIF { } // namespace cfdp -#endif /* FSFW_SRC_FSFW_CFDP_FILESIZE_H_ */ +#endif /* FSFW_CFDP_FILESIZE_H_ */ diff --git a/src/fsfw/cfdp/pdu/VarLenField.cpp b/src/fsfw/cfdp/VarLenFields.cpp similarity index 71% rename from src/fsfw/cfdp/pdu/VarLenField.cpp rename to src/fsfw/cfdp/VarLenFields.cpp index b11c3b09..b9e0b3a8 100644 --- a/src/fsfw/cfdp/pdu/VarLenField.cpp +++ b/src/fsfw/cfdp/VarLenFields.cpp @@ -1,12 +1,11 @@ -#include "VarLenField.h" +#include "VarLenFields.h" -#include "fsfw/FSFW.h" #include "fsfw/serialize/SerializeAdapter.h" #include "fsfw/serviceinterface.h" cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, size_t value) : VarLenField() { ReturnValue_t result = this->setValue(width, value); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_DISABLE_PRINTOUT == 0 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "cfdp::VarLenField: Setting value failed" << std::endl; @@ -21,27 +20,27 @@ cfdp::VarLenField::VarLenField() : width(cfdp::WidthInBytes::ONE_BYTE) { value.o cfdp::WidthInBytes cfdp::VarLenField::getWidth() const { return width; } -ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_t value) { +ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_t value_) { switch (widthInBytes) { case (cfdp::WidthInBytes::ONE_BYTE): { - if (value > UINT8_MAX) { - return HasReturnvaluesIF::RETURN_FAILED; + if (value_ > UINT8_MAX) { + return returnvalue::FAILED; } - this->value.oneByte = value; + this->value.oneByte = value_; break; } case (cfdp::WidthInBytes::TWO_BYTES): { - if (value > UINT16_MAX) { - return HasReturnvaluesIF::RETURN_FAILED; + if (value_ > UINT16_MAX) { + return returnvalue::FAILED; } - this->value.twoBytes = value; + this->value.twoBytes = value_; break; } case (cfdp::WidthInBytes::FOUR_BYTES): { - if (value > UINT32_MAX) { - return HasReturnvaluesIF::RETURN_FAILED; + if (value_ > UINT32_MAX) { + return returnvalue::FAILED; } - this->value.fourBytes = value; + this->value.fourBytes = value_; break; } default: { @@ -49,7 +48,7 @@ ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_ } } this->width = widthInBytes; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } size_t cfdp::VarLenField::getValue() const { @@ -77,7 +76,7 @@ ReturnValue_t cfdp::VarLenField::serialize(uint8_t **buffer, size_t *size, size_ **buffer = value.oneByte; *size += 1; *buffer += 1; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } case (cfdp::WidthInBytes::TWO_BYTES): { return SerializeAdapter::serialize(&value.twoBytes, buffer, size, maxSize, streamEndianness); @@ -86,16 +85,16 @@ ReturnValue_t cfdp::VarLenField::serialize(uint8_t **buffer, size_t *size, size_ return SerializeAdapter::serialize(&value.fourBytes, buffer, size, maxSize, streamEndianness); } default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } } size_t cfdp::VarLenField::getSerializedSize() const { return width; } -ReturnValue_t cfdp::VarLenField::deSerialize(cfdp::WidthInBytes width, const uint8_t **buffer, +ReturnValue_t cfdp::VarLenField::deSerialize(cfdp::WidthInBytes width_, const uint8_t **buffer, size_t *size, Endianness streamEndianness) { - this->width = width; + this->width = width_; return deSerialize(buffer, size, streamEndianness); } @@ -105,7 +104,7 @@ ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *siz case (cfdp::WidthInBytes::ONE_BYTE): { value.oneByte = **buffer; *size += 1; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } case (cfdp::WidthInBytes::TWO_BYTES): { return SerializeAdapter::deSerialize(&value.twoBytes, buffer, size, streamEndianness); @@ -114,7 +113,25 @@ ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *siz return SerializeAdapter::deSerialize(&value.fourBytes, buffer, size, streamEndianness); } default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } } + +bool cfdp::VarLenField::operator<(const cfdp::VarLenField &other) const { + if (getWidth() < other.getWidth()) { + return true; + } else if (getWidth() == other.getWidth()) { + return getValue() < other.getValue(); + } else { + return false; + } +} + +bool cfdp::VarLenField::operator==(const cfdp::VarLenField &other) const { + return getWidth() == other.getWidth() and getValue() == other.getValue(); +} + +bool cfdp::VarLenField::operator!=(const cfdp::VarLenField &other) const { + return not(*this == other); +} diff --git a/src/fsfw/cfdp/VarLenFields.h b/src/fsfw/cfdp/VarLenFields.h new file mode 100644 index 00000000..2758dc67 --- /dev/null +++ b/src/fsfw/cfdp/VarLenFields.h @@ -0,0 +1,108 @@ +#ifndef FSFW_CFDP_PDU_VARLENFIELD_H_ +#define FSFW_CFDP_PDU_VARLENFIELD_H_ + +#include +#include +#include + +#include "fsfw/cfdp/definitions.h" +#include "fsfw/serialize/SerializeIF.h" +#include "fsfw/serviceinterface.h" +#include "fsfw/util/UnsignedByteField.h" + +namespace cfdp { + +class VarLenField : public SerializeIF { + public: + union LengthFieldLen { + uint8_t oneByte; + uint16_t twoBytes; + uint32_t fourBytes; + uint64_t eightBytes; + }; + + VarLenField(); + template + explicit VarLenField(UnsignedByteField byteField); + + VarLenField(cfdp::WidthInBytes width, size_t value); + + bool operator==(const VarLenField &other) const; + bool operator!=(const VarLenField &other) const; + bool operator<(const VarLenField &other) const; + + ReturnValue_t setValue(cfdp::WidthInBytes, size_t value); + + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override; + + [[nodiscard]] size_t getSerializedSize() const override; + + ReturnValue_t deSerialize(cfdp::WidthInBytes width, const uint8_t **buffer, size_t *size, + Endianness streamEndianness); + + [[nodiscard]] cfdp::WidthInBytes getWidth() const; + [[nodiscard]] size_t getValue() const; + +#if FSFW_CPP_OSTREAM_ENABLED == 1 + friend std::ostream &operator<<(std::ostream &os, const VarLenField &id) { + os << "dec: " << id.getValue() << ", hex: " << std::hex << std::setw(id.getWidth()) + << std::setfill('0') << id.getValue() << std::dec << std::setfill('0'); + return os; + } +#endif + private: + using SerializeIF::deSerialize; // we overloaded above, so this is needed to uncofuse the + // compiler + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override; + + cfdp::WidthInBytes width; + LengthFieldLen value{}; +}; + +template +cfdp::VarLenField::VarLenField(UnsignedByteField byteField) + : width(static_cast(sizeof(T))) { + static_assert((sizeof(T) % 2) == 0); + setValue(width, byteField.getValue()); +} + +struct EntityId : public VarLenField { + public: + EntityId() : VarLenField() {} + template + explicit EntityId(UnsignedByteField byteField) : VarLenField(byteField) {} + EntityId(cfdp::WidthInBytes width, size_t entityId) : VarLenField(width, entityId) {} +}; + +struct TransactionSeqNum : public VarLenField { + public: + TransactionSeqNum() : VarLenField() {} + template + explicit TransactionSeqNum(UnsignedByteField byteField) : VarLenField(byteField) {} + TransactionSeqNum(cfdp::WidthInBytes width, size_t seqNum) : VarLenField(width, seqNum) {} +}; + +struct TransactionId { + TransactionId() = default; + TransactionId(EntityId entityId, TransactionSeqNum seqNum) + : entityId(std::move(entityId)), seqNum(std::move(seqNum)) {} + + bool operator==(const TransactionId &other) const { + return entityId == other.entityId and seqNum == other.seqNum; + } + +#if FSFW_CPP_OSTREAM_ENABLED == 1 + friend std::ostream &operator<<(std::ostream &os, const TransactionId &id) { + os << "Source ID { " << id.entityId << " }, Sequence Number " << id.seqNum.getValue(); + return os; + } +#endif + EntityId entityId; + TransactionSeqNum seqNum; +}; + +} // namespace cfdp + +#endif /* FSFW_CFDP_PDU_VARLENFIELD_H_ */ diff --git a/src/fsfw/cfdp/definitions.h b/src/fsfw/cfdp/definitions.h index eb21f5bf..2d7a37fc 100644 --- a/src/fsfw/cfdp/definitions.h +++ b/src/fsfw/cfdp/definitions.h @@ -7,36 +7,37 @@ #include #include "fsfw/returnvalues/FwClassIds.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" namespace cfdp { -static constexpr uint8_t VERSION_BITS = 0b00100000; +static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5"; + +// Second version of the protocol, only this one is supported here +static constexpr uint8_t CFDP_VERSION_2 = 0b001; +static constexpr uint8_t VERSION_BITS = CFDP_VERSION_2 << 5; static constexpr uint8_t CFDP_CLASS_ID = CLASS_ID::CFDP; -static constexpr ReturnValue_t INVALID_TLV_TYPE = - HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 1); -static constexpr ReturnValue_t INVALID_DIRECTIVE_FIELDS = - HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 2); -static constexpr ReturnValue_t INVALID_PDU_DATAFIELD_LEN = - HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 3); +static constexpr ReturnValue_t INVALID_TLV_TYPE = returnvalue::makeCode(CFDP_CLASS_ID, 1); +static constexpr ReturnValue_t INVALID_DIRECTIVE_FIELD = returnvalue::makeCode(CFDP_CLASS_ID, 2); +static constexpr ReturnValue_t INVALID_PDU_DATAFIELD_LEN = returnvalue::makeCode(CFDP_CLASS_ID, 3); static constexpr ReturnValue_t INVALID_ACK_DIRECTIVE_FIELDS = - HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 4); + returnvalue::makeCode(CFDP_CLASS_ID, 4); //! Can not parse options. This can also occur because there are options //! available but the user did not pass a valid options array static constexpr ReturnValue_t METADATA_CANT_PARSE_OPTIONS = - HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 5); -static constexpr ReturnValue_t NAK_CANT_PARSE_OPTIONS = - HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 6); + returnvalue::makeCode(CFDP_CLASS_ID, 5); +static constexpr ReturnValue_t NAK_CANT_PARSE_OPTIONS = returnvalue::makeCode(CFDP_CLASS_ID, 6); static constexpr ReturnValue_t FINISHED_CANT_PARSE_FS_RESPONSES = - HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 6); + returnvalue::makeCode(CFDP_CLASS_ID, 7); static constexpr ReturnValue_t FILESTORE_REQUIRES_SECOND_FILE = - HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 8); + returnvalue::makeCode(CFDP_CLASS_ID, 8); //! Can not parse filestore response because user did not pass a valid instance //! or remaining size is invalid static constexpr ReturnValue_t FILESTORE_RESPONSE_CANT_PARSE_FS_MESSAGE = - HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 9); + returnvalue::makeCode(CFDP_CLASS_ID, 9); +static constexpr ReturnValue_t INVALID_PDU_FORMAT = returnvalue::makeCode(CFDP_CLASS_ID, 10); //! Checksum types according to the SANA Checksum Types registry //! https://sanaregistry.org/r/checksum_identifiers/ @@ -49,17 +50,17 @@ enum ChecksumType { NULL_CHECKSUM = 15 }; -enum PduType : bool { FILE_DIRECTIVE = 0, FILE_DATA = 1 }; +enum PduType : uint8_t { FILE_DIRECTIVE = 0, FILE_DATA = 1 }; -enum TransmissionModes : bool { ACKNOWLEDGED = 0, UNACKNOWLEDGED = 1 }; +enum TransmissionMode : uint8_t { ACKNOWLEDGED = 0, UNACKNOWLEDGED = 1 }; -enum SegmentMetadataFlag : bool { NOT_PRESENT = 0, PRESENT = 1 }; +enum SegmentMetadataFlag : bool { NOT_PRESENT = false, PRESENT = true }; -enum Direction : bool { TOWARDS_RECEIVER = 0, TOWARDS_SENDER = 1 }; +enum Direction : uint8_t { TOWARDS_RECEIVER = 0, TOWARDS_SENDER = 1 }; enum SegmentationControl : bool { - NO_RECORD_BOUNDARIES_PRESERVATION = 0, - RECORD_BOUNDARIES_PRESERVATION = 1 + NO_RECORD_BOUNDARIES_PRESERVATION = false, + RECORD_BOUNDARIES_PRESERVATION = true }; enum WidthInBytes : uint8_t { @@ -69,8 +70,9 @@ enum WidthInBytes : uint8_t { FOUR_BYTES = 4, }; -enum FileDirectives : uint8_t { +enum FileDirective : uint8_t { INVALID_DIRECTIVE = 0x0f, + // The _DIRECTIVE suffix is mandatory here because of some nameclash! EOF_DIRECTIVE = 0x04, FINISH = 0x05, ACK = 0x06, @@ -97,6 +99,14 @@ enum ConditionCode : uint8_t { CANCEL_REQUEST_RECEIVED = 0b1111 }; +enum FaultHandlerCode { + RESERVED = 0b0000, + NOTICE_OF_CANCELLATION = 0b0001, + NOTICE_OF_SUSPENSION = 0b0010, + IGNORE_ERROR = 0b0011, + ABANDON_TRANSACTION = 0b0100 +}; + enum AckTransactionStatus { UNDEFINED = 0b00, ACTIVE = 0b01, @@ -104,18 +114,18 @@ enum AckTransactionStatus { UNRECOGNIZED = 0b11 }; -enum FinishedDeliveryCode { DATA_COMPLETE = 0, DATA_INCOMPLETE = 1 }; +enum FileDeliveryCode { DATA_COMPLETE = 0, DATA_INCOMPLETE = 1 }; -enum FinishedFileStatus { +enum FileDeliveryStatus { DISCARDED_DELIBERATELY = 0, DISCARDED_FILESTORE_REJECTION = 1, RETAINED_IN_FILESTORE = 2, FILE_STATUS_UNREPORTED = 3 }; -enum PromptResponseRequired : bool { PROMPT_NAK = 0, PROMPT_KEEP_ALIVE = 1 }; +enum PromptResponseRequired : uint8_t { PROMPT_NAK = 0, PROMPT_KEEP_ALIVE = 1 }; -enum TlvTypes : uint8_t { +enum TlvType : uint8_t { FILESTORE_REQUEST = 0x00, FILESTORE_RESPONSE = 0x01, MSG_TO_USER = 0x02, diff --git a/src/fsfw/cfdp/handler/CMakeLists.txt b/src/fsfw/cfdp/handler/CMakeLists.txt new file mode 100644 index 00000000..90130806 --- /dev/null +++ b/src/fsfw/cfdp/handler/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE FaultHandlerBase.cpp UserBase.cpp) diff --git a/src/fsfw/cfdp/handler/FaultHandlerBase.cpp b/src/fsfw/cfdp/handler/FaultHandlerBase.cpp new file mode 100644 index 00000000..4e16692e --- /dev/null +++ b/src/fsfw/cfdp/handler/FaultHandlerBase.cpp @@ -0,0 +1,51 @@ +#include "FaultHandlerBase.h" + +namespace cfdp { + +FaultHandlerBase::FaultHandlerBase() = default; +FaultHandlerBase::~FaultHandlerBase() = default; + +bool FaultHandlerBase::getFaultHandler(cfdp::ConditionCode code, + cfdp::FaultHandlerCode& handler) const { + auto iter = faultHandlerMap.find(code); + if (iter == faultHandlerMap.end()) { + return false; + } + handler = iter->second; + return true; +} + +bool FaultHandlerBase::setFaultHandler(cfdp::ConditionCode code, cfdp::FaultHandlerCode handler) { + if (not faultHandlerMap.contains(code)) { + return false; + } + if (handler != FaultHandlerCode::NOTICE_OF_SUSPENSION and + handler != FaultHandlerCode::ABANDON_TRANSACTION and + handler != FaultHandlerCode::NOTICE_OF_CANCELLATION and + handler != FaultHandlerCode::IGNORE_ERROR) { + return false; + } + faultHandlerMap[code] = handler; + return true; +} + +bool FaultHandlerBase::reportFault(cfdp::TransactionId& id, cfdp::ConditionCode code) { + if (not faultHandlerMap.contains(code)) { + return false; + } + cfdp::FaultHandlerCode fh = faultHandlerMap[code]; + if (fh == cfdp::FaultHandlerCode::IGNORE_ERROR) { + ignoreCb(id, code); + } else if (fh == cfdp::FaultHandlerCode::ABANDON_TRANSACTION) { + abandonCb(id, code); + } else if (fh == cfdp::FaultHandlerCode::NOTICE_OF_CANCELLATION) { + noticeOfCancellationCb(id, code); + } else if (fh == cfdp::FaultHandlerCode::NOTICE_OF_SUSPENSION) { + noticeOfSuspensionCb(id, code); + } else { + // Should never happen, but use defensive programming + return false; + } + return true; +} +} // namespace cfdp diff --git a/src/fsfw/cfdp/handler/FaultHandlerBase.h b/src/fsfw/cfdp/handler/FaultHandlerBase.h new file mode 100644 index 00000000..39b8e180 --- /dev/null +++ b/src/fsfw/cfdp/handler/FaultHandlerBase.h @@ -0,0 +1,77 @@ +#ifndef FSFW_CFDP_FAULTHANDLERBASE_H +#define FSFW_CFDP_FAULTHANDLERBASE_H + +#include + +#include "fsfw/cfdp/VarLenFields.h" +#include "fsfw/cfdp/definitions.h" + +namespace cfdp { + +/** + * @brief Provides a way to implement the fault handling procedures as specified + * in chapter 4.8 of the CFDP standard. + * + * @details + * It is passed into the CFDP handlers as part of the local entity configuration and provides + * a way to specify custom user error handlers. + * + * It does so by mapping each applicable CFDP condition code to a fault handler which + * is denoted by the four @cfdp::FaultHandlerCodes. This code is used to dispatch + * to a user-provided callback function: + * + * 1. @FaultHandlerCodes::IGNORE_ERROR -> @ignore_cb + * 2. @FaultHandlerCodes::NOTICE_OF_CANCELLATION` -> @notice_of_cancellation_cb + * 3. @FaultHandlerCodes::NOTICE_OF_SUSPENSION` -> @notice_of_suspension_cb + * 4. @FaultHandlerCodes::ABANDON_TRANSACTION` -> @abandon_transaction_cb + * + * For each error reported by @reportError, the appropriate fault handler callback + * will be called. The user provides the callbacks by providing a custom class which implements + * these base class and all abstract fault handler callbacks. + */ +class FaultHandlerBase { + public: + virtual ~FaultHandlerBase(); + FaultHandlerBase(); + + /** + * Get the fault handler code for the given condition code + * @param code + * @param handler [out] Will be set to the approrpiate handler for the condition code if + * it is valid + * @return + * - true if the condition code is valid + * - false otherwise + */ + bool getFaultHandler(cfdp::ConditionCode code, cfdp::FaultHandlerCode& handler) const; + + bool setFaultHandler(cfdp::ConditionCode code, cfdp::FaultHandlerCode handler); + + bool reportFault(cfdp::TransactionId& id, cfdp::ConditionCode code); + + virtual void noticeOfSuspensionCb(cfdp::TransactionId& id, cfdp::ConditionCode code) = 0; + virtual void noticeOfCancellationCb(cfdp::TransactionId& id, cfdp::ConditionCode code) = 0; + virtual void abandonCb(cfdp::TransactionId& id, cfdp::ConditionCode code) = 0; + virtual void ignoreCb(cfdp::TransactionId& id, cfdp::ConditionCode code) = 0; + + private: + etl::flat_map faultHandlerMap = { + etl::pair{cfdp::ConditionCode::POSITIVE_ACK_LIMIT_REACHED, + cfdp::FaultHandlerCode::IGNORE_ERROR}, + etl::pair{cfdp::ConditionCode::KEEP_ALIVE_LIMIT_REACHED, + cfdp::FaultHandlerCode::IGNORE_ERROR}, + etl::pair{cfdp::ConditionCode::INVALID_TRANSMISSION_MODE, + cfdp::FaultHandlerCode::IGNORE_ERROR}, + etl::pair{cfdp::ConditionCode::FILE_CHECKSUM_FAILURE, cfdp::FaultHandlerCode::IGNORE_ERROR}, + etl::pair{cfdp::ConditionCode::FILE_SIZE_ERROR, cfdp::FaultHandlerCode::IGNORE_ERROR}, + etl::pair{cfdp::ConditionCode::NAK_LIMIT_REACHED, cfdp::FaultHandlerCode::IGNORE_ERROR}, + etl::pair{cfdp::ConditionCode::INACTIVITY_DETECTED, cfdp::FaultHandlerCode::IGNORE_ERROR}, + etl::pair{cfdp::ConditionCode::UNSUPPORTED_CHECKSUM_TYPE, + cfdp::FaultHandlerCode::IGNORE_ERROR}, + etl::pair{cfdp::ConditionCode::FILESTORE_REJECTION, cfdp::FaultHandlerCode::IGNORE_ERROR}, + etl::pair{cfdp::ConditionCode::CHECK_LIMIT_REACHED, cfdp::FaultHandlerCode::IGNORE_ERROR}}; +}; + +} // namespace cfdp + +#endif // FSFW_CFDP_FAULTHANDLERBASE_H diff --git a/src/fsfw/cfdp/handler/RemoteConfigTableIF.h b/src/fsfw/cfdp/handler/RemoteConfigTableIF.h new file mode 100644 index 00000000..d0e6121d --- /dev/null +++ b/src/fsfw/cfdp/handler/RemoteConfigTableIF.h @@ -0,0 +1,35 @@ +#ifndef FSFW_CFDP_HANDLER_REMOTECONFIGTABLEIF_H +#define FSFW_CFDP_HANDLER_REMOTECONFIGTABLEIF_H + +#include "fsfw/cfdp/handler/mib.h" + +namespace cfdp { + +class RemoteConfigTableIF { + public: + virtual ~RemoteConfigTableIF() = default; + virtual bool getRemoteCfg(const cfdp::EntityId& remoteId, cfdp::RemoteEntityCfg** cfg) = 0; +}; + +/** + * Helper class for the common case that there is exactly one remote entity + */ +class OneRemoteConfigProvider : public RemoteConfigTableIF { + public: + explicit OneRemoteConfigProvider(RemoteEntityCfg cfg) : cfg(std::move(cfg)) {} + + bool getRemoteCfg(const EntityId& remoteId, cfdp::RemoteEntityCfg** cfg_) override { + if (remoteId != cfg.remoteId) { + return false; + } + *cfg_ = &cfg; + return true; + } + + private: + RemoteEntityCfg cfg; +}; + +} // namespace cfdp + +#endif // FSFW_CFDP_HANDLER_REMOTECONFIGTABLEIF_H diff --git a/src/fsfw/cfdp/handler/StatusReportIF.h b/src/fsfw/cfdp/handler/StatusReportIF.h new file mode 100644 index 00000000..1bf98628 --- /dev/null +++ b/src/fsfw/cfdp/handler/StatusReportIF.h @@ -0,0 +1,12 @@ +#ifndef FSFW_CFDP_HANDLER_STATUSREPORTIF_H +#define FSFW_CFDP_HANDLER_STATUSREPORTIF_H + +namespace cfdp { + +class StatusReportIF { + virtual ~StatusReportIF() = default; +}; + +} // namespace cfdp + +#endif // FSFW_CFDP_HANDLER_STATUSREPORTIF_H diff --git a/src/fsfw/cfdp/handler/UserBase.cpp b/src/fsfw/cfdp/handler/UserBase.cpp new file mode 100644 index 00000000..212396fb --- /dev/null +++ b/src/fsfw/cfdp/handler/UserBase.cpp @@ -0,0 +1,3 @@ +#include "UserBase.h" + +cfdp::UserBase::UserBase(HasFileSystemIF& vfs) : vfs(vfs) {} diff --git a/src/fsfw/cfdp/handler/UserBase.h b/src/fsfw/cfdp/handler/UserBase.h new file mode 100644 index 00000000..e367b4a8 --- /dev/null +++ b/src/fsfw/cfdp/handler/UserBase.h @@ -0,0 +1,101 @@ +#ifndef FSFW_CFDP_USERBASE_H +#define FSFW_CFDP_USERBASE_H + +#include +#include +#include + +#include "StatusReportIF.h" +#include "fsfw/cfdp/VarLenFields.h" +#include "fsfw/cfdp/tlv/FilestoreResponseTlv.h" +#include "fsfw/cfdp/tlv/MessageToUserTlv.h" +#include "fsfw/filesystem/HasFileSystemIF.h" + +namespace cfdp { + +struct TransactionFinishedParams { + TransactionFinishedParams(const TransactionId& id, ConditionCode code, FileDeliveryCode delivCode, + FileDeliveryStatus status) + : id(id), condCode(code), status(status), deliveryCode(delivCode) {} + + const TransactionId& id; + ConditionCode condCode; + FileDeliveryStatus status; + FileDeliveryCode deliveryCode; + std::vector fsResponses; + StatusReportIF* statusReport = nullptr; +}; + +struct MetadataRecvdParams { + MetadataRecvdParams(const TransactionId& id, const EntityId& sourceId) + : id(id), sourceId(sourceId) {} + const TransactionId& id; + const EntityId& sourceId; + uint64_t fileSize = 0; + const char* sourceFileName = ""; + const char* destFileName = ""; + size_t msgsToUserLen = 0; + const MessageToUserTlv* msgsToUserArray = nullptr; +}; + +struct FileSegmentRecvdParams { + TransactionId id; + size_t offset; + size_t length; + std::optional recContState = std::nullopt; + std::pair segmentMetadata; +}; + +/** + * @brief Base class which provides a user interface to interact with CFDP handlers. + * + * @details + * This class is also used to pass the Virtual Filestore (VFS) Implementation to the CFDP + * handlers so the filestore operations can be mapped to the underlying filestore. + * + * It is used by implementing it in a child class and then passing it to the CFDP + * handler objects. The base class provides default implementation for the user indication + * primitives specified in the CFDP standard. The user can override these implementations + * to provide custom indication handlers. + * + * Please note that for all indication callbacks, the passed transaction ID reference will + * become invalid shortly after the function has been executed. If the transaction ID is to be + * cached or used, create an own copy of it. + * @param vfs Virtual Filestore Object. Will be used for all file operations + */ +class UserBase { + friend class DestHandler; + + public: + explicit UserBase(HasFileSystemIF& vfs); + + virtual void transactionIndication(const TransactionId& id) = 0; + virtual void eofSentIndication(const TransactionId& id) = 0; + virtual void transactionFinishedIndication(const TransactionFinishedParams& params) = 0; + /** + * Will be called if metadata was received. + * + * IMPORTANT: The passed struct contains the messages to the user in form of a raw C array. + * The TLVs in these arrays are zero-copy types, which means that they point to the raw data + * inside the metadata packet directly. The metadata packet will be deleted from the TC store + * shortly after it was processed. If some of the data is to be cached and/or used after the + * function call, it needs to be copied into another user-provided buffer. + * @param params + */ + virtual void metadataRecvdIndication(const MetadataRecvdParams& params) = 0; + virtual void fileSegmentRecvdIndication(const FileSegmentRecvdParams& params) = 0; + virtual void reportIndication(const TransactionId& id, StatusReportIF& report) = 0; + virtual void suspendedIndication(const TransactionId& id, ConditionCode code) = 0; + virtual void resumedIndication(const TransactionId& id, size_t progress) = 0; + virtual void faultIndication(const TransactionId& id, ConditionCode code, size_t progress) = 0; + virtual void abandonedIndication(const TransactionId& id, ConditionCode code, + size_t progress) = 0; + virtual void eofRecvIndication(const TransactionId& id) = 0; + + private: + HasFileSystemIF& vfs; +}; + +} // namespace cfdp + +#endif // FSFW_CFDP_USERBASE_H diff --git a/src/fsfw/cfdp/handler/defs.h b/src/fsfw/cfdp/handler/defs.h new file mode 100644 index 00000000..9e837a96 --- /dev/null +++ b/src/fsfw/cfdp/handler/defs.h @@ -0,0 +1,9 @@ +#ifndef FSFW_CFDP_HANDLER_DEFS_H +#define FSFW_CFDP_HANDLER_DEFS_H + +namespace cfdp { + +enum class CfdpStates { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED }; + +} +#endif // FSFW_CFDP_HANDLER_DEFS_H diff --git a/src/fsfw/cfdp/handler/mib.h b/src/fsfw/cfdp/handler/mib.h new file mode 100644 index 00000000..553596a6 --- /dev/null +++ b/src/fsfw/cfdp/handler/mib.h @@ -0,0 +1,42 @@ +#ifndef FSFW_CFDP_MIB_H +#define FSFW_CFDP_MIB_H + +#include + +#include "FaultHandlerBase.h" +#include "fsfw/cfdp/pdu/PduConfig.h" + +namespace cfdp { + +struct IndicationCfg { + bool eofSentIndicRequired = true; + bool eofRecvIndicRequired = true; + bool fileSegmentRecvIndicRequired = true; + bool transactionFinishedIndicRequired = true; + bool suspendedIndicRequired = true; + bool resumedIndicRequired = true; +}; + +struct LocalEntityCfg { + LocalEntityCfg(EntityId localId, IndicationCfg indicationCfg, FaultHandlerBase& fhBase) + : localId(std::move(localId)), indicCfg(indicationCfg), fhBase(fhBase) {} + + EntityId localId; + IndicationCfg indicCfg; + FaultHandlerBase& fhBase; +}; + +struct RemoteEntityCfg { + explicit RemoteEntityCfg(EntityId id) : remoteId(std::move(id)) {} + EntityId remoteId; + size_t maxFileSegmentLen = 2048; + bool closureRequested = false; + bool crcOnTransmission = false; + TransmissionMode defaultTransmissionMode = TransmissionMode::UNACKNOWLEDGED; + ChecksumType defaultChecksum = ChecksumType::NULL_CHECKSUM; + const uint8_t version = CFDP_VERSION_2; +}; + +} // namespace cfdp + +#endif // FSFW_CFDP_MIB_H diff --git a/src/fsfw/cfdp/helpers.cpp b/src/fsfw/cfdp/helpers.cpp new file mode 100644 index 00000000..fdb7d5ff --- /dev/null +++ b/src/fsfw/cfdp/helpers.cpp @@ -0,0 +1,50 @@ +#include "helpers.h" + +const char* COND_CODE_STRINGS[14] = {"Unknown", + "No Error", + "Positive ACK Limit Reached", + "Keep Alive Limit Reached", + "Invalid Transmission Mode", + "Filestore Rejection", + "File Checksum Failure", + "File Size Error", + "NAK limit reached", + "Inactivity Detected", + "Check Limit Reached", + "Unsupported Checksum Type", + "Suspend Request Received", + "Cancel Request Received"}; + +const char* cfdp::getConditionCodeString(cfdp::ConditionCode code) { + switch (code) { + case NO_CONDITION_FIELD: + return COND_CODE_STRINGS[0]; + case NO_ERROR: + return COND_CODE_STRINGS[1]; + case POSITIVE_ACK_LIMIT_REACHED: + return COND_CODE_STRINGS[2]; + case KEEP_ALIVE_LIMIT_REACHED: + return COND_CODE_STRINGS[3]; + case INVALID_TRANSMISSION_MODE: + return COND_CODE_STRINGS[4]; + case FILESTORE_REJECTION: + return COND_CODE_STRINGS[5]; + case FILE_CHECKSUM_FAILURE: + return COND_CODE_STRINGS[6]; + case FILE_SIZE_ERROR: + return COND_CODE_STRINGS[7]; + case NAK_LIMIT_REACHED: + return COND_CODE_STRINGS[8]; + case INACTIVITY_DETECTED: + return COND_CODE_STRINGS[9]; + case CHECK_LIMIT_REACHED: + return COND_CODE_STRINGS[10]; + case UNSUPPORTED_CHECKSUM_TYPE: + return COND_CODE_STRINGS[11]; + case SUSPEND_REQUEST_RECEIVED: + return COND_CODE_STRINGS[12]; + case CANCEL_REQUEST_RECEIVED: + return COND_CODE_STRINGS[13]; + } + return "Unknown"; +} diff --git a/src/fsfw/cfdp/helpers.h b/src/fsfw/cfdp/helpers.h new file mode 100644 index 00000000..37428108 --- /dev/null +++ b/src/fsfw/cfdp/helpers.h @@ -0,0 +1,11 @@ +#ifndef FSFW_EXAMPLE_HOSTED_HELPER_H +#define FSFW_EXAMPLE_HOSTED_HELPER_H + +#include "definitions.h" + +namespace cfdp { + +const char* getConditionCodeString(cfdp::ConditionCode code); + +} +#endif // FSFW_EXAMPLE_HOSTED_HELPER_H diff --git a/src/fsfw/cfdp/pdu/AckInfo.cpp b/src/fsfw/cfdp/pdu/AckInfo.cpp index f35cfbb1..963f7cbb 100644 --- a/src/fsfw/cfdp/pdu/AckInfo.cpp +++ b/src/fsfw/cfdp/pdu/AckInfo.cpp @@ -1,12 +1,12 @@ #include "AckInfo.h" -AckInfo::AckInfo(cfdp::FileDirectives ackedDirective, cfdp::ConditionCode ackedConditionCode, +AckInfo::AckInfo(cfdp::FileDirective ackedDirective, cfdp::ConditionCode ackedConditionCode, cfdp::AckTransactionStatus transactionStatus, uint8_t directiveSubtypeCode) : ackedDirective(ackedDirective), ackedConditionCode(ackedConditionCode), transactionStatus(transactionStatus), directiveSubtypeCode(directiveSubtypeCode) { - if (ackedDirective == cfdp::FileDirectives::FINISH) { + if (ackedDirective == cfdp::FileDirective::FINISH) { this->directiveSubtypeCode = 0b0001; } else { this->directiveSubtypeCode = 0b0000; @@ -17,16 +17,16 @@ cfdp::ConditionCode AckInfo::getAckedConditionCode() const { return ackedConditi void AckInfo::setAckedConditionCode(cfdp::ConditionCode ackedConditionCode) { this->ackedConditionCode = ackedConditionCode; - if (ackedDirective == cfdp::FileDirectives::FINISH) { + if (ackedDirective == cfdp::FileDirective::FINISH) { this->directiveSubtypeCode = 0b0001; } else { this->directiveSubtypeCode = 0b0000; } } -cfdp::FileDirectives AckInfo::getAckedDirective() const { return ackedDirective; } +cfdp::FileDirective AckInfo::getAckedDirective() const { return ackedDirective; } -void AckInfo::setAckedDirective(cfdp::FileDirectives ackedDirective) { +void AckInfo::setAckedDirective(cfdp::FileDirective ackedDirective) { this->ackedDirective = ackedDirective; } diff --git a/src/fsfw/cfdp/pdu/AckInfo.h b/src/fsfw/cfdp/pdu/AckInfo.h index 572fc59f..23e4d6ab 100644 --- a/src/fsfw/cfdp/pdu/AckInfo.h +++ b/src/fsfw/cfdp/pdu/AckInfo.h @@ -6,14 +6,14 @@ class AckInfo { public: AckInfo(); - AckInfo(cfdp::FileDirectives ackedDirective, cfdp::ConditionCode ackedConditionCode, + AckInfo(cfdp::FileDirective ackedDirective, cfdp::ConditionCode ackedConditionCode, cfdp::AckTransactionStatus transactionStatus, uint8_t directiveSubtypeCode = 0); cfdp::ConditionCode getAckedConditionCode() const; void setAckedConditionCode(cfdp::ConditionCode ackedConditionCode); - cfdp::FileDirectives getAckedDirective() const; - void setAckedDirective(cfdp::FileDirectives ackedDirective); + cfdp::FileDirective getAckedDirective() const; + void setAckedDirective(cfdp::FileDirective ackedDirective); uint8_t getDirectiveSubtypeCode() const; void setDirectiveSubtypeCode(uint8_t directiveSubtypeCode); @@ -22,7 +22,7 @@ class AckInfo { void setTransactionStatus(cfdp::AckTransactionStatus transactionStatus); private: - cfdp::FileDirectives ackedDirective = cfdp::FileDirectives::INVALID_DIRECTIVE; + cfdp::FileDirective ackedDirective = cfdp::FileDirective::INVALID_DIRECTIVE; cfdp::ConditionCode ackedConditionCode = cfdp::ConditionCode::NO_CONDITION_FIELD; cfdp::AckTransactionStatus transactionStatus = cfdp::AckTransactionStatus::UNDEFINED; uint8_t directiveSubtypeCode = 0; diff --git a/src/fsfw/cfdp/pdu/AckPduCreator.cpp b/src/fsfw/cfdp/pdu/AckPduCreator.cpp new file mode 100644 index 00000000..f7623e57 --- /dev/null +++ b/src/fsfw/cfdp/pdu/AckPduCreator.cpp @@ -0,0 +1,33 @@ +#include "AckPduCreator.h" + +AckPduCreator::AckPduCreator(AckInfo &ackInfo, PduConfig &pduConf) + : FileDirectiveCreator(pduConf, cfdp::FileDirective::ACK, 2), ackInfo(ackInfo) {} + +size_t AckPduCreator::getSerializedSize() const { return FileDirectiveCreator::getWholePduSize(); } + +ReturnValue_t AckPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const { + ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + cfdp::FileDirective ackedDirective = ackInfo.getAckedDirective(); + uint8_t directiveSubtypeCode = ackInfo.getDirectiveSubtypeCode(); + cfdp::ConditionCode ackedConditionCode = ackInfo.getAckedConditionCode(); + cfdp::AckTransactionStatus transactionStatus = ackInfo.getTransactionStatus(); + if (ackedDirective != cfdp::FileDirective::FINISH and + ackedDirective != cfdp::FileDirective::EOF_DIRECTIVE) { + // TODO: better returncode + return returnvalue::FAILED; + } + if (*size + 2 > maxSize) { + return SerializeIF::BUFFER_TOO_SHORT; + } + **buffer = ackedDirective << 4 | directiveSubtypeCode; + *buffer += 1; + *size += 1; + **buffer = ackedConditionCode << 4 | transactionStatus; + *buffer += 1; + *size += 1; + return returnvalue::OK; +} diff --git a/src/fsfw/cfdp/pdu/AckPduSerializer.h b/src/fsfw/cfdp/pdu/AckPduCreator.h similarity index 53% rename from src/fsfw/cfdp/pdu/AckPduSerializer.h rename to src/fsfw/cfdp/pdu/AckPduCreator.h index 68a049e2..c0a89cc3 100644 --- a/src/fsfw/cfdp/pdu/AckPduSerializer.h +++ b/src/fsfw/cfdp/pdu/AckPduCreator.h @@ -1,11 +1,11 @@ -#ifndef FSFW_SRC_FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_ -#define FSFW_SRC_FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_ +#ifndef FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_ +#define FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_ #include "AckInfo.h" -#include "FileDirectiveDeserializer.h" -#include "FileDirectiveSerializer.h" +#include "FileDirectiveCreator.h" +#include "FileDirectiveReader.h" -class AckPduSerializer : public FileDirectiveSerializer { +class AckPduCreator : public FileDirectiveCreator { public: /** * @brief Serializer to pack ACK PDUs @@ -16,9 +16,9 @@ class AckPduSerializer : public FileDirectiveSerializer { * @param transactionStatus * @param pduConf */ - AckPduSerializer(AckInfo& ackInfo, PduConfig& pduConf); + AckPduCreator(AckInfo& ackInfo, PduConfig& pduConf); - size_t getSerializedSize() const override; + [[nodiscard]] size_t getSerializedSize() const override; ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness) const override; @@ -27,4 +27,4 @@ class AckPduSerializer : public FileDirectiveSerializer { AckInfo& ackInfo; }; -#endif /* FSFW_SRC_FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_ */ +#endif /* FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/AckPduDeserializer.cpp b/src/fsfw/cfdp/pdu/AckPduDeserializer.cpp deleted file mode 100644 index f5babf4b..00000000 --- a/src/fsfw/cfdp/pdu/AckPduDeserializer.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "AckPduDeserializer.h" - -AckPduDeserializer::AckPduDeserializer(const uint8_t* pduBuf, size_t maxSize, AckInfo& info) - : FileDirectiveDeserializer(pduBuf, maxSize), info(info) {} - -ReturnValue_t AckPduDeserializer::parseData() { - ReturnValue_t result = FileDirectiveDeserializer::parseData(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - size_t currentIdx = FileDirectiveDeserializer::getHeaderSize(); - if (currentIdx + 2 > this->maxSize) { - return SerializeIF::BUFFER_TOO_SHORT; - } - if (not checkAndSetCodes(rawPtr[currentIdx], rawPtr[currentIdx + 1])) { - return cfdp::INVALID_ACK_DIRECTIVE_FIELDS; - } - return HasReturnvaluesIF::RETURN_OK; -} - -bool AckPduDeserializer::checkAndSetCodes(uint8_t firstByte, uint8_t secondByte) { - uint8_t ackedDirective = static_cast(firstByte >> 4); - - if (ackedDirective != cfdp::FileDirectives::EOF_DIRECTIVE and - ackedDirective != cfdp::FileDirectives::FINISH) { - return false; - } - this->info.setAckedDirective(static_cast(ackedDirective)); - uint8_t directiveSubtypeCode = firstByte & 0x0f; - if (directiveSubtypeCode != 0b0000 and directiveSubtypeCode != 0b0001) { - return false; - } - this->info.setDirectiveSubtypeCode(directiveSubtypeCode); - this->info.setAckedConditionCode(static_cast(secondByte >> 4)); - this->info.setTransactionStatus(static_cast(secondByte & 0x0f)); - return true; -} diff --git a/src/fsfw/cfdp/pdu/AckPduReader.cpp b/src/fsfw/cfdp/pdu/AckPduReader.cpp new file mode 100644 index 00000000..7204ced0 --- /dev/null +++ b/src/fsfw/cfdp/pdu/AckPduReader.cpp @@ -0,0 +1,45 @@ +#include "AckPduReader.h" + +AckPduReader::AckPduReader(const uint8_t* pduBuf, size_t maxSize, AckInfo& info) + : FileDirectiveReader(pduBuf, maxSize), info(info) {} + +ReturnValue_t AckPduReader::parseData() { + ReturnValue_t result = FileDirectiveReader::parseData(); + if (result != returnvalue::OK) { + return result; + } + size_t currentIdx = FileDirectiveReader::getHeaderSize(); + if (currentIdx + 2 > this->maxSize) { + return SerializeIF::BUFFER_TOO_SHORT; + } + if (not checkAndSetCodes(pointers.rawPtr[currentIdx], pointers.rawPtr[currentIdx + 1])) { + return cfdp::INVALID_ACK_DIRECTIVE_FIELDS; + } + return returnvalue::OK; +} + +bool AckPduReader::checkAndSetCodes(uint8_t firstByte, uint8_t secondByte) { + cfdp::FileDirective directive; + if (not checkAckedDirectiveField(firstByte, directive)) { + return false; + } + this->info.setAckedDirective(directive); + uint8_t directiveSubtypeCode = firstByte & 0x0f; + if (directiveSubtypeCode != 0b0000 and directiveSubtypeCode != 0b0001) { + return false; + } + this->info.setDirectiveSubtypeCode(directiveSubtypeCode); + this->info.setAckedConditionCode(static_cast(secondByte >> 4)); + this->info.setTransactionStatus(static_cast(secondByte & 0x0f)); + return true; +} +bool AckPduReader::checkAckedDirectiveField(uint8_t firstPduDataByte, + cfdp::FileDirective& ackedDirective) { + uint8_t ackedDirectiveRaw = static_cast(firstPduDataByte >> 4); + if (ackedDirectiveRaw != cfdp::FileDirective::EOF_DIRECTIVE and + ackedDirectiveRaw != cfdp::FileDirective::FINISH) { + return false; + } + ackedDirective = (static_cast(ackedDirectiveRaw)); + return true; +} diff --git a/src/fsfw/cfdp/pdu/AckPduDeserializer.h b/src/fsfw/cfdp/pdu/AckPduReader.h similarity index 52% rename from src/fsfw/cfdp/pdu/AckPduDeserializer.h rename to src/fsfw/cfdp/pdu/AckPduReader.h index 0bb95071..8f8b515b 100644 --- a/src/fsfw/cfdp/pdu/AckPduDeserializer.h +++ b/src/fsfw/cfdp/pdu/AckPduReader.h @@ -2,18 +2,21 @@ #define FSFW_SRC_FSFW_CFDP_PDU_ACKPDUDESERIALIZER_H_ #include "AckInfo.h" -#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h" +#include "fsfw/cfdp/pdu/FileDirectiveReader.h" -class AckPduDeserializer : public FileDirectiveDeserializer { +class AckPduReader : public FileDirectiveReader { public: - AckPduDeserializer(const uint8_t* pduBuf, size_t maxSize, AckInfo& info); + AckPduReader(const uint8_t* pduBuf, size_t maxSize, AckInfo& info); /** * * @return * - cfdp::INVALID_DIRECTIVE_FIELDS: Invalid fields */ - ReturnValue_t parseData(); + ReturnValue_t parseData() override; + + static bool checkAckedDirectiveField(uint8_t firstPduDataByte, + cfdp::FileDirective& ackedDirective); private: bool checkAndSetCodes(uint8_t rawAckedByte, uint8_t rawAckedConditionCode); diff --git a/src/fsfw/cfdp/pdu/AckPduSerializer.cpp b/src/fsfw/cfdp/pdu/AckPduSerializer.cpp deleted file mode 100644 index d19418f1..00000000 --- a/src/fsfw/cfdp/pdu/AckPduSerializer.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "AckPduSerializer.h" - -AckPduSerializer::AckPduSerializer(AckInfo &ackInfo, PduConfig &pduConf) - : FileDirectiveSerializer(pduConf, cfdp::FileDirectives::ACK, 2), ackInfo(ackInfo) {} - -size_t AckPduSerializer::getSerializedSize() const { - return FileDirectiveSerializer::getWholePduSize(); -} - -ReturnValue_t AckPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const { - ReturnValue_t result = - FileDirectiveSerializer::serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - cfdp::FileDirectives ackedDirective = ackInfo.getAckedDirective(); - uint8_t directiveSubtypeCode = ackInfo.getDirectiveSubtypeCode(); - cfdp::ConditionCode ackedConditionCode = ackInfo.getAckedConditionCode(); - cfdp::AckTransactionStatus transactionStatus = ackInfo.getTransactionStatus(); - if (ackedDirective != cfdp::FileDirectives::FINISH and - ackedDirective != cfdp::FileDirectives::EOF_DIRECTIVE) { - // TODO: better returncode - return HasReturnvaluesIF::RETURN_FAILED; - } - if (*size + 2 > maxSize) { - return SerializeIF::BUFFER_TOO_SHORT; - } - **buffer = ackedDirective << 4 | directiveSubtypeCode; - *buffer += 1; - *size += 1; - **buffer = ackedConditionCode << 4 | transactionStatus; - *buffer += 1; - *size += 1; - return HasReturnvaluesIF::RETURN_OK; -} diff --git a/src/fsfw/cfdp/pdu/CMakeLists.txt b/src/fsfw/cfdp/pdu/CMakeLists.txt index 931db306..c08a4b29 100644 --- a/src/fsfw/cfdp/pdu/CMakeLists.txt +++ b/src/fsfw/cfdp/pdu/CMakeLists.txt @@ -1,32 +1,29 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - PduConfig.cpp - VarLenField.cpp - HeaderSerializer.cpp - HeaderDeserializer.cpp - FileDirectiveDeserializer.cpp - FileDirectiveSerializer.cpp - - AckInfo.cpp - AckPduSerializer.cpp - AckPduDeserializer.cpp - EofInfo.cpp - EofPduSerializer.cpp - EofPduDeserializer.cpp - NakInfo.cpp - NakPduSerializer.cpp - NakPduDeserializer.cpp - FinishedInfo.cpp - FinishedPduSerializer.cpp - FinishedPduDeserializer.cpp - MetadataInfo.cpp - MetadataPduSerializer.cpp - MetadataPduDeserializer.cpp - KeepAlivePduSerializer.cpp - KeepAlivePduDeserializer.cpp - PromptPduSerializer.cpp - PromptPduDeserializer.cpp - - FileDataSerializer.cpp - FileDataDeserializer.cpp - FileDataInfo.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE PduConfig.cpp + HeaderCreator.cpp + HeaderReader.cpp + FileDirectiveReader.cpp + FileDirectiveCreator.cpp + AckInfo.cpp + AckPduCreator.cpp + AckPduReader.cpp + EofInfo.cpp + EofPduCreator.cpp + EofPduReader.cpp + NakInfo.cpp + NakPduCreator.cpp + NakPduReader.cpp + FinishedInfo.cpp + FinishedPduCreator.cpp + FinishedPduReader.cpp + MetadataInfo.cpp + MetadataPduCreator.cpp + MetadataPduReader.cpp + KeepAlivePduCreator.cpp + KeepAlivePduReader.cpp + PromptPduCreator.cpp + PromptPduReader.cpp + FileDataCreator.cpp + FileDataReader.cpp + FileDataInfo.cpp) diff --git a/src/fsfw/cfdp/pdu/EofInfo.h b/src/fsfw/cfdp/pdu/EofInfo.h index fa8adfd9..4b4fb057 100644 --- a/src/fsfw/cfdp/pdu/EofInfo.h +++ b/src/fsfw/cfdp/pdu/EofInfo.h @@ -7,16 +7,16 @@ struct EofInfo { public: - EofInfo(EntityIdTlv* faultLoc = nullptr); + explicit EofInfo(EntityIdTlv* faultLoc = nullptr); EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::FileSize fileSize, EntityIdTlv* faultLoc = nullptr); size_t getSerializedSize(bool fssLarge = false); - uint32_t getChecksum() const; - cfdp::ConditionCode getConditionCode() const; + [[nodiscard]] uint32_t getChecksum() const; + [[nodiscard]] cfdp::ConditionCode getConditionCode() const; - EntityIdTlv* getFaultLoc() const; + [[nodiscard]] EntityIdTlv* getFaultLoc() const; cfdp::FileSize& getFileSize(); void setChecksum(uint32_t checksum); void setConditionCode(cfdp::ConditionCode conditionCode); diff --git a/src/fsfw/cfdp/pdu/EofPduSerializer.cpp b/src/fsfw/cfdp/pdu/EofPduCreator.cpp similarity index 54% rename from src/fsfw/cfdp/pdu/EofPduSerializer.cpp rename to src/fsfw/cfdp/pdu/EofPduCreator.cpp index e9fe0ca0..12a3e696 100644 --- a/src/fsfw/cfdp/pdu/EofPduSerializer.cpp +++ b/src/fsfw/cfdp/pdu/EofPduCreator.cpp @@ -1,22 +1,18 @@ -#include "EofPduSerializer.h" +#include "EofPduCreator.h" #include "fsfw/FSFW.h" -#include "fsfw/serviceinterface.h" -EofPduSerializer::EofPduSerializer(PduConfig &conf, EofInfo &info) - : FileDirectiveSerializer(conf, cfdp::FileDirectives::EOF_DIRECTIVE, 9), info(info) { - setDirectiveDataFieldLen(info.getSerializedSize(getLargeFileFlag())); +EofPduCreator::EofPduCreator(PduConfig &conf, EofInfo &info) + : FileDirectiveCreator(conf, cfdp::FileDirective::EOF_DIRECTIVE, 9), info(info) { + setDirectiveDataFieldLen(info.getSerializedSize(HeaderCreator::getLargeFileFlag())); } -size_t EofPduSerializer::getSerializedSize() const { - return FileDirectiveSerializer::getWholePduSize(); -} +size_t EofPduCreator::getSerializedSize() const { return FileDirectiveCreator::getWholePduSize(); } -ReturnValue_t EofPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const { - ReturnValue_t result = - FileDirectiveSerializer::serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { +ReturnValue_t EofPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const { + ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { return result; } if (*size + 1 > maxSize) { @@ -27,7 +23,7 @@ ReturnValue_t EofPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t *size += 1; uint32_t checksum = info.getChecksum(); result = SerializeAdapter::serialize(&checksum, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (info.getFileSize().isLargeFile()) { diff --git a/src/fsfw/cfdp/pdu/EofPduSerializer.h b/src/fsfw/cfdp/pdu/EofPduCreator.h similarity index 62% rename from src/fsfw/cfdp/pdu/EofPduSerializer.h rename to src/fsfw/cfdp/pdu/EofPduCreator.h index fbdcfe67..f098a5d2 100644 --- a/src/fsfw/cfdp/pdu/EofPduSerializer.h +++ b/src/fsfw/cfdp/pdu/EofPduCreator.h @@ -2,18 +2,20 @@ #define FSFW_SRC_FSFW_CFDP_PDU_EOFPDUSERIALIZER_H_ #include "EofInfo.h" -#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h" +#include "fsfw/cfdp/pdu/FileDirectiveCreator.h" #include "fsfw/cfdp/tlv/EntityIdTlv.h" -class EofPduSerializer : public FileDirectiveSerializer { +class EofPduCreator : public FileDirectiveCreator { public: - EofPduSerializer(PduConfig& conf, EofInfo& info); + EofPduCreator(PduConfig& conf, EofInfo& info); - size_t getSerializedSize() const override; + [[nodiscard]] size_t getSerializedSize() const override; ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness) const override; + using FileDirectiveCreator::serialize; + private: EofInfo& info; }; diff --git a/src/fsfw/cfdp/pdu/EofPduDeserializer.h b/src/fsfw/cfdp/pdu/EofPduDeserializer.h deleted file mode 100644 index 8f62b25a..00000000 --- a/src/fsfw/cfdp/pdu/EofPduDeserializer.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef FSFW_SRC_FSFW_CFDP_PDU_EOFPDUDESERIALIZER_H_ -#define FSFW_SRC_FSFW_CFDP_PDU_EOFPDUDESERIALIZER_H_ - -#include "EofInfo.h" -#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h" - -class EofPduDeserializer : public FileDirectiveDeserializer { - public: - EofPduDeserializer(const uint8_t* pduBuf, size_t maxSize, EofInfo& eofInfo); - - virtual ReturnValue_t parseData() override; - - private: - EofInfo& info; -}; - -#endif /* FSFW_SRC_FSFW_CFDP_PDU_EOFPDUDESERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/EofPduDeserializer.cpp b/src/fsfw/cfdp/pdu/EofPduReader.cpp similarity index 74% rename from src/fsfw/cfdp/pdu/EofPduDeserializer.cpp rename to src/fsfw/cfdp/pdu/EofPduReader.cpp index e1ab8dc9..c80c501c 100644 --- a/src/fsfw/cfdp/pdu/EofPduDeserializer.cpp +++ b/src/fsfw/cfdp/pdu/EofPduReader.cpp @@ -1,23 +1,23 @@ -#include "EofPduDeserializer.h" +#include "EofPduReader.h" #include "fsfw/FSFW.h" #include "fsfw/serviceinterface.h" -EofPduDeserializer::EofPduDeserializer(const uint8_t* pduBuf, size_t maxSize, EofInfo& eofInfo) - : FileDirectiveDeserializer(pduBuf, maxSize), info(eofInfo) {} +EofPduReader::EofPduReader(const uint8_t* pduBuf, size_t maxSize, EofInfo& eofInfo) + : FileDirectiveReader(pduBuf, maxSize), info(eofInfo) {} -ReturnValue_t EofPduDeserializer::parseData() { - ReturnValue_t result = FileDirectiveDeserializer::parseData(); - if (result != HasReturnvaluesIF::RETURN_OK) { +ReturnValue_t EofPduReader::parseData() { + ReturnValue_t result = FileDirectiveReader::parseData(); + if (result != returnvalue::OK) { return result; } - const uint8_t* bufPtr = rawPtr; + const uint8_t* bufPtr = pointers.rawPtr; size_t expectedFileFieldLen = 4; if (this->getLargeFileFlag()) { expectedFileFieldLen = 8; } - size_t currentIdx = FileDirectiveDeserializer::getHeaderSize(); + size_t currentIdx = FileDirectiveReader::getHeaderSize(); size_t deserLen = maxSize; if (maxSize < currentIdx + 5 + expectedFileFieldLen) { return SerializeIF::STREAM_TOO_SHORT; @@ -31,7 +31,7 @@ ReturnValue_t EofPduDeserializer::parseData() { uint32_t checksum = 0; auto endianness = getEndianness(); result = SerializeAdapter::deSerialize(&checksum, &bufPtr, &deserLen, endianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } info.setChecksum(checksum); @@ -44,7 +44,7 @@ ReturnValue_t EofPduDeserializer::parseData() { result = SerializeAdapter::deSerialize(&fileSizeValue, &bufPtr, &deserLen, endianness); info.setFileSize(fileSizeValue, false); } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (info.getConditionCode() != cfdp::ConditionCode::NO_ERROR) { @@ -61,7 +61,7 @@ ReturnValue_t EofPduDeserializer::parseData() { " given TLV pointer invalid"); #endif #endif /* FSFW_VERBOSE_LEVEL >= 1 */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } result = tlvPtr->deSerialize(&bufPtr, &deserLen, endianness); } diff --git a/src/fsfw/cfdp/pdu/EofPduReader.h b/src/fsfw/cfdp/pdu/EofPduReader.h new file mode 100644 index 00000000..456ea0dc --- /dev/null +++ b/src/fsfw/cfdp/pdu/EofPduReader.h @@ -0,0 +1,17 @@ +#ifndef FSFW_SRC_FSFW_CFDP_PDU_EOFPDUDESERIALIZER_H_ +#define FSFW_SRC_FSFW_CFDP_PDU_EOFPDUDESERIALIZER_H_ + +#include "EofInfo.h" +#include "fsfw/cfdp/pdu/FileDirectiveReader.h" + +class EofPduReader : public FileDirectiveReader { + public: + EofPduReader(const uint8_t* pduBuf, size_t maxSize, EofInfo& eofInfo); + + ReturnValue_t parseData() override; + + private: + EofInfo& info; +}; + +#endif /* FSFW_SRC_FSFW_CFDP_PDU_EOFPDUDESERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/FileDataSerializer.cpp b/src/fsfw/cfdp/pdu/FileDataCreator.cpp similarity index 56% rename from src/fsfw/cfdp/pdu/FileDataSerializer.cpp rename to src/fsfw/cfdp/pdu/FileDataCreator.cpp index 837b418b..956752fb 100644 --- a/src/fsfw/cfdp/pdu/FileDataSerializer.cpp +++ b/src/fsfw/cfdp/pdu/FileDataCreator.cpp @@ -1,28 +1,31 @@ -#include "FileDataSerializer.h" +#include "FileDataCreator.h" #include -FileDataSerializer::FileDataSerializer(PduConfig& conf, FileDataInfo& info) - : HeaderSerializer(conf, cfdp::PduType::FILE_DATA, 0, info.getSegmentMetadataFlag()), - info(info) { +FileDataCreator::FileDataCreator(PduConfig& conf, FileDataInfo& info) + : HeaderCreator(conf, cfdp::PduType::FILE_DATA, 0, info.getSegmentMetadataFlag()), info(info) { update(); } -void FileDataSerializer::update() { +void FileDataCreator::update() { this->setSegmentMetadataFlag(info.getSegmentMetadataFlag()); this->setSegmentationControl(info.getSegmentationControl()); setPduDataFieldLen(info.getSerializedSize(this->getLargeFileFlag())); } -ReturnValue_t FileDataSerializer::serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const { - ReturnValue_t result = HeaderSerializer::serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; +ReturnValue_t FileDataCreator::serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const { + if (buffer == nullptr or size == nullptr) { + return returnvalue::FAILED; } - if (*size + this->getSerializedSize() > maxSize) { + if (*size + getSerializedSize() > maxSize) { return SerializeIF::BUFFER_TOO_SHORT; } + ReturnValue_t result = HeaderCreator::serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + const uint8_t* readOnlyPtr = nullptr; if (this->hasSegmentMetadataFlag()) { size_t segmentMetadataLen = info.getSegmentMetadataLen(); @@ -36,7 +39,7 @@ ReturnValue_t FileDataSerializer::serialize(uint8_t** buffer, size_t* size, size } cfdp::FileSize& offset = info.getOffset(); result = offset.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } size_t fileSize = 0; @@ -47,9 +50,9 @@ ReturnValue_t FileDataSerializer::serialize(uint8_t** buffer, size_t* size, size std::memcpy(*buffer, readOnlyPtr, fileSize); *buffer += fileSize; *size += fileSize; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } -size_t FileDataSerializer::getSerializedSize() const { - return HeaderSerializer::getSerializedSize() + info.getSerializedSize(this->getLargeFileFlag()); +size_t FileDataCreator::getSerializedSize() const { + return HeaderCreator::getSerializedSize() + info.getSerializedSize(this->getLargeFileFlag()); } diff --git a/src/fsfw/cfdp/pdu/FileDataCreator.h b/src/fsfw/cfdp/pdu/FileDataCreator.h new file mode 100644 index 00000000..2ce8989d --- /dev/null +++ b/src/fsfw/cfdp/pdu/FileDataCreator.h @@ -0,0 +1,27 @@ +#ifndef FSFW_CFDP_PDU_FILEDATASERIALIZER_H_ +#define FSFW_CFDP_PDU_FILEDATASERIALIZER_H_ + +#include "../definitions.h" +#include "FileDataInfo.h" +#include "HeaderCreator.h" + +class FileDataCreator : public HeaderCreator { + public: + FileDataCreator(PduConfig& conf, FileDataInfo& info); + + void update(); + + ReturnValue_t serialize(uint8_t* buf, size_t& serLen, size_t maxSize) const { + return SerializeIF::serialize(buf, serLen, maxSize, SerializeIF::Endianness::NETWORK); + } + + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override; + + [[nodiscard]] size_t getSerializedSize() const override; + + private: + FileDataInfo& info; +}; + +#endif /* FSFW_CFDP_PDU_FILEDATASERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/FileDataDeserializer.cpp b/src/fsfw/cfdp/pdu/FileDataDeserializer.cpp deleted file mode 100644 index 240c4188..00000000 --- a/src/fsfw/cfdp/pdu/FileDataDeserializer.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "FileDataDeserializer.h" - -FileDataDeserializer::FileDataDeserializer(const uint8_t* pduBuf, size_t maxSize, - FileDataInfo& info) - : HeaderDeserializer(pduBuf, maxSize), info(info) {} - -ReturnValue_t FileDataDeserializer::parseData() { - ReturnValue_t result = HeaderDeserializer::parseData(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - size_t currentIdx = HeaderDeserializer::getHeaderSize(); - const uint8_t* buf = rawPtr + currentIdx; - size_t remSize = HeaderDeserializer::getWholePduSize() - currentIdx; - if (remSize < 1) { - return SerializeIF::STREAM_TOO_SHORT; - } - if (hasSegmentMetadataFlag()) { - info.setSegmentMetadataFlag(true); - info.setRecordContinuationState(static_cast((*buf >> 6) & 0b11)); - size_t segmentMetadataLen = *buf & 0b00111111; - info.setSegmentMetadataLen(segmentMetadataLen); - if (remSize < segmentMetadataLen + 1) { - return SerializeIF::STREAM_TOO_SHORT; - } - if (segmentMetadataLen > 0) { - buf += 1; - remSize -= 1; - info.setSegmentMetadata(buf); - buf += segmentMetadataLen; - remSize -= segmentMetadataLen; - } - } - result = info.getOffset().deSerialize(&buf, &remSize, this->getEndianness()); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - if (remSize > 0) { - info.setFileData(buf, remSize); - } - return HasReturnvaluesIF::RETURN_OK; -} - -SerializeIF::Endianness FileDataDeserializer::getEndianness() const { return endianness; } - -void FileDataDeserializer::setEndianness(SerializeIF::Endianness endianness) { - this->endianness = endianness; -} diff --git a/src/fsfw/cfdp/pdu/FileDataInfo.cpp b/src/fsfw/cfdp/pdu/FileDataInfo.cpp index c410adce..19fc00cd 100644 --- a/src/fsfw/cfdp/pdu/FileDataInfo.cpp +++ b/src/fsfw/cfdp/pdu/FileDataInfo.cpp @@ -50,23 +50,23 @@ ReturnValue_t FileDataInfo::addSegmentMetadataInfo(cfdp::RecordContinuationState this->segmentMetadataFlag = cfdp::SegmentMetadataFlag::PRESENT; this->recContState = recContState; if (segmentMetadataLen > 63) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } this->segmentMetadata = segmentMetadata; this->segmentMetadataLen = segmentMetadataLen; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } -const uint8_t *FileDataInfo::getFileData(size_t *fileSize) const { - if (fileSize != nullptr) { - *fileSize = this->fileSize; +const uint8_t *FileDataInfo::getFileData(size_t *fileSize_) const { + if (fileSize_ != nullptr) { + *fileSize_ = this->fileSize; } return fileData; } -const uint8_t *FileDataInfo::getSegmentMetadata(size_t *segmentMetadataLen) { - if (segmentMetadataLen != nullptr) { - *segmentMetadataLen = this->segmentMetadataLen; +const uint8_t *FileDataInfo::getSegmentMetadata(size_t *segmentMetadataLen_) { + if (segmentMetadataLen_ != nullptr) { + *segmentMetadataLen_ = this->segmentMetadataLen; } return segmentMetadata; } diff --git a/src/fsfw/cfdp/pdu/FileDataInfo.h b/src/fsfw/cfdp/pdu/FileDataInfo.h index 7fd573db..36908d8b 100644 --- a/src/fsfw/cfdp/pdu/FileDataInfo.h +++ b/src/fsfw/cfdp/pdu/FileDataInfo.h @@ -6,25 +6,25 @@ class FileDataInfo { public: - FileDataInfo(cfdp::FileSize& offset); + explicit FileDataInfo(cfdp::FileSize& offset); FileDataInfo(cfdp::FileSize& offset, const uint8_t* fileData, size_t fileSize); - size_t getSerializedSize(bool largeFile = false) const; + [[nodiscard]] size_t getSerializedSize(bool largeFile = false) const; cfdp::FileSize& getOffset(); const uint8_t* getFileData(size_t* fileSize = nullptr) const; void setFileData(const uint8_t* fileData, size_t fileSize); - cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const; - cfdp::SegmentationControl getSegmentationControl() const; - cfdp::RecordContinuationState getRecordContinuationState() const; + [[nodiscard]] cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const; + [[nodiscard]] cfdp::SegmentationControl getSegmentationControl() const; + [[nodiscard]] cfdp::RecordContinuationState getRecordContinuationState() const; void setRecordContinuationState(cfdp::RecordContinuationState recContState); void setSegmentationControl(cfdp::SegmentationControl segCtrl); - size_t getSegmentMetadataLen() const; + [[nodiscard]] size_t getSegmentMetadataLen() const; void setSegmentMetadataLen(size_t len); void setSegmentMetadata(const uint8_t* ptr); - bool hasSegmentMetadata() const; + [[nodiscard]] bool hasSegmentMetadata() const; void setSegmentMetadataFlag(bool enable); ReturnValue_t addSegmentMetadataInfo(cfdp::RecordContinuationState recContState, const uint8_t* segmentMetadata, size_t segmentMetadataLen); diff --git a/src/fsfw/cfdp/pdu/FileDataReader.cpp b/src/fsfw/cfdp/pdu/FileDataReader.cpp new file mode 100644 index 00000000..9155ef28 --- /dev/null +++ b/src/fsfw/cfdp/pdu/FileDataReader.cpp @@ -0,0 +1,47 @@ +#include "FileDataReader.h" + +FileDataReader::FileDataReader(const uint8_t* pduBuf, size_t maxSize, FileDataInfo& info) + : PduHeaderReader(pduBuf, maxSize), info(info) {} + +ReturnValue_t FileDataReader::parseData() { + ReturnValue_t result = PduHeaderReader::parseData(); + if (result != returnvalue::OK) { + return result; + } + size_t currentIdx = PduHeaderReader::getHeaderSize(); + const uint8_t* buf = pointers.rawPtr + currentIdx; + size_t remSize = PduHeaderReader::getWholePduSize() - currentIdx; + if (remSize < 1) { + return SerializeIF::STREAM_TOO_SHORT; + } + if (hasSegmentMetadataFlag()) { + info.setSegmentMetadataFlag(true); + info.setRecordContinuationState(static_cast((*buf >> 6) & 0b11)); + size_t segmentMetadataLen = *buf & 0b00111111; + info.setSegmentMetadataLen(segmentMetadataLen); + if (remSize < segmentMetadataLen + 1) { + return SerializeIF::STREAM_TOO_SHORT; + } + if (segmentMetadataLen > 0) { + buf += 1; + remSize -= 1; + info.setSegmentMetadata(buf); + buf += segmentMetadataLen; + remSize -= segmentMetadataLen; + } + } + result = info.getOffset().deSerialize(&buf, &remSize, this->getEndianness()); + if (result != returnvalue::OK) { + return result; + } + if (remSize > 0) { + info.setFileData(buf, remSize); + } + return returnvalue::OK; +} + +SerializeIF::Endianness FileDataReader::getEndianness() const { return endianness; } + +void FileDataReader::setEndianness(SerializeIF::Endianness endianness_) { + endianness = endianness_; +} diff --git a/src/fsfw/cfdp/pdu/FileDataDeserializer.h b/src/fsfw/cfdp/pdu/FileDataReader.h similarity index 63% rename from src/fsfw/cfdp/pdu/FileDataDeserializer.h rename to src/fsfw/cfdp/pdu/FileDataReader.h index 833c0561..aa962e2b 100644 --- a/src/fsfw/cfdp/pdu/FileDataDeserializer.h +++ b/src/fsfw/cfdp/pdu/FileDataReader.h @@ -3,14 +3,14 @@ #include "../definitions.h" #include "FileDataInfo.h" -#include "HeaderDeserializer.h" +#include "PduHeaderReader.h" -class FileDataDeserializer : public HeaderDeserializer { +class FileDataReader : public PduHeaderReader { public: - FileDataDeserializer(const uint8_t* pduBuf, size_t maxSize, FileDataInfo& info); + FileDataReader(const uint8_t* pduBuf, size_t maxSize, FileDataInfo& info); - ReturnValue_t parseData(); - SerializeIF::Endianness getEndianness() const; + ReturnValue_t parseData() override; + [[nodiscard]] SerializeIF::Endianness getEndianness() const; void setEndianness(SerializeIF::Endianness endianness = SerializeIF::Endianness::NETWORK); private: diff --git a/src/fsfw/cfdp/pdu/FileDataSerializer.h b/src/fsfw/cfdp/pdu/FileDataSerializer.h deleted file mode 100644 index 662b9b4d..00000000 --- a/src/fsfw/cfdp/pdu/FileDataSerializer.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDATASERIALIZER_H_ -#define FSFW_SRC_FSFW_CFDP_PDU_FILEDATASERIALIZER_H_ - -#include "../definitions.h" -#include "FileDataInfo.h" -#include "HeaderSerializer.h" - -class FileDataSerializer : public HeaderSerializer { - public: - FileDataSerializer(PduConfig& conf, FileDataInfo& info); - - void update(); - - ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const override; - - size_t getSerializedSize() const override; - - private: - FileDataInfo& info; -}; - -#endif /* FSFW_SRC_FSFW_CFDP_PDU_FILEDATADESERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/FileDirectiveCreator.cpp b/src/fsfw/cfdp/pdu/FileDirectiveCreator.cpp new file mode 100644 index 00000000..20f93df9 --- /dev/null +++ b/src/fsfw/cfdp/pdu/FileDirectiveCreator.cpp @@ -0,0 +1,39 @@ +#include "FileDirectiveCreator.h" + +FileDirectiveCreator::FileDirectiveCreator(PduConfig &pduConf, cfdp::FileDirective directiveCode, + size_t directiveParamFieldLen) + : HeaderCreator(pduConf, cfdp::PduType::FILE_DIRECTIVE, directiveParamFieldLen + 1), + directiveCode(directiveCode) {} + +size_t FileDirectiveCreator::getSerializedSize() const { + return HeaderCreator::getSerializedSize() + 1; +} + +ReturnValue_t FileDirectiveCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const { + if (buffer == nullptr or size == nullptr) { + return returnvalue::FAILED; + } + if (FileDirectiveCreator::getWholePduSize() > maxSize) { + return BUFFER_TOO_SHORT; + } + ReturnValue_t result = HeaderCreator::serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + + if (*size >= maxSize) { + return BUFFER_TOO_SHORT; + } + **buffer = directiveCode; + *buffer += 1; + *size += 1; + return returnvalue::OK; +} + +void FileDirectiveCreator::setDirectiveDataFieldLen(size_t len) { + // Set length of data field plus 1 byte for the directive octet + HeaderCreator::setPduDataFieldLen(len + 1); +} + +cfdp::FileDirective FileDirectiveCreator::getDirectiveCode() const { return directiveCode; } diff --git a/src/fsfw/cfdp/pdu/FileDirectiveCreator.h b/src/fsfw/cfdp/pdu/FileDirectiveCreator.h new file mode 100644 index 00000000..9b7f2f52 --- /dev/null +++ b/src/fsfw/cfdp/pdu/FileDirectiveCreator.h @@ -0,0 +1,34 @@ +#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_ +#define FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_ + +#include "fsfw/cfdp/pdu/HeaderCreator.h" + +class FileDirectiveCreator : public HeaderCreator { + public: + FileDirectiveCreator(PduConfig& pduConf, cfdp::FileDirective directiveCode, + size_t directiveParamFieldLen); + + [[nodiscard]] cfdp::FileDirective getDirectiveCode() const; + + /** + * This only returns the size of the PDU header + 1 for the directive code octet. + * Use FileDirectiveCreator::getWholePduSize to get the full packet length, assuming + * the length fields was set correctly + * @return + */ + [[nodiscard]] size_t getSerializedSize() const override; + + [[nodiscard]] ReturnValue_t serialize(uint8_t* buffer, size_t& serLen, size_t maxSize) const { + return SerializeIF::serialize(buffer, serLen, maxSize, SerializeIF::Endianness::NETWORK); + } + + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override; + + void setDirectiveDataFieldLen(size_t len); + + private: + cfdp::FileDirective directiveCode = cfdp::FileDirective::INVALID_DIRECTIVE; +}; + +#endif /* FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/FileDirectiveDeserializer.cpp b/src/fsfw/cfdp/pdu/FileDirectiveDeserializer.cpp deleted file mode 100644 index 3c0552f7..00000000 --- a/src/fsfw/cfdp/pdu/FileDirectiveDeserializer.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "FileDirectiveDeserializer.h" - -FileDirectiveDeserializer::FileDirectiveDeserializer(const uint8_t *pduBuf, size_t maxSize) - : HeaderDeserializer(pduBuf, maxSize) {} - -cfdp::FileDirectives FileDirectiveDeserializer::getFileDirective() const { return fileDirective; } - -ReturnValue_t FileDirectiveDeserializer::parseData() { - ReturnValue_t result = HeaderDeserializer::parseData(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - if (this->getPduDataFieldLen() < 1) { - return cfdp::INVALID_PDU_DATAFIELD_LEN; - } - if (FileDirectiveDeserializer::getWholePduSize() > maxSize) { - return SerializeIF::STREAM_TOO_SHORT; - } - size_t currentIdx = HeaderDeserializer::getHeaderSize(); - if (not checkFileDirective(rawPtr[currentIdx])) { - return cfdp::INVALID_DIRECTIVE_FIELDS; - } - setFileDirective(static_cast(rawPtr[currentIdx])); - return HasReturnvaluesIF::RETURN_OK; -} - -size_t FileDirectiveDeserializer::getHeaderSize() const { - // return size of header plus the directive byte - return HeaderDeserializer::getHeaderSize() + 1; -} - -bool FileDirectiveDeserializer::checkFileDirective(uint8_t rawByte) { - if (rawByte < cfdp::FileDirectives::EOF_DIRECTIVE or - (rawByte > cfdp::FileDirectives::PROMPT and rawByte != cfdp::FileDirectives::KEEP_ALIVE)) { - // Invalid directive field. TODO: Custom returnvalue - return false; - } - return true; -} - -void FileDirectiveDeserializer::setFileDirective(cfdp::FileDirectives fileDirective) { - this->fileDirective = fileDirective; -} - -void FileDirectiveDeserializer::setEndianness(SerializeIF::Endianness endianness) { - this->endianness = endianness; -} - -SerializeIF::Endianness FileDirectiveDeserializer::getEndianness() const { return endianness; } diff --git a/src/fsfw/cfdp/pdu/FileDirectiveReader.cpp b/src/fsfw/cfdp/pdu/FileDirectiveReader.cpp new file mode 100644 index 00000000..f5fc6e58 --- /dev/null +++ b/src/fsfw/cfdp/pdu/FileDirectiveReader.cpp @@ -0,0 +1,49 @@ +#include "FileDirectiveReader.h" + +FileDirectiveReader::FileDirectiveReader(const uint8_t *pduBuf, size_t maxSize) + : PduHeaderReader(pduBuf, maxSize) {} + +cfdp::FileDirective FileDirectiveReader::getFileDirective() const { return fileDirective; } + +ReturnValue_t FileDirectiveReader::parseData() { + ReturnValue_t result = PduHeaderReader::parseData(); + if (result != returnvalue::OK) { + return result; + } + if (this->getPduDataFieldLen() < 1) { + return cfdp::INVALID_PDU_DATAFIELD_LEN; + } + if (FileDirectiveReader::getWholePduSize() > maxSize) { + return SerializeIF::STREAM_TOO_SHORT; + } + size_t currentIdx = PduHeaderReader::getHeaderSize(); + if (not checkFileDirective(pointers.rawPtr[currentIdx])) { + return cfdp::INVALID_DIRECTIVE_FIELD; + } + setFileDirective(static_cast(pointers.rawPtr[currentIdx])); + return returnvalue::OK; +} + +size_t FileDirectiveReader::getHeaderSize() const { + // return size of header plus the directive byte + return PduHeaderReader::getHeaderSize() + 1; +} + +bool FileDirectiveReader::checkFileDirective(uint8_t rawByte) { + if (rawByte < cfdp::FileDirective::EOF_DIRECTIVE or + (rawByte > cfdp::FileDirective::PROMPT and rawByte != cfdp::FileDirective::KEEP_ALIVE)) { + // Invalid directive field + return false; + } + return true; +} + +void FileDirectiveReader::setFileDirective(cfdp::FileDirective fileDirective_) { + fileDirective = fileDirective_; +} + +void FileDirectiveReader::setEndianness(SerializeIF::Endianness endianness_) { + endianness = endianness_; +} + +SerializeIF::Endianness FileDirectiveReader::getEndianness() const { return endianness; } diff --git a/src/fsfw/cfdp/pdu/FileDirectiveDeserializer.h b/src/fsfw/cfdp/pdu/FileDirectiveReader.h similarity index 57% rename from src/fsfw/cfdp/pdu/FileDirectiveDeserializer.h rename to src/fsfw/cfdp/pdu/FileDirectiveReader.h index 064cb64a..9e88e006 100644 --- a/src/fsfw/cfdp/pdu/FileDirectiveDeserializer.h +++ b/src/fsfw/cfdp/pdu/FileDirectiveReader.h @@ -2,7 +2,7 @@ #define FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVEDESERIALIZER_H_ #include "../definitions.h" -#include "fsfw/cfdp/pdu/HeaderDeserializer.h" +#include "fsfw/cfdp/pdu/PduHeaderReader.h" /** * @brief This class is used to deserialize a PDU file directive header from raw memory. @@ -11,28 +11,27 @@ * This is a zero-copy implementation and #parseData needs to be called to ensure the data is * valid. */ -class FileDirectiveDeserializer : public HeaderDeserializer { +class FileDirectiveReader : public PduHeaderReader { public: - FileDirectiveDeserializer(const uint8_t* pduBuf, size_t maxSize); + FileDirectiveReader(const uint8_t* pduBuf, size_t maxSize); /** * This needs to be called before accessing the PDU fields to avoid segmentation faults. * @return */ - virtual ReturnValue_t parseData(); - size_t getHeaderSize() const; + ReturnValue_t parseData() override; + [[nodiscard]] size_t getHeaderSize() const override; - cfdp::FileDirectives getFileDirective() const; + [[nodiscard]] cfdp::FileDirective getFileDirective() const; void setEndianness(SerializeIF::Endianness endianness); - SerializeIF::Endianness getEndianness() const; + [[nodiscard]] SerializeIF::Endianness getEndianness() const; + static bool checkFileDirective(uint8_t rawByte); protected: - bool checkFileDirective(uint8_t rawByte); - private: - void setFileDirective(cfdp::FileDirectives fileDirective); - cfdp::FileDirectives fileDirective = cfdp::FileDirectives::INVALID_DIRECTIVE; + void setFileDirective(cfdp::FileDirective fileDirective); + cfdp::FileDirective fileDirective = cfdp::FileDirective::INVALID_DIRECTIVE; SerializeIF::Endianness endianness = SerializeIF::Endianness::NETWORK; }; diff --git a/src/fsfw/cfdp/pdu/FileDirectiveSerializer.cpp b/src/fsfw/cfdp/pdu/FileDirectiveSerializer.cpp deleted file mode 100644 index 98b2d0a2..00000000 --- a/src/fsfw/cfdp/pdu/FileDirectiveSerializer.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "FileDirectiveSerializer.h" - -FileDirectiveSerializer::FileDirectiveSerializer(PduConfig &pduConf, - cfdp::FileDirectives directiveCode, - size_t directiveParamFieldLen) - : HeaderSerializer(pduConf, cfdp::PduType::FILE_DIRECTIVE, directiveParamFieldLen + 1), - directiveCode(directiveCode) {} - -size_t FileDirectiveSerializer::getSerializedSize() const { - return HeaderSerializer::getSerializedSize() + 1; -} - -ReturnValue_t FileDirectiveSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const { - if (buffer == nullptr or size == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - if (FileDirectiveSerializer::getWholePduSize() > maxSize) { - return BUFFER_TOO_SHORT; - } - ReturnValue_t result = HeaderSerializer::serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - if (*size >= maxSize) { - return BUFFER_TOO_SHORT; - } - **buffer = directiveCode; - *buffer += 1; - *size += 1; - return HasReturnvaluesIF::RETURN_OK; -} - -void FileDirectiveSerializer::setDirectiveDataFieldLen(size_t len) { - // Set length of data field plus 1 byte for the directive octet - HeaderSerializer::setPduDataFieldLen(len + 1); -} diff --git a/src/fsfw/cfdp/pdu/FileDirectiveSerializer.h b/src/fsfw/cfdp/pdu/FileDirectiveSerializer.h deleted file mode 100644 index 8f86a5e1..00000000 --- a/src/fsfw/cfdp/pdu/FileDirectiveSerializer.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_ -#define FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_ - -#include "fsfw/cfdp/pdu/HeaderSerializer.h" - -class FileDirectiveSerializer : public HeaderSerializer { - public: - FileDirectiveSerializer(PduConfig& pduConf, cfdp::FileDirectives directiveCode, - size_t directiveParamFieldLen); - - /** - * This only returns the size of the PDU header + 1 for the directive code octet. - * Use FileDirectiveSerializer::getWholePduSize to get the full packet length, assuming - * the length fields was set correctly - * @return - */ - size_t getSerializedSize() const override; - - ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const override; - - void setDirectiveDataFieldLen(size_t len); - - private: - cfdp::FileDirectives directiveCode = cfdp::FileDirectives::INVALID_DIRECTIVE; -}; - -#endif /* FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/FinishedInfo.cpp b/src/fsfw/cfdp/pdu/FinishedInfo.cpp index c32372a1..2f986e85 100644 --- a/src/fsfw/cfdp/pdu/FinishedInfo.cpp +++ b/src/fsfw/cfdp/pdu/FinishedInfo.cpp @@ -2,9 +2,8 @@ FinishedInfo::FinishedInfo() {} -FinishedInfo::FinishedInfo(cfdp::ConditionCode conditionCode, - cfdp::FinishedDeliveryCode deliveryCode, - cfdp::FinishedFileStatus fileStatus) +FinishedInfo::FinishedInfo(cfdp::ConditionCode conditionCode, cfdp::FileDeliveryCode deliveryCode, + cfdp::FileDeliveryStatus fileStatus) : conditionCode(conditionCode), deliveryCode(deliveryCode), fileStatus(fileStatus) {} size_t FinishedInfo::getSerializedSize() const { @@ -46,14 +45,14 @@ ReturnValue_t FinishedInfo::setFilestoreResponsesArray(FilestoreResponseTlv** fs if (maxFsResponsesLen != nullptr) { this->fsResponsesMaxLen = *maxFsResponsesLen; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t FinishedInfo::getFilestoreResonses(FilestoreResponseTlv*** fsResponses, size_t* fsResponsesLen, size_t* fsResponsesMaxLen) { if (fsResponses == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } *fsResponses = this->fsResponses; if (fsResponsesLen != nullptr) { @@ -62,7 +61,7 @@ ReturnValue_t FinishedInfo::getFilestoreResonses(FilestoreResponseTlv*** fsRespo if (fsResponsesMaxLen != nullptr) { *fsResponsesMaxLen = this->fsResponsesMaxLen; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void FinishedInfo::setFaultLocation(EntityIdTlv* faultLocation) { @@ -71,10 +70,10 @@ void FinishedInfo::setFaultLocation(EntityIdTlv* faultLocation) { ReturnValue_t FinishedInfo::getFaultLocation(EntityIdTlv** faultLocation) { if (this->faultLocation == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } *faultLocation = this->faultLocation; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } cfdp::ConditionCode FinishedInfo::getConditionCode() const { return conditionCode; } @@ -83,13 +82,13 @@ void FinishedInfo::setConditionCode(cfdp::ConditionCode conditionCode) { this->conditionCode = conditionCode; } -cfdp::FinishedDeliveryCode FinishedInfo::getDeliveryCode() const { return deliveryCode; } +cfdp::FileDeliveryCode FinishedInfo::getDeliveryCode() const { return deliveryCode; } -void FinishedInfo::setDeliveryCode(cfdp::FinishedDeliveryCode deliveryCode) { +void FinishedInfo::setDeliveryCode(cfdp::FileDeliveryCode deliveryCode) { this->deliveryCode = deliveryCode; } -cfdp::FinishedFileStatus FinishedInfo::getFileStatus() const { return fileStatus; } +cfdp::FileDeliveryStatus FinishedInfo::getFileStatus() const { return fileStatus; } void FinishedInfo::setFilestoreResponsesArrayLen(size_t fsResponsesLen) { this->fsResponsesLen = fsResponsesLen; @@ -97,6 +96,6 @@ void FinishedInfo::setFilestoreResponsesArrayLen(size_t fsResponsesLen) { size_t FinishedInfo::getFsResponsesLen() const { return fsResponsesLen; } -void FinishedInfo::setFileStatus(cfdp::FinishedFileStatus fileStatus) { +void FinishedInfo::setFileStatus(cfdp::FileDeliveryStatus fileStatus) { this->fileStatus = fileStatus; } diff --git a/src/fsfw/cfdp/pdu/FinishedInfo.h b/src/fsfw/cfdp/pdu/FinishedInfo.h index 5768a298..49d7c64d 100644 --- a/src/fsfw/cfdp/pdu/FinishedInfo.h +++ b/src/fsfw/cfdp/pdu/FinishedInfo.h @@ -8,13 +8,13 @@ class FinishedInfo { public: FinishedInfo(); - FinishedInfo(cfdp::ConditionCode conditionCode, cfdp::FinishedDeliveryCode deliveryCode, - cfdp::FinishedFileStatus fileStatus); + FinishedInfo(cfdp::ConditionCode conditionCode, cfdp::FileDeliveryCode deliveryCode, + cfdp::FileDeliveryStatus fileStatus); - size_t getSerializedSize() const; + [[nodiscard]] size_t getSerializedSize() const; - bool hasFsResponses() const; - bool canHoldFsResponses() const; + [[nodiscard]] bool hasFsResponses() const; + [[nodiscard]] bool canHoldFsResponses() const; ReturnValue_t setFilestoreResponsesArray(FilestoreResponseTlv** fsResponses, size_t* fsResponsesLen, const size_t* maxFsResponseLen); @@ -22,20 +22,20 @@ class FinishedInfo { ReturnValue_t getFilestoreResonses(FilestoreResponseTlv*** fsResponses, size_t* fsResponsesLen, size_t* fsResponsesMaxLen); - size_t getFsResponsesLen() const; + [[nodiscard]] size_t getFsResponsesLen() const; void setFilestoreResponsesArrayLen(size_t fsResponsesLen); ReturnValue_t getFaultLocation(EntityIdTlv** entityId); - cfdp::ConditionCode getConditionCode() const; + [[nodiscard]] cfdp::ConditionCode getConditionCode() const; void setConditionCode(cfdp::ConditionCode conditionCode); - cfdp::FinishedDeliveryCode getDeliveryCode() const; - void setDeliveryCode(cfdp::FinishedDeliveryCode deliveryCode); - cfdp::FinishedFileStatus getFileStatus() const; - void setFileStatus(cfdp::FinishedFileStatus fileStatus); + [[nodiscard]] cfdp::FileDeliveryCode getDeliveryCode() const; + void setDeliveryCode(cfdp::FileDeliveryCode deliveryCode); + [[nodiscard]] cfdp::FileDeliveryStatus getFileStatus() const; + void setFileStatus(cfdp::FileDeliveryStatus fileStatus); private: cfdp::ConditionCode conditionCode = cfdp::ConditionCode::NO_CONDITION_FIELD; - cfdp::FinishedDeliveryCode deliveryCode = cfdp::FinishedDeliveryCode::DATA_COMPLETE; - cfdp::FinishedFileStatus fileStatus = cfdp::FinishedFileStatus::DISCARDED_DELIBERATELY; + cfdp::FileDeliveryCode deliveryCode = cfdp::FileDeliveryCode::DATA_COMPLETE; + cfdp::FileDeliveryStatus fileStatus = cfdp::FileDeliveryStatus::DISCARDED_DELIBERATELY; FilestoreResponseTlv** fsResponses = nullptr; size_t fsResponsesLen = 0; size_t fsResponsesMaxLen = 0; diff --git a/src/fsfw/cfdp/pdu/FinishedPduCreator.cpp b/src/fsfw/cfdp/pdu/FinishedPduCreator.cpp new file mode 100644 index 00000000..d002e8aa --- /dev/null +++ b/src/fsfw/cfdp/pdu/FinishedPduCreator.cpp @@ -0,0 +1,44 @@ +#include "FinishedPduCreator.h" + +FinishPduCreator::FinishPduCreator(PduConfig &conf, FinishedInfo &finishInfo) + : FileDirectiveCreator(conf, cfdp::FileDirective::FINISH, 0), finishInfo(finishInfo) { + updateDirectiveFieldLen(); +} + +size_t FinishPduCreator::getSerializedSize() const { return FinishPduCreator::getWholePduSize(); } + +void FinishPduCreator::updateDirectiveFieldLen() { + setDirectiveDataFieldLen(finishInfo.getSerializedSize()); +} + +ReturnValue_t FinishPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const { + ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + if (*size + 1 > maxSize) { + return SerializeIF::BUFFER_TOO_SHORT; + } + **buffer = finishInfo.getConditionCode() << 4 | finishInfo.getDeliveryCode() << 2 | + finishInfo.getFileStatus(); + *size += 1; + *buffer += 1; + + if (finishInfo.hasFsResponses()) { + FilestoreResponseTlv **fsResponsesArray = nullptr; + size_t fsResponsesArrayLen = 0; + finishInfo.getFilestoreResonses(&fsResponsesArray, &fsResponsesArrayLen, nullptr); + for (size_t idx = 0; idx < fsResponsesArrayLen; idx++) { + result = fsResponsesArray[idx]->serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + } + } + EntityIdTlv *entityId = nullptr; + if (finishInfo.getFaultLocation(&entityId) == returnvalue::OK) { + result = entityId->serialize(buffer, size, maxSize, streamEndianness); + } + return result; +} diff --git a/src/fsfw/cfdp/pdu/FinishedPduCreator.h b/src/fsfw/cfdp/pdu/FinishedPduCreator.h new file mode 100644 index 00000000..bef59ada --- /dev/null +++ b/src/fsfw/cfdp/pdu/FinishedPduCreator.h @@ -0,0 +1,24 @@ +#ifndef FSFW_CFDP_PDU_FINISHEDPDUSERIALIZER_H_ +#define FSFW_CFDP_PDU_FINISHEDPDUSERIALIZER_H_ + +#include "FinishedInfo.h" +#include "fsfw/cfdp/pdu/FileDataCreator.h" +#include "fsfw/cfdp/pdu/FileDirectiveCreator.h" + +class FinishPduCreator : public FileDirectiveCreator { + public: + FinishPduCreator(PduConfig& pduConf, FinishedInfo& finishInfo); + + void updateDirectiveFieldLen(); + + [[nodiscard]] size_t getSerializedSize() const override; + + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override; + using FileDirectiveCreator::serialize; + + private: + FinishedInfo& finishInfo; +}; + +#endif /* FSFW_CFDP_PDU_FINISHEDPDUSERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/FinishedPduDeserializer.h b/src/fsfw/cfdp/pdu/FinishedPduDeserializer.h deleted file mode 100644 index a34fc4cb..00000000 --- a/src/fsfw/cfdp/pdu/FinishedPduDeserializer.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUDESERIALIZER_H_ -#define FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUDESERIALIZER_H_ - -#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h" -#include "fsfw/cfdp/pdu/FinishedInfo.h" - -class FinishPduDeserializer : public FileDirectiveDeserializer { - public: - FinishPduDeserializer(const uint8_t* pduBuf, size_t maxSize, FinishedInfo& info); - - ReturnValue_t parseData() override; - - FinishedInfo& getInfo(); - - private: - FinishedInfo& finishedInfo; - - ReturnValue_t parseTlvs(size_t remLen, size_t currentIdx, const uint8_t* buf, - cfdp::ConditionCode conditionCode); -}; - -#endif /* FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUDESERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/FinishedPduDeserializer.cpp b/src/fsfw/cfdp/pdu/FinishedPduReader.cpp similarity index 57% rename from src/fsfw/cfdp/pdu/FinishedPduDeserializer.cpp rename to src/fsfw/cfdp/pdu/FinishedPduReader.cpp index feeca617..08dd3a82 100644 --- a/src/fsfw/cfdp/pdu/FinishedPduDeserializer.cpp +++ b/src/fsfw/cfdp/pdu/FinishedPduReader.cpp @@ -1,25 +1,24 @@ -#include "FinishedPduDeserializer.h" +#include "FinishedPduReader.h" -FinishPduDeserializer::FinishPduDeserializer(const uint8_t* pduBuf, size_t maxSize, - FinishedInfo& info) - : FileDirectiveDeserializer(pduBuf, maxSize), finishedInfo(info) {} +FinishPduReader::FinishPduReader(const uint8_t* pduBuf, size_t maxSize, FinishedInfo& info) + : FileDirectiveReader(pduBuf, maxSize), finishedInfo(info) {} -ReturnValue_t FinishPduDeserializer::parseData() { - ReturnValue_t result = FileDirectiveDeserializer::parseData(); - if (result != HasReturnvaluesIF::RETURN_OK) { +ReturnValue_t FinishPduReader::parseData() { + ReturnValue_t result = FileDirectiveReader::parseData(); + if (result != returnvalue::OK) { return result; } - size_t currentIdx = FileDirectiveDeserializer::getHeaderSize(); - const uint8_t* buf = rawPtr + currentIdx; - size_t remSize = FileDirectiveDeserializer::getWholePduSize() - currentIdx; + size_t currentIdx = FileDirectiveReader::getHeaderSize(); + const uint8_t* buf = pointers.rawPtr + currentIdx; + size_t remSize = FileDirectiveReader::getWholePduSize() - currentIdx; if (remSize < 1) { return SerializeIF::STREAM_TOO_SHORT; } uint8_t firstByte = *buf; - cfdp::ConditionCode condCode = static_cast((firstByte >> 4) & 0x0f); + auto condCode = static_cast((firstByte >> 4) & 0x0f); finishedInfo.setConditionCode(condCode); - finishedInfo.setDeliveryCode(static_cast(firstByte >> 2 & 0b1)); - finishedInfo.setFileStatus(static_cast(firstByte & 0b11)); + finishedInfo.setDeliveryCode(static_cast(firstByte >> 2 & 0b1)); + finishedInfo.setFileStatus(static_cast(firstByte & 0b11)); buf += 1; remSize -= 1; currentIdx += 1; @@ -29,17 +28,17 @@ ReturnValue_t FinishPduDeserializer::parseData() { return result; } -FinishedInfo& FinishPduDeserializer::getInfo() { return finishedInfo; } +FinishedInfo& FinishPduReader::getInfo() { return finishedInfo; } -ReturnValue_t FinishPduDeserializer::parseTlvs(size_t remLen, size_t currentIdx, const uint8_t* buf, - cfdp::ConditionCode conditionCode) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; +ReturnValue_t FinishPduReader::parseTlvs(size_t remLen, size_t currentIdx, const uint8_t* buf, + cfdp::ConditionCode conditionCode) { + ReturnValue_t result = returnvalue::OK; size_t fsResponsesIdx = 0; auto endianness = getEndianness(); FilestoreResponseTlv** fsResponseArray = nullptr; size_t fsResponseMaxArrayLen = 0; EntityIdTlv* faultLocation = nullptr; - cfdp::TlvTypes nextTlv = cfdp::TlvTypes::INVALID_TLV; + cfdp::TlvType nextTlv = cfdp::TlvType::INVALID_TLV; while (remLen > 0) { // Simply forward parse the TLV type. Every TLV type except the last one must be a Filestore // Response TLV, and even the last one can be a Filestore Response TLV if the fault @@ -47,8 +46,8 @@ ReturnValue_t FinishPduDeserializer::parseTlvs(size_t remLen, size_t currentIdx, if (currentIdx + 2 > maxSize) { return SerializeIF::STREAM_TOO_SHORT; } - nextTlv = static_cast(*buf); - if (nextTlv == cfdp::TlvTypes::FILESTORE_RESPONSE) { + nextTlv = static_cast(*buf); + if (nextTlv == cfdp::TlvType::FILESTORE_RESPONSE) { if (fsResponseArray == nullptr) { if (not finishedInfo.canHoldFsResponses()) { return cfdp::FINISHED_CANT_PARSE_FS_RESPONSES; @@ -60,11 +59,11 @@ ReturnValue_t FinishPduDeserializer::parseTlvs(size_t remLen, size_t currentIdx, return cfdp::FINISHED_CANT_PARSE_FS_RESPONSES; } result = fsResponseArray[fsResponsesIdx]->deSerialize(&buf, &remLen, endianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } fsResponsesIdx += 1; - } else if (nextTlv == cfdp::TlvTypes::ENTITY_ID) { + } else if (nextTlv == cfdp::TlvType::ENTITY_ID) { // This needs to be the last TLV and it should not be here if the condition code // is "No Error" or "Unsupported Checksum Type" if (conditionCode == cfdp::ConditionCode::NO_ERROR or @@ -72,11 +71,11 @@ ReturnValue_t FinishPduDeserializer::parseTlvs(size_t remLen, size_t currentIdx, return cfdp::INVALID_TLV_TYPE; } result = finishedInfo.getFaultLocation(&faultLocation); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = faultLocation->deSerialize(&buf, &remLen, endianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } } else { diff --git a/src/fsfw/cfdp/pdu/FinishedPduReader.h b/src/fsfw/cfdp/pdu/FinishedPduReader.h new file mode 100644 index 00000000..791a2ef4 --- /dev/null +++ b/src/fsfw/cfdp/pdu/FinishedPduReader.h @@ -0,0 +1,22 @@ +#ifndef FSFW_CFDP_PDU_FINISHEDPDUDESERIALIZER_H_ +#define FSFW_CFDP_PDU_FINISHEDPDUDESERIALIZER_H_ + +#include "fsfw/cfdp/pdu/FileDirectiveReader.h" +#include "fsfw/cfdp/pdu/FinishedInfo.h" + +class FinishPduReader : public FileDirectiveReader { + public: + FinishPduReader(const uint8_t* pduBuf, size_t maxSize, FinishedInfo& info); + + ReturnValue_t parseData() override; + + FinishedInfo& getInfo(); + + private: + FinishedInfo& finishedInfo; + + ReturnValue_t parseTlvs(size_t remLen, size_t currentIdx, const uint8_t* buf, + cfdp::ConditionCode conditionCode); +}; + +#endif /* FSFW_CFDP_PDU_FINISHEDPDUDESERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/FinishedPduSerializer.cpp b/src/fsfw/cfdp/pdu/FinishedPduSerializer.cpp deleted file mode 100644 index 115a2c9c..00000000 --- a/src/fsfw/cfdp/pdu/FinishedPduSerializer.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "FinishedPduSerializer.h" - -FinishPduSerializer::FinishPduSerializer(PduConfig &conf, FinishedInfo &finishInfo) - : FileDirectiveSerializer(conf, cfdp::FileDirectives::FINISH, 0), finishInfo(finishInfo) { - updateDirectiveFieldLen(); -} - -size_t FinishPduSerializer::getSerializedSize() const { - return FinishPduSerializer::getWholePduSize(); -} - -void FinishPduSerializer::updateDirectiveFieldLen() { - setDirectiveDataFieldLen(finishInfo.getSerializedSize()); -} - -ReturnValue_t FinishPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const { - ReturnValue_t result = - FileDirectiveSerializer::serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - if (*size + 1 >= maxSize) { - return SerializeIF::BUFFER_TOO_SHORT; - } - **buffer = finishInfo.getConditionCode() << 4 | finishInfo.getDeliveryCode() << 2 | - finishInfo.getFileStatus(); - *size += 1; - *buffer += 1; - - if (finishInfo.hasFsResponses()) { - FilestoreResponseTlv **fsResponsesArray = nullptr; - size_t fsResponsesArrayLen = 0; - finishInfo.getFilestoreResonses(&fsResponsesArray, &fsResponsesArrayLen, nullptr); - for (size_t idx = 0; idx < fsResponsesArrayLen; idx++) { - result = fsResponsesArray[idx]->serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - } - } - EntityIdTlv *entityId = nullptr; - if (finishInfo.getFaultLocation(&entityId) == HasReturnvaluesIF::RETURN_OK) { - result = entityId->serialize(buffer, size, maxSize, streamEndianness); - } - return result; -} diff --git a/src/fsfw/cfdp/pdu/FinishedPduSerializer.h b/src/fsfw/cfdp/pdu/FinishedPduSerializer.h deleted file mode 100644 index d66b25f2..00000000 --- a/src/fsfw/cfdp/pdu/FinishedPduSerializer.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUSERIALIZER_H_ -#define FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUSERIALIZER_H_ - -#include "FinishedInfo.h" -#include "fsfw/cfdp/pdu/FileDataSerializer.h" -#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h" - -class FinishPduSerializer : public FileDirectiveSerializer { - public: - FinishPduSerializer(PduConfig& pduConf, FinishedInfo& finishInfo); - - void updateDirectiveFieldLen(); - - size_t getSerializedSize() const override; - - ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const override; - - private: - FinishedInfo& finishInfo; -}; - -#endif /* FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUSERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/HeaderCreator.cpp b/src/fsfw/cfdp/pdu/HeaderCreator.cpp new file mode 100644 index 00000000..2db3953c --- /dev/null +++ b/src/fsfw/cfdp/pdu/HeaderCreator.cpp @@ -0,0 +1,111 @@ +#include "HeaderCreator.h" + +HeaderCreator::HeaderCreator(PduConfig &pduConf, cfdp::PduType pduType, size_t initPduDataFieldLen, + cfdp::SegmentMetadataFlag segmentMetadataFlag, + cfdp::SegmentationControl segCtrl) + : pduType(pduType), + segmentMetadataFlag(segmentMetadataFlag), + segmentationCtrl(segCtrl), + pduDataFieldLen(initPduDataFieldLen), + pduConf(pduConf) {} + +ReturnValue_t HeaderCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const { + if (buffer == nullptr or size == nullptr) { + return returnvalue::FAILED; + } + if (maxSize < this->getSerializedSize()) { + return BUFFER_TOO_SHORT; + } + **buffer = cfdp::VERSION_BITS | this->pduType << 4 | pduConf.direction << 3 | pduConf.mode << 2 | + pduConf.crcFlag << 1 | pduConf.largeFile; + *buffer += 1; + **buffer = (pduDataFieldLen & 0xff00) >> 8; + *buffer += 1; + **buffer = pduDataFieldLen & 0x00ff; + *buffer += 1; + **buffer = segmentationCtrl << 7 | ((pduConf.sourceId.getWidth() - 1) << 4) | + segmentMetadataFlag << 3 | (pduConf.seqNum.getWidth() - 1); + *buffer += 1; + *size += 4; + ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + result = pduConf.seqNum.serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + result = pduConf.destId.serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + + return returnvalue::OK; +} + +size_t HeaderCreator::getSerializedSize() const { + return pduConf.seqNum.getWidth() + pduConf.sourceId.getWidth() * 2 + 4; +} + +ReturnValue_t HeaderCreator::deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) { + // We could implement this, but I prefer dedicated classes + return returnvalue::FAILED; +} + +size_t HeaderCreator::getWholePduSize() const { + // Return size of header plus the PDU data field length + return pduDataFieldLen + HeaderCreator::getSerializedSize(); +} + +size_t HeaderCreator::getPduDataFieldLen() const { return pduDataFieldLen; } + +void HeaderCreator::setPduDataFieldLen(size_t pduDataFieldLen_) { + pduDataFieldLen = pduDataFieldLen_; +} + +void HeaderCreator::setPduType(cfdp::PduType pduType_) { pduType = pduType_; } + +void HeaderCreator::setSegmentMetadataFlag(cfdp::SegmentMetadataFlag segmentMetadataFlag_) { + segmentMetadataFlag = segmentMetadataFlag_; +} + +cfdp::PduType HeaderCreator::getPduType() const { return pduType; } + +cfdp::Direction HeaderCreator::getDirection() const { return pduConf.direction; } + +cfdp::TransmissionMode HeaderCreator::getTransmissionMode() const { return pduConf.mode; } + +bool HeaderCreator::getCrcFlag() const { return pduConf.crcFlag; } + +bool HeaderCreator::getLargeFileFlag() const { return pduConf.largeFile; } + +cfdp::SegmentationControl HeaderCreator::getSegmentationControl() const { return segmentationCtrl; } + +cfdp::WidthInBytes HeaderCreator::getLenEntityIds() const { return pduConf.sourceId.getWidth(); } + +cfdp::WidthInBytes HeaderCreator::getLenSeqNum() const { return pduConf.seqNum.getWidth(); } + +cfdp::SegmentMetadataFlag HeaderCreator::getSegmentMetadataFlag() const { + return segmentMetadataFlag; +} + +void HeaderCreator::getSourceId(cfdp::EntityId &sourceId) const { sourceId = pduConf.sourceId; } + +void HeaderCreator::getDestId(cfdp::EntityId &destId) const { destId = pduConf.destId; } + +void HeaderCreator::setSegmentationControl(cfdp::SegmentationControl segmentationControl) { + this->segmentationCtrl = segmentationControl; +} + +void HeaderCreator::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) const { + seqNum = pduConf.seqNum; +} + +bool HeaderCreator::hasSegmentMetadataFlag() const { + if (this->segmentMetadataFlag == cfdp::SegmentMetadataFlag::PRESENT) { + return true; + } + return false; +} diff --git a/src/fsfw/cfdp/pdu/HeaderSerializer.h b/src/fsfw/cfdp/pdu/HeaderCreator.h similarity index 63% rename from src/fsfw/cfdp/pdu/HeaderSerializer.h rename to src/fsfw/cfdp/pdu/HeaderCreator.h index 8f2fc3fd..173a6239 100644 --- a/src/fsfw/cfdp/pdu/HeaderSerializer.h +++ b/src/fsfw/cfdp/pdu/HeaderCreator.h @@ -1,14 +1,14 @@ #ifndef FSFW_SRC_FSFW_CFDP_PDU_HEADERSERIALIZER_H_ #define FSFW_SRC_FSFW_CFDP_PDU_HEADERSERIALIZER_H_ -#include "../definitions.h" #include "PduConfig.h" #include "PduHeaderIF.h" +#include "fsfw/cfdp/definitions.h" #include "fsfw/serialize/SerializeIF.h" -class HeaderSerializer : public SerializeIF, public PduHeaderIF { +class HeaderCreator : public SerializeIF, public PduHeaderIF { public: - HeaderSerializer( + HeaderCreator( PduConfig& pduConf, cfdp::PduType pduType, size_t initPduDataFieldLen, cfdp::SegmentMetadataFlag segmentMetadataFlag = cfdp::SegmentMetadataFlag::NOT_PRESENT, cfdp::SegmentationControl segCtrl = @@ -23,7 +23,7 @@ class HeaderSerializer : public SerializeIF, public PduHeaderIF { * data field length was not properly. * @return */ - size_t getSerializedSize() const override; + [[nodiscard]] size_t getSerializedSize() const override; ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) override; @@ -32,19 +32,19 @@ class HeaderSerializer : public SerializeIF, public PduHeaderIF { void setPduType(cfdp::PduType pduType); void setSegmentMetadataFlag(cfdp::SegmentMetadataFlag); - size_t getPduDataFieldLen() const override; - size_t getWholePduSize() const override; + [[nodiscard]] size_t getPduDataFieldLen() const override; + [[nodiscard]] size_t getWholePduSize() const override; - cfdp::PduType getPduType() const override; - cfdp::Direction getDirection() const override; - cfdp::TransmissionModes getTransmissionMode() const override; - bool getCrcFlag() const override; - bool getLargeFileFlag() const override; - cfdp::SegmentationControl getSegmentationControl() const override; - cfdp::WidthInBytes getLenEntityIds() const override; - cfdp::WidthInBytes getLenSeqNum() const override; - cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const override; - bool hasSegmentMetadataFlag() const; + [[nodiscard]] cfdp::PduType getPduType() const override; + [[nodiscard]] cfdp::Direction getDirection() const override; + [[nodiscard]] cfdp::TransmissionMode getTransmissionMode() const override; + [[nodiscard]] bool getCrcFlag() const override; + [[nodiscard]] bool getLargeFileFlag() const override; + [[nodiscard]] cfdp::SegmentationControl getSegmentationControl() const override; + [[nodiscard]] cfdp::WidthInBytes getLenEntityIds() const override; + [[nodiscard]] cfdp::WidthInBytes getLenSeqNum() const override; + [[nodiscard]] cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const override; + [[nodiscard]] bool hasSegmentMetadataFlag() const override; void setSegmentationControl(cfdp::SegmentationControl); void getSourceId(cfdp::EntityId& sourceId) const override; diff --git a/src/fsfw/cfdp/pdu/HeaderDeserializer.cpp b/src/fsfw/cfdp/pdu/HeaderDeserializer.cpp deleted file mode 100644 index 70f397f8..00000000 --- a/src/fsfw/cfdp/pdu/HeaderDeserializer.cpp +++ /dev/null @@ -1,128 +0,0 @@ -#include "HeaderDeserializer.h" - -#include - -#include - -HeaderDeserializer::HeaderDeserializer(const uint8_t *pduBuf, size_t maxSize) - : rawPtr(pduBuf), maxSize(maxSize) {} - -ReturnValue_t HeaderDeserializer::parseData() { - if (maxSize < 7) { - return SerializeIF::STREAM_TOO_SHORT; - } - return setData(const_cast(rawPtr), maxSize); -} - -ReturnValue_t HeaderDeserializer::setData(uint8_t *dataPtr, size_t maxSize, void *args) { - if (dataPtr == nullptr) { - // Allowed for now - this->fixedHeader = nullptr; - return HasReturnvaluesIF::RETURN_OK; - } - this->fixedHeader = reinterpret_cast(const_cast(dataPtr)); - sourceIdRaw = static_cast(&fixedHeader->variableFieldsStart); - cfdp::WidthInBytes widthEntityIds = getLenEntityIds(); - cfdp::WidthInBytes widthSeqNum = getLenSeqNum(); - seqNumRaw = static_cast(sourceIdRaw) + static_cast(widthEntityIds); - destIdRaw = static_cast(seqNumRaw) + static_cast(widthSeqNum); - this->maxSize = maxSize; - return HasReturnvaluesIF::RETURN_OK; -} - -size_t HeaderDeserializer::getHeaderSize() const { - if (fixedHeader != nullptr) { - return getLenEntityIds() * 2 + getLenSeqNum() + 4; - } - return 0; -} - -size_t HeaderDeserializer::getPduDataFieldLen() const { - uint16_t pduFiedlLen = (fixedHeader->pduDataFieldLenH << 8) | fixedHeader->pduDataFieldLenL; - return pduFiedlLen; -} - -size_t HeaderDeserializer::getWholePduSize() const { - return getPduDataFieldLen() + getHeaderSize(); -} - -cfdp::PduType HeaderDeserializer::getPduType() const { - return static_cast((fixedHeader->firstByte >> 4) & 0x01); -} - -cfdp::Direction HeaderDeserializer::getDirection() const { - return static_cast((fixedHeader->firstByte >> 3) & 0x01); -} - -cfdp::TransmissionModes HeaderDeserializer::getTransmissionMode() const { - return static_cast((fixedHeader->firstByte >> 2) & 0x01); -} - -bool HeaderDeserializer::getCrcFlag() const { return (fixedHeader->firstByte >> 1) & 0x01; } - -bool HeaderDeserializer::getLargeFileFlag() const { return fixedHeader->firstByte & 0x01; } - -cfdp::SegmentationControl HeaderDeserializer::getSegmentationControl() const { - return static_cast((fixedHeader->fourthByte >> 7) & 0x01); -} - -cfdp::WidthInBytes HeaderDeserializer::getLenEntityIds() const { - return static_cast((fixedHeader->fourthByte >> 4) & 0x07); -} - -cfdp::WidthInBytes HeaderDeserializer::getLenSeqNum() const { - return static_cast(fixedHeader->fourthByte & 0x07); -} - -cfdp::SegmentMetadataFlag HeaderDeserializer::getSegmentMetadataFlag() const { - return static_cast((fixedHeader->fourthByte >> 3) & 0x01); -} - -void HeaderDeserializer::getSourceId(cfdp::EntityId &sourceId) const { - assignVarLenField(dynamic_cast(&sourceId), getLenEntityIds(), - this->sourceIdRaw); -} - -void HeaderDeserializer::getDestId(cfdp::EntityId &destId) const { - assignVarLenField(dynamic_cast(&destId), getLenEntityIds(), this->destIdRaw); -} - -void HeaderDeserializer::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) const { - assignVarLenField(dynamic_cast(&seqNum), getLenSeqNum(), this->seqNumRaw); -} - -void HeaderDeserializer::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInBytes width, - void *sourcePtr) const { - switch (width) { - case (cfdp::WidthInBytes::ONE_BYTE): { - uint8_t *fieldTyped = static_cast(sourcePtr); - field->setValue(width, *fieldTyped); - break; - } - case (cfdp::WidthInBytes::TWO_BYTES): { - uint16_t fieldTyped = 0; - size_t deserSize = 0; - SerializeAdapter::deSerialize(&fieldTyped, static_cast(sourcePtr), &deserSize, - SerializeIF::Endianness::NETWORK); - field->setValue(width, fieldTyped); - break; - } - case (cfdp::WidthInBytes::FOUR_BYTES): { - uint32_t fieldTyped = 0; - size_t deserSize = 0; - SerializeAdapter::deSerialize(&fieldTyped, static_cast(sourcePtr), &deserSize, - SerializeIF::Endianness::NETWORK); - field->setValue(width, fieldTyped); - break; - } - } -} - -size_t HeaderDeserializer::getMaxSize() const { return maxSize; } - -bool HeaderDeserializer::hasSegmentMetadataFlag() const { - if (this->getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT) { - return true; - } - return false; -} diff --git a/src/fsfw/cfdp/pdu/HeaderDeserializer.h b/src/fsfw/cfdp/pdu/HeaderDeserializer.h deleted file mode 100644 index ed033697..00000000 --- a/src/fsfw/cfdp/pdu/HeaderDeserializer.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef FSFW_SRC_FSFW_CFDP_PDU_HEADERDESERIALIZER_H_ -#define FSFW_SRC_FSFW_CFDP_PDU_HEADERDESERIALIZER_H_ - -#include -#include - -#include "PduConfig.h" -#include "PduHeaderIF.h" -#include "fsfw/serialize/SerializeIF.h" -#include "fsfw/tmtcpacket/RedirectableDataPointerIF.h" - -struct PduHeaderFixedStruct { - uint8_t firstByte; - uint8_t pduDataFieldLenH; - uint8_t pduDataFieldLenL; - uint8_t fourthByte; - uint8_t variableFieldsStart; -}; - -/** - * @brief This class is used to deserialize a PDU header from raw memory. - * @details - * This is a zero-copy implementation and #parseData needs to be called to ensure the data is - * valid. - */ -class HeaderDeserializer : public RedirectableDataPointerIF, public PduHeaderIF { - public: - /** - * Initialize a PDU header from raw data. This is a zero-copy implementation and #parseData - * needs to be called to ensure the data is valid - * @param pduBuf - * @param maxSize - */ - HeaderDeserializer(const uint8_t* pduBuf, size_t maxSize); - - /** - * This needs to be called before accessing the PDU fields to avoid segmentation faults. - * @return - * - RETURN_OK on parse success - * - RETURN_FAILED Invalid raw data - * - SerializeIF::BUFFER_TOO_SHORT if buffer is shorter than expected - */ - virtual ReturnValue_t parseData(); - size_t getHeaderSize() const; - - size_t getPduDataFieldLen() const override; - size_t getWholePduSize() const override; - - cfdp::PduType getPduType() const override; - cfdp::Direction getDirection() const override; - cfdp::TransmissionModes getTransmissionMode() const override; - bool getCrcFlag() const override; - bool getLargeFileFlag() const override; - cfdp::SegmentationControl getSegmentationControl() const override; - cfdp::WidthInBytes getLenEntityIds() const override; - cfdp::WidthInBytes getLenSeqNum() const override; - cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const override; - bool hasSegmentMetadataFlag() const override; - - void getSourceId(cfdp::EntityId& sourceId) const override; - void getDestId(cfdp::EntityId& destId) const override; - void getTransactionSeqNum(cfdp::TransactionSeqNum& seqNum) const override; - - ReturnValue_t deserResult = HasReturnvaluesIF::RETURN_OK; - - /** - * Can also be used to reset the pointer to a nullptr, but the getter functions will not - * perform nullptr checks! - * @param dataPtr - * @param maxSize - * @param args - * @return - */ - ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize, void* args = nullptr) override; - - size_t getMaxSize() const; - - protected: - PduHeaderFixedStruct* fixedHeader = nullptr; - const uint8_t* rawPtr = nullptr; - size_t maxSize = 0; - - private: - void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width, void* sourcePtr) const; - void* sourceIdRaw = nullptr; - void* seqNumRaw = nullptr; - void* destIdRaw = nullptr; -}; - -#endif /* FSFW_SRC_FSFW_CFDP_PDU_HEADERDESERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/HeaderReader.cpp b/src/fsfw/cfdp/pdu/HeaderReader.cpp new file mode 100644 index 00000000..de3d2906 --- /dev/null +++ b/src/fsfw/cfdp/pdu/HeaderReader.cpp @@ -0,0 +1,160 @@ +#include + +#include + +#include "PduHeaderReader.h" + +PduHeaderReader::PduHeaderReader(const uint8_t *pduBuf, size_t maxSize) { + setReadOnlyData(pduBuf, maxSize); +} + +ReturnValue_t PduHeaderReader::parseData() { + if (pointers.rawPtr == nullptr) { + return returnvalue::FAILED; + } + if (maxSize < 7) { + return SerializeIF::STREAM_TOO_SHORT; + } + pointers.fixedHeader = + reinterpret_cast(const_cast(pointers.rawPtr)); + sourceIdRaw = static_cast(&pointers.fixedHeader->variableFieldsStart); + cfdp::WidthInBytes widthEntityIds = getLenEntityIds(); + cfdp::WidthInBytes widthSeqNum = getLenSeqNum(); + seqNumRaw = static_cast(sourceIdRaw) + static_cast(widthEntityIds); + destIdRaw = static_cast(seqNumRaw) + static_cast(widthSeqNum); + if (getWholePduSize() > PduHeaderReader::getHeaderSize()) { + pointers.dataFieldStart = reinterpret_cast(destIdRaw) + widthEntityIds; + } else { + pointers.dataFieldStart = nullptr; + } + return returnvalue::OK; +} + +ReturnValue_t PduHeaderReader::setData(uint8_t *dataPtr, size_t maxSize_, void *args) { + if (dataPtr == nullptr) { + return returnvalue::FAILED; + } + if (maxSize_ < 7) { + return SerializeIF::STREAM_TOO_SHORT; + } + pointers.rawPtr = dataPtr; + maxSize = maxSize_; + return returnvalue::OK; +} + +size_t PduHeaderReader::getHeaderSize() const { + if (pointers.fixedHeader != nullptr) { + return getLenEntityIds() * 2 + getLenSeqNum() + 4; + } + return 0; +} + +size_t PduHeaderReader::getPduDataFieldLen() const { + return (pointers.fixedHeader->pduDataFieldLenH << 8) | pointers.fixedHeader->pduDataFieldLenL; +} + +size_t PduHeaderReader::getWholePduSize() const { + return getPduDataFieldLen() + PduHeaderReader::getHeaderSize(); +} + +cfdp::PduType PduHeaderReader::getPduType() const { + return static_cast((pointers.fixedHeader->firstByte >> 4) & 0x01); +} + +cfdp::Direction PduHeaderReader::getDirection() const { + return static_cast((pointers.fixedHeader->firstByte >> 3) & 0x01); +} + +cfdp::TransmissionMode PduHeaderReader::getTransmissionMode() const { + return static_cast((pointers.fixedHeader->firstByte >> 2) & 0x01); +} + +bool PduHeaderReader::getCrcFlag() const { return (pointers.fixedHeader->firstByte >> 1) & 0x01; } + +bool PduHeaderReader::getLargeFileFlag() const { return pointers.fixedHeader->firstByte & 0x01; } + +cfdp::SegmentationControl PduHeaderReader::getSegmentationControl() const { + return static_cast((pointers.fixedHeader->fourthByte >> 7) & 0x01); +} + +cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() const { + return static_cast(((pointers.fixedHeader->fourthByte >> 4) & 0b111) + 1); +} + +cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const { + return static_cast((pointers.fixedHeader->fourthByte & 0b111) + 1); +} + +cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const { + return static_cast((pointers.fixedHeader->fourthByte >> 3) & 0x01); +} + +void PduHeaderReader::getSourceId(cfdp::EntityId &sourceId) const { + assignVarLenField(dynamic_cast(&sourceId), getLenEntityIds(), + this->sourceIdRaw); +} + +void PduHeaderReader::getDestId(cfdp::EntityId &destId) const { + assignVarLenField(dynamic_cast(&destId), getLenEntityIds(), this->destIdRaw); +} + +void PduHeaderReader::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) const { + assignVarLenField(dynamic_cast(&seqNum), getLenSeqNum(), this->seqNumRaw); +} + +void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInBytes width, + void *sourcePtr) const { + switch (width) { + case (cfdp::WidthInBytes::ONE_BYTE): { + auto *fieldTyped = static_cast(sourcePtr); + field->setValue(width, *fieldTyped); + break; + } + case (cfdp::WidthInBytes::TWO_BYTES): { + uint16_t fieldTyped = 0; + size_t deserSize = 0; + SerializeAdapter::deSerialize(&fieldTyped, static_cast(sourcePtr), &deserSize, + SerializeIF::Endianness::NETWORK); + field->setValue(width, fieldTyped); + break; + } + case (cfdp::WidthInBytes::FOUR_BYTES): { + uint32_t fieldTyped = 0; + size_t deserSize = 0; + SerializeAdapter::deSerialize(&fieldTyped, static_cast(sourcePtr), &deserSize, + SerializeIF::Endianness::NETWORK); + field->setValue(width, fieldTyped); + break; + } + } +} + +size_t PduHeaderReader::getMaxSize() const { return maxSize; } + +bool PduHeaderReader::hasSegmentMetadataFlag() const { + if (this->getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT) { + return true; + } + return false; +} + +ReturnValue_t PduHeaderReader::setReadOnlyData(const uint8_t *dataPtr, size_t maxSize_) { + return setData(const_cast(dataPtr), maxSize_, nullptr); +} +bool PduHeaderReader::isNull() const { + return pointers.rawPtr == nullptr or pointers.fixedHeader == nullptr; +} + +PduHeaderReader::operator bool() const { return not isNull(); } + +void PduHeaderReader::fillConfig(PduConfig &cfg) const { + cfg.largeFile = getLargeFileFlag(); + cfg.crcFlag = getCrcFlag(); + cfg.mode = getTransmissionMode(); + cfg.direction = getDirection(); + getTransactionSeqNum(cfg.seqNum); + getSourceId(cfg.sourceId); + getDestId(cfg.destId); +} + +const uint8_t *PduHeaderReader::getPduDataField() const { return pointers.dataFieldStart; } diff --git a/src/fsfw/cfdp/pdu/HeaderSerializer.cpp b/src/fsfw/cfdp/pdu/HeaderSerializer.cpp deleted file mode 100644 index 041fb714..00000000 --- a/src/fsfw/cfdp/pdu/HeaderSerializer.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "HeaderSerializer.h" - -#include "HeaderDeserializer.h" - -HeaderSerializer::HeaderSerializer(PduConfig &pduConf, cfdp::PduType pduType, - size_t initPduDataFieldLen, - cfdp::SegmentMetadataFlag segmentMetadataFlag, - cfdp::SegmentationControl segCtrl) - : pduType(pduType), - segmentMetadataFlag(segmentMetadataFlag), - segmentationCtrl(segCtrl), - pduDataFieldLen(initPduDataFieldLen), - pduConf(pduConf) {} - -ReturnValue_t HeaderSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const { - if (buffer == nullptr or size == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - if (maxSize < this->getSerializedSize()) { - return BUFFER_TOO_SHORT; - } - **buffer = cfdp::VERSION_BITS | this->pduType << 4 | pduConf.direction << 3 | pduConf.mode << 2 | - pduConf.crcFlag << 1 | pduConf.largeFile; - *buffer += 1; - **buffer = (pduDataFieldLen & 0xff00) >> 8; - *buffer += 1; - **buffer = pduDataFieldLen & 0x00ff; - *buffer += 1; - **buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 | segmentMetadataFlag << 3 | - pduConf.seqNum.getWidth(); - *buffer += 1; - *size += 4; - ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - result = pduConf.seqNum.serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - result = pduConf.destId.serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - return HasReturnvaluesIF::RETURN_OK; -} - -size_t HeaderSerializer::getSerializedSize() const { - size_t shit = pduConf.seqNum.getWidth() + pduConf.sourceId.getWidth() * 2 + 4; - return shit; -} - -ReturnValue_t HeaderSerializer::deSerialize(const uint8_t **buffer, size_t *size, - Endianness streamEndianness) { - // We could implement this, but I prefer dedicated classes - return HasReturnvaluesIF::RETURN_FAILED; -} - -size_t HeaderSerializer::getWholePduSize() const { - // Return size of header plus the PDU data field length - return pduDataFieldLen + HeaderSerializer::getSerializedSize(); -} - -size_t HeaderSerializer::getPduDataFieldLen() const { return pduDataFieldLen; } - -void HeaderSerializer::setPduDataFieldLen(size_t pduDataFieldLen) { - this->pduDataFieldLen = pduDataFieldLen; -} - -void HeaderSerializer::setPduType(cfdp::PduType pduType) { this->pduType = pduType; } - -void HeaderSerializer::setSegmentMetadataFlag(cfdp::SegmentMetadataFlag segmentMetadataFlag) { - this->segmentMetadataFlag = segmentMetadataFlag; -} - -cfdp::PduType HeaderSerializer::getPduType() const { return pduType; } - -cfdp::Direction HeaderSerializer::getDirection() const { return pduConf.direction; } - -cfdp::TransmissionModes HeaderSerializer::getTransmissionMode() const { return pduConf.mode; } - -bool HeaderSerializer::getCrcFlag() const { return pduConf.crcFlag; } - -bool HeaderSerializer::getLargeFileFlag() const { return pduConf.largeFile; } - -cfdp::SegmentationControl HeaderSerializer::getSegmentationControl() const { - return segmentationCtrl; -} - -cfdp::WidthInBytes HeaderSerializer::getLenEntityIds() const { return pduConf.sourceId.getWidth(); } - -cfdp::WidthInBytes HeaderSerializer::getLenSeqNum() const { return pduConf.seqNum.getWidth(); } - -cfdp::SegmentMetadataFlag HeaderSerializer::getSegmentMetadataFlag() const { - return segmentMetadataFlag; -} - -void HeaderSerializer::getSourceId(cfdp::EntityId &sourceId) const { sourceId = pduConf.sourceId; } - -void HeaderSerializer::getDestId(cfdp::EntityId &destId) const { destId = pduConf.destId; } - -void HeaderSerializer::setSegmentationControl(cfdp::SegmentationControl segmentationControl) { - this->segmentationCtrl = segmentationControl; -} - -void HeaderSerializer::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) const { - seqNum = pduConf.seqNum; -} - -bool HeaderSerializer::hasSegmentMetadataFlag() const { - if (this->segmentMetadataFlag == cfdp::SegmentMetadataFlag::PRESENT) { - return true; - } - return false; -} diff --git a/src/fsfw/cfdp/pdu/KeepAlivePduCreator.cpp b/src/fsfw/cfdp/pdu/KeepAlivePduCreator.cpp new file mode 100644 index 00000000..40747751 --- /dev/null +++ b/src/fsfw/cfdp/pdu/KeepAlivePduCreator.cpp @@ -0,0 +1,25 @@ +#include "KeepAlivePduCreator.h" + +KeepAlivePduCreator::KeepAlivePduCreator(PduConfig &conf, cfdp::FileSize &progress) + : FileDirectiveCreator(conf, cfdp::FileDirective::KEEP_ALIVE, 4), progress(progress) { + updateDirectiveFieldLen(); +} + +size_t KeepAlivePduCreator::getSerializedSize() const { + return FileDirectiveCreator::getWholePduSize(); +} + +void KeepAlivePduCreator::updateDirectiveFieldLen() { + if (this->getLargeFileFlag()) { + this->setDirectiveDataFieldLen(8); + } +} + +ReturnValue_t KeepAlivePduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const { + ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + return progress.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness); +} diff --git a/src/fsfw/cfdp/pdu/KeepAlivePduCreator.h b/src/fsfw/cfdp/pdu/KeepAlivePduCreator.h new file mode 100644 index 00000000..aa4bf0fd --- /dev/null +++ b/src/fsfw/cfdp/pdu/KeepAlivePduCreator.h @@ -0,0 +1,22 @@ +#ifndef FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ +#define FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ + +#include "fsfw/cfdp/FileSize.h" +#include "fsfw/cfdp/pdu/FileDirectiveCreator.h" + +class KeepAlivePduCreator : public FileDirectiveCreator { + public: + KeepAlivePduCreator(PduConfig& conf, cfdp::FileSize& progress); + + void updateDirectiveFieldLen(); + + [[nodiscard]] size_t getSerializedSize() const override; + + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override; + + private: + cfdp::FileSize& progress; +}; + +#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/KeepAlivePduDeserializer.cpp b/src/fsfw/cfdp/pdu/KeepAlivePduDeserializer.cpp deleted file mode 100644 index 15f80549..00000000 --- a/src/fsfw/cfdp/pdu/KeepAlivePduDeserializer.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "KeepAlivePduDeserializer.h" - -KeepAlivePduDeserializer::KeepAlivePduDeserializer(const uint8_t* pduBuf, size_t maxSize, - cfdp::FileSize& progress) - : FileDirectiveDeserializer(pduBuf, maxSize), progress(progress) {} - -ReturnValue_t KeepAlivePduDeserializer::parseData() { - ReturnValue_t result = FileDirectiveDeserializer::parseData(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - size_t currentIdx = FileDirectiveDeserializer::getHeaderSize(); - size_t remLen = FileDirectiveDeserializer::getWholePduSize() - currentIdx; - const uint8_t* buffer = rawPtr + currentIdx; - return progress.deSerialize(&buffer, &remLen, getEndianness()); -} - -cfdp::FileSize& KeepAlivePduDeserializer::getProgress() { return progress; } diff --git a/src/fsfw/cfdp/pdu/KeepAlivePduDeserializer.h b/src/fsfw/cfdp/pdu/KeepAlivePduDeserializer.h deleted file mode 100644 index e8b83ad6..00000000 --- a/src/fsfw/cfdp/pdu/KeepAlivePduDeserializer.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef FSFW_SRC_FSFW_CFDP_PDU_KEEPALIVEPDUDESERIALIZER_H_ -#define FSFW_SRC_FSFW_CFDP_PDU_KEEPALIVEPDUDESERIALIZER_H_ - -#include "fsfw/cfdp/FileSize.h" -#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h" - -class KeepAlivePduDeserializer : public FileDirectiveDeserializer { - public: - KeepAlivePduDeserializer(const uint8_t* pduBuf, size_t maxSize, cfdp::FileSize& progress); - - ReturnValue_t parseData() override; - - cfdp::FileSize& getProgress(); - - private: - cfdp::FileSize& progress; -}; - -#endif /* FSFW_SRC_FSFW_CFDP_PDU_KEEPALIVEPDUDESERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/KeepAlivePduReader.cpp b/src/fsfw/cfdp/pdu/KeepAlivePduReader.cpp new file mode 100644 index 00000000..d3362cf9 --- /dev/null +++ b/src/fsfw/cfdp/pdu/KeepAlivePduReader.cpp @@ -0,0 +1,18 @@ +#include "KeepAlivePduReader.h" + +KeepAlivePduReader::KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, + cfdp::FileSize& progress) + : FileDirectiveReader(pduBuf, maxSize), progress(progress) {} + +ReturnValue_t KeepAlivePduReader::parseData() { + ReturnValue_t result = FileDirectiveReader::parseData(); + if (result != returnvalue::OK) { + return result; + } + size_t currentIdx = FileDirectiveReader::getHeaderSize(); + size_t remLen = FileDirectiveReader::getWholePduSize() - currentIdx; + const uint8_t* buffer = pointers.rawPtr + currentIdx; + return progress.deSerialize(&buffer, &remLen, getEndianness()); +} + +cfdp::FileSize& KeepAlivePduReader::getProgress() { return progress; } diff --git a/src/fsfw/cfdp/pdu/KeepAlivePduReader.h b/src/fsfw/cfdp/pdu/KeepAlivePduReader.h new file mode 100644 index 00000000..38e061f1 --- /dev/null +++ b/src/fsfw/cfdp/pdu/KeepAlivePduReader.h @@ -0,0 +1,19 @@ +#ifndef FSFW_CFDP_PDU_KEEPALIVEREADER_H_ +#define FSFW_CFDP_PDU_KEEPALIVEREADER_H_ + +#include "fsfw/cfdp/FileSize.h" +#include "fsfw/cfdp/pdu/FileDirectiveReader.h" + +class KeepAlivePduReader : public FileDirectiveReader { + public: + KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, cfdp::FileSize& progress); + + ReturnValue_t parseData() override; + + cfdp::FileSize& getProgress(); + + private: + cfdp::FileSize& progress; +}; + +#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUREADER_H_ */ diff --git a/src/fsfw/cfdp/pdu/KeepAlivePduSerializer.cpp b/src/fsfw/cfdp/pdu/KeepAlivePduSerializer.cpp deleted file mode 100644 index e635ce06..00000000 --- a/src/fsfw/cfdp/pdu/KeepAlivePduSerializer.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "KeepAlivePduSerializer.h" - -KeepAlivePduSerializer::KeepAlivePduSerializer(PduConfig &conf, cfdp::FileSize &progress) - : FileDirectiveSerializer(conf, cfdp::FileDirectives::KEEP_ALIVE, 4), progress(progress) { - updateDirectiveFieldLen(); -} - -size_t KeepAlivePduSerializer::getSerializedSize() const { - return FileDirectiveSerializer::getWholePduSize(); -} - -void KeepAlivePduSerializer::updateDirectiveFieldLen() { - if (this->getLargeFileFlag()) { - this->setDirectiveDataFieldLen(8); - } -} - -ReturnValue_t KeepAlivePduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const { - ReturnValue_t result = - FileDirectiveSerializer::serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - return progress.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness); -} diff --git a/src/fsfw/cfdp/pdu/KeepAlivePduSerializer.h b/src/fsfw/cfdp/pdu/KeepAlivePduSerializer.h deleted file mode 100644 index d2499a79..00000000 --- a/src/fsfw/cfdp/pdu/KeepAlivePduSerializer.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef FSFW_SRC_FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ -#define FSFW_SRC_FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ - -#include "fsfw/cfdp/FileSize.h" -#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h" - -class KeepAlivePduSerializer : public FileDirectiveSerializer { - public: - KeepAlivePduSerializer(PduConfig& conf, cfdp::FileSize& progress); - - void updateDirectiveFieldLen(); - - size_t getSerializedSize() const override; - - ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const override; - - private: - cfdp::FileSize& progress; -}; - -#endif /* FSFW_SRC_FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/MetadataInfo.cpp b/src/fsfw/cfdp/pdu/MetadataInfo.cpp index a2ca6972..d88bdd87 100644 --- a/src/fsfw/cfdp/pdu/MetadataInfo.cpp +++ b/src/fsfw/cfdp/pdu/MetadataInfo.cpp @@ -1,54 +1,57 @@ #include "MetadataInfo.h" MetadataInfo::MetadataInfo(bool closureRequested, cfdp::ChecksumType checksumType, - cfdp::FileSize& fileSize, cfdp::Lv& sourceFileName, - cfdp::Lv& destFileName) - : closureRequested(closureRequested), - checksumType(checksumType), - fileSize(fileSize), - sourceFileName(sourceFileName), - destFileName(destFileName) {} + cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName, + cfdp::StringLv& destFileName) + : MetadataInfo(fileSize, sourceFileName, destFileName) { + this->closureRequested = closureRequested; + this->checksumType = checksumType; +} -void MetadataInfo::setOptionsArray(cfdp::Tlv** optionsArray, size_t* optionsLen, - size_t* maxOptionsLen) { - this->optionsArray = optionsArray; - if (maxOptionsLen != nullptr) { - this->maxOptionsLen = *maxOptionsLen; +MetadataInfo::MetadataInfo(cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName, + cfdp::StringLv& destFileName) + : fileSize(fileSize), sourceFileName(sourceFileName), destFileName(destFileName) {} + +void MetadataInfo::setOptionsArray(cfdp::Tlv** optionsArray_, std::optional optionsLen_, + std::optional maxOptionsLen_) { + this->optionsArray = optionsArray_; + if (maxOptionsLen_) { + this->maxOptionsLen = maxOptionsLen_.value(); } - if (optionsLen != nullptr) { - this->optionsLen = *optionsLen; + if (optionsLen_) { + this->optionsLen = optionsLen_.value(); } } cfdp::ChecksumType MetadataInfo::getChecksumType() const { return checksumType; } -void MetadataInfo::setChecksumType(cfdp::ChecksumType checksumType) { - this->checksumType = checksumType; +void MetadataInfo::setChecksumType(cfdp::ChecksumType checksumType_) { + checksumType = checksumType_; } bool MetadataInfo::isClosureRequested() const { return closureRequested; } -void MetadataInfo::setClosureRequested(bool closureRequested) { - this->closureRequested = closureRequested; +void MetadataInfo::setClosureRequested(bool closureRequested_) { + closureRequested = closureRequested_; } -cfdp::Lv& MetadataInfo::getDestFileName() { return destFileName; } +cfdp::StringLv& MetadataInfo::getDestFileName() { return destFileName; } cfdp::FileSize& MetadataInfo::getFileSize() { return fileSize; } -ReturnValue_t MetadataInfo::getOptions(cfdp::Tlv*** optionsArray, size_t* optionsLen, +ReturnValue_t MetadataInfo::getOptions(cfdp::Tlv*** optionsArray_, size_t* optionsLen_, size_t* maxOptsLen) { - if (optionsArray == nullptr or this->optionsArray == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + if (optionsArray_ == nullptr or optionsArray == nullptr) { + return returnvalue::FAILED; } - *optionsArray = this->optionsArray; - if (optionsLen != nullptr) { - *optionsLen = this->optionsLen; + *optionsArray_ = optionsArray; + if (optionsLen_ != nullptr) { + *optionsLen_ = this->optionsLen; } if (maxOptsLen != nullptr) { *maxOptsLen = this->maxOptionsLen; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } bool MetadataInfo::hasOptions() const { @@ -81,18 +84,20 @@ size_t MetadataInfo::getSerializedSize(bool fssLarge) { return size; } -void MetadataInfo::setDestFileName(cfdp::Lv& destFileName) { this->destFileName = destFileName; } +void MetadataInfo::setDestFileName(cfdp::StringLv& destFileName_) { + this->destFileName = destFileName_; +} -void MetadataInfo::setSourceFileName(cfdp::Lv& sourceFileName) { - this->sourceFileName = sourceFileName; +void MetadataInfo::setSourceFileName(cfdp::StringLv& sourceFileName_) { + this->sourceFileName = sourceFileName_; } size_t MetadataInfo::getMaxOptionsLen() const { return maxOptionsLen; } -void MetadataInfo::setMaxOptionsLen(size_t maxOptionsLen) { this->maxOptionsLen = maxOptionsLen; } +void MetadataInfo::setMaxOptionsLen(size_t maxOptionsLen_) { this->maxOptionsLen = maxOptionsLen_; } size_t MetadataInfo::getOptionsLen() const { return optionsLen; } -void MetadataInfo::setOptionsLen(size_t optionsLen) { this->optionsLen = optionsLen; } +void MetadataInfo::setOptionsLen(size_t optionsLen_) { this->optionsLen = optionsLen_; } -cfdp::Lv& MetadataInfo::getSourceFileName() { return sourceFileName; } +cfdp::StringLv& MetadataInfo::getSourceFileName() { return sourceFileName; } diff --git a/src/fsfw/cfdp/pdu/MetadataInfo.h b/src/fsfw/cfdp/pdu/MetadataInfo.h index 9b90138c..95f4544a 100644 --- a/src/fsfw/cfdp/pdu/MetadataInfo.h +++ b/src/fsfw/cfdp/pdu/MetadataInfo.h @@ -1,45 +1,51 @@ #ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_ #define FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_ +#include + #include "fsfw/cfdp/FileSize.h" #include "fsfw/cfdp/definitions.h" #include "fsfw/cfdp/tlv/Lv.h" +#include "fsfw/cfdp/tlv/StringLv.h" #include "fsfw/cfdp/tlv/Tlv.h" class MetadataInfo { public: + MetadataInfo(cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName, + cfdp::StringLv& destFileName); MetadataInfo(bool closureRequested, cfdp::ChecksumType checksumType, cfdp::FileSize& fileSize, - cfdp::Lv& sourceFileName, cfdp::Lv& destFileName); + cfdp::StringLv& sourceFileName, cfdp::StringLv& destFileName); size_t getSerializedSize(bool fssLarge = false); - void setOptionsArray(cfdp::Tlv** optionsArray, size_t* optionsLen, size_t* maxOptionsLen); - cfdp::ChecksumType getChecksumType() const; + void setOptionsArray(cfdp::Tlv** optionsArray, std::optional optionsLen, + std::optional maxOptionsLen); + [[nodiscard]] cfdp::ChecksumType getChecksumType() const; void setChecksumType(cfdp::ChecksumType checksumType); - bool isClosureRequested() const; + [[nodiscard]] bool isClosureRequested() const; void setClosureRequested(bool closureRequested = false); - void setDestFileName(cfdp::Lv& destFileName); - void setSourceFileName(cfdp::Lv& sourceFileName); + void setDestFileName(cfdp::StringLv& destFileName); + void setSourceFileName(cfdp::StringLv& sourceFileName); - cfdp::Lv& getDestFileName(); - cfdp::Lv& getSourceFileName(); + cfdp::StringLv& getDestFileName(); + cfdp::StringLv& getSourceFileName(); cfdp::FileSize& getFileSize(); - bool hasOptions() const; - bool canHoldOptions() const; + [[nodiscard]] bool hasOptions() const; + [[nodiscard]] bool canHoldOptions() const; ReturnValue_t getOptions(cfdp::Tlv*** optionsArray, size_t* optionsLen, size_t* maxOptsLen); void setOptionsLen(size_t optionsLen); - size_t getOptionsLen() const; + [[nodiscard]] size_t getOptionsLen() const; void setMaxOptionsLen(size_t maxOptionsLen); - size_t getMaxOptionsLen() const; + [[nodiscard]] size_t getMaxOptionsLen() const; private: bool closureRequested = false; - cfdp::ChecksumType checksumType; + cfdp::ChecksumType checksumType = cfdp::ChecksumType::NULL_CHECKSUM; cfdp::FileSize& fileSize; - cfdp::Lv& sourceFileName; - cfdp::Lv& destFileName; + cfdp::StringLv& sourceFileName; + cfdp::StringLv& destFileName; cfdp::Tlv** optionsArray = nullptr; size_t optionsLen = 0; diff --git a/src/fsfw/cfdp/pdu/MetadataPduSerializer.cpp b/src/fsfw/cfdp/pdu/MetadataPduCreator.cpp similarity index 51% rename from src/fsfw/cfdp/pdu/MetadataPduSerializer.cpp rename to src/fsfw/cfdp/pdu/MetadataPduCreator.cpp index f5c4de0a..536a48f4 100644 --- a/src/fsfw/cfdp/pdu/MetadataPduSerializer.cpp +++ b/src/fsfw/cfdp/pdu/MetadataPduCreator.cpp @@ -1,23 +1,22 @@ -#include "MetadataPduSerializer.h" +#include "MetadataPduCreator.h" -MetadataPduSerializer::MetadataPduSerializer(PduConfig &conf, MetadataInfo &info) - : FileDirectiveSerializer(conf, cfdp::FileDirectives::METADATA, 5), info(info) { +MetadataPduCreator::MetadataPduCreator(PduConfig &conf, MetadataInfo &info) + : FileDirectiveCreator(conf, cfdp::FileDirective::METADATA, 5), info(info) { updateDirectiveFieldLen(); } -void MetadataPduSerializer::updateDirectiveFieldLen() { +void MetadataPduCreator::updateDirectiveFieldLen() { setDirectiveDataFieldLen(info.getSerializedSize(getLargeFileFlag())); } -size_t MetadataPduSerializer::getSerializedSize() const { - return FileDirectiveSerializer::getWholePduSize(); +size_t MetadataPduCreator::getSerializedSize() const { + return FileDirectiveCreator::getWholePduSize(); } -ReturnValue_t MetadataPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const { - ReturnValue_t result = - FileDirectiveSerializer::serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { +ReturnValue_t MetadataPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const { + ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { return result; } if (*size + 1 >= maxSize) { @@ -27,15 +26,15 @@ ReturnValue_t MetadataPduSerializer::serialize(uint8_t **buffer, size_t *size, s *buffer += 1; *size += 1; result = info.getFileSize().serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = info.getSourceFileName().serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = info.getDestFileName().serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -45,7 +44,7 @@ ReturnValue_t MetadataPduSerializer::serialize(uint8_t **buffer, size_t *size, s info.getOptions(&optsArray, &optsLen, nullptr); for (size_t idx = 0; idx < optsLen; idx++) { result = optsArray[idx]->serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } } diff --git a/src/fsfw/cfdp/pdu/MetadataPduCreator.h b/src/fsfw/cfdp/pdu/MetadataPduCreator.h new file mode 100644 index 00000000..4486a79c --- /dev/null +++ b/src/fsfw/cfdp/pdu/MetadataPduCreator.h @@ -0,0 +1,23 @@ +#ifndef FSFW_CFDP_PDU_METADATAPDUCREATOR_H_ +#define FSFW_CFDP_PDU_METADATAPDUCREATOR_H_ + +#include "fsfw/cfdp/pdu/FileDirectiveCreator.h" +#include "fsfw/cfdp/pdu/MetadataInfo.h" + +class MetadataPduCreator : public FileDirectiveCreator { + public: + MetadataPduCreator(PduConfig& conf, MetadataInfo& info); + + void updateDirectiveFieldLen(); + + [[nodiscard]] size_t getSerializedSize() const override; + + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override; + using FileDirectiveCreator::serialize; + + private: + MetadataInfo& info; +}; + +#endif /* FSFW_CFDP_PDU_METADATAPDUCREATOR_H_ */ diff --git a/src/fsfw/cfdp/pdu/MetadataPduDeserializer.h b/src/fsfw/cfdp/pdu/MetadataPduDeserializer.h deleted file mode 100644 index 1a8f9315..00000000 --- a/src/fsfw/cfdp/pdu/MetadataPduDeserializer.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAPDUDESERIALIZER_H_ -#define FSFW_SRC_FSFW_CFDP_PDU_METADATAPDUDESERIALIZER_H_ - -#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h" -#include "fsfw/cfdp/pdu/MetadataInfo.h" - -class MetadataPduDeserializer : public FileDirectiveDeserializer { - public: - MetadataPduDeserializer(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info); - - ReturnValue_t parseData() override; - - private: - MetadataInfo& info; -}; - -#endif /* FSFW_SRC_FSFW_CFDP_PDU_METADATAPDUDESERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/MetadataPduDeserializer.cpp b/src/fsfw/cfdp/pdu/MetadataPduReader.cpp similarity index 58% rename from src/fsfw/cfdp/pdu/MetadataPduDeserializer.cpp rename to src/fsfw/cfdp/pdu/MetadataPduReader.cpp index 161eb63a..66025140 100644 --- a/src/fsfw/cfdp/pdu/MetadataPduDeserializer.cpp +++ b/src/fsfw/cfdp/pdu/MetadataPduReader.cpp @@ -1,17 +1,16 @@ -#include "MetadataPduDeserializer.h" +#include "MetadataPduReader.h" -MetadataPduDeserializer::MetadataPduDeserializer(const uint8_t* pduBuf, size_t maxSize, - MetadataInfo& info) - : FileDirectiveDeserializer(pduBuf, maxSize), info(info) {} +MetadataPduReader::MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info) + : FileDirectiveReader(pduBuf, maxSize), info(info) {} -ReturnValue_t MetadataPduDeserializer::parseData() { - ReturnValue_t result = FileDirectiveDeserializer::parseData(); - if (result != HasReturnvaluesIF::RETURN_OK) { +ReturnValue_t MetadataPduReader::parseData() { + ReturnValue_t result = FileDirectiveReader::parseData(); + if (result != returnvalue::OK) { return result; } - size_t currentIdx = FileDirectiveDeserializer::getHeaderSize(); - const uint8_t* buf = rawPtr + currentIdx; - size_t remSize = FileDirectiveDeserializer::getWholePduSize() - currentIdx; + size_t currentIdx = FileDirectiveReader::getHeaderSize(); + const uint8_t* buf = pointers.rawPtr + currentIdx; + size_t remSize = FileDirectiveReader::getWholePduSize() - currentIdx; if (remSize < 1) { return SerializeIF::STREAM_TOO_SHORT; } @@ -21,15 +20,15 @@ ReturnValue_t MetadataPduDeserializer::parseData() { buf += 1; auto endianness = getEndianness(); result = info.getFileSize().deSerialize(&buf, &remSize, endianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = info.getSourceFileName().deSerialize(&buf, &remSize, endianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = info.getDestFileName().deSerialize(&buf, &remSize, endianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -47,7 +46,7 @@ ReturnValue_t MetadataPduDeserializer::parseData() { return cfdp::METADATA_CANT_PARSE_OPTIONS; } result = optionsArray[optsIdx]->deSerialize(&buf, &remSize, endianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } optsIdx++; diff --git a/src/fsfw/cfdp/pdu/MetadataPduReader.h b/src/fsfw/cfdp/pdu/MetadataPduReader.h new file mode 100644 index 00000000..3e8c0f30 --- /dev/null +++ b/src/fsfw/cfdp/pdu/MetadataPduReader.h @@ -0,0 +1,17 @@ +#ifndef FSFW_CFDP_PDU_METADATAPDUREADER_H_ +#define FSFW_CFDP_PDU_METADATAPDUREADER_H_ + +#include "fsfw/cfdp/pdu/FileDirectiveReader.h" +#include "fsfw/cfdp/pdu/MetadataInfo.h" + +class MetadataPduReader : public FileDirectiveReader { + public: + MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info); + + ReturnValue_t parseData() override; + + private: + MetadataInfo& info; +}; + +#endif /* FSFW_CFDP_PDU_METADATAPDUREADER_H_ */ diff --git a/src/fsfw/cfdp/pdu/MetadataPduSerializer.h b/src/fsfw/cfdp/pdu/MetadataPduSerializer.h deleted file mode 100644 index cacf8a52..00000000 --- a/src/fsfw/cfdp/pdu/MetadataPduSerializer.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAPDUSERIALIZER_H_ -#define FSFW_SRC_FSFW_CFDP_PDU_METADATAPDUSERIALIZER_H_ - -#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h" -#include "fsfw/cfdp/pdu/MetadataInfo.h" - -class MetadataPduSerializer : public FileDirectiveSerializer { - public: - MetadataPduSerializer(PduConfig& conf, MetadataInfo& info); - - void updateDirectiveFieldLen(); - - size_t getSerializedSize() const override; - - ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const override; - - private: - MetadataInfo& info; -}; - -#endif /* FSFW_SRC_FSFW_CFDP_PDU_METADATAPDUSERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/NakInfo.cpp b/src/fsfw/cfdp/pdu/NakInfo.cpp index 795004a9..14d06cb0 100644 --- a/src/fsfw/cfdp/pdu/NakInfo.cpp +++ b/src/fsfw/cfdp/pdu/NakInfo.cpp @@ -26,7 +26,7 @@ bool NakInfo::hasSegmentRequests() const { } bool NakInfo::canHoldSegmentRequests() const { - if (this->segmentRequests != nullptr and maxSegmentRequestsLen > 0) { + if (segmentRequests != nullptr and maxSegmentRequestsLen > 0) { return true; } return false; diff --git a/src/fsfw/cfdp/pdu/NakPduSerializer.cpp b/src/fsfw/cfdp/pdu/NakPduCreator.cpp similarity index 50% rename from src/fsfw/cfdp/pdu/NakPduSerializer.cpp rename to src/fsfw/cfdp/pdu/NakPduCreator.cpp index 95f1bc98..11f3aba9 100644 --- a/src/fsfw/cfdp/pdu/NakPduSerializer.cpp +++ b/src/fsfw/cfdp/pdu/NakPduCreator.cpp @@ -1,31 +1,28 @@ -#include "NakPduSerializer.h" +#include "NakPduCreator.h" -NakPduSerializer::NakPduSerializer(PduConfig &pduConf, NakInfo &nakInfo) - : FileDirectiveSerializer(pduConf, cfdp::FileDirectives::NAK, 0), nakInfo(nakInfo) { +NakPduCreator::NakPduCreator(PduConfig &pduConf, NakInfo &nakInfo) + : FileDirectiveCreator(pduConf, cfdp::FileDirective::NAK, 0), nakInfo(nakInfo) { updateDirectiveFieldLen(); } -void NakPduSerializer::updateDirectiveFieldLen() { +void NakPduCreator::updateDirectiveFieldLen() { this->setDirectiveDataFieldLen(nakInfo.getSerializedSize(getLargeFileFlag())); } -size_t NakPduSerializer::getSerializedSize() const { - return FileDirectiveSerializer::getWholePduSize(); -} +size_t NakPduCreator::getSerializedSize() const { return FileDirectiveCreator::getWholePduSize(); } -ReturnValue_t NakPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const { - ReturnValue_t result = - FileDirectiveSerializer::serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { +ReturnValue_t NakPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const { + ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { return result; } result = nakInfo.getStartOfScope().serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = nakInfo.getEndOfScope().serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (nakInfo.hasSegmentRequests()) { @@ -34,11 +31,11 @@ ReturnValue_t NakPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t nakInfo.getSegmentRequests(&segmentRequests, &segmentRequestLen, nullptr); for (size_t idx = 0; idx < segmentRequestLen; idx++) { result = segmentRequests[idx].first.serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = segmentRequests[idx].second.serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } } diff --git a/src/fsfw/cfdp/pdu/NakPduSerializer.h b/src/fsfw/cfdp/pdu/NakPduCreator.h similarity index 65% rename from src/fsfw/cfdp/pdu/NakPduSerializer.h rename to src/fsfw/cfdp/pdu/NakPduCreator.h index 4009884b..bfcff78d 100644 --- a/src/fsfw/cfdp/pdu/NakPduSerializer.h +++ b/src/fsfw/cfdp/pdu/NakPduCreator.h @@ -1,14 +1,14 @@ -#ifndef FSFW_SRC_FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_ -#define FSFW_SRC_FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_ +#ifndef FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_ +#define FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_ #include #include "NakInfo.h" #include "fsfw/cfdp/FileSize.h" #include "fsfw/cfdp/definitions.h" -#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h" +#include "fsfw/cfdp/pdu/FileDirectiveCreator.h" -class NakPduSerializer : public FileDirectiveSerializer { +class NakPduCreator : public FileDirectiveCreator { public: /** * @@ -18,9 +18,9 @@ class NakPduSerializer : public FileDirectiveSerializer { * @param [in] segmentRequests Pointer to the start of a list of segment requests * @param segmentRequestLen Length of the segment request list to be serialized */ - NakPduSerializer(PduConfig& PduConf, NakInfo& nakInfo); + NakPduCreator(PduConfig& PduConf, NakInfo& nakInfo); - size_t getSerializedSize() const override; + [[nodiscard]] size_t getSerializedSize() const override; ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness) const override; @@ -35,4 +35,4 @@ class NakPduSerializer : public FileDirectiveSerializer { NakInfo& nakInfo; }; -#endif /* FSFW_SRC_FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_ */ +#endif /* FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/NakPduDeserializer.h b/src/fsfw/cfdp/pdu/NakPduDeserializer.h deleted file mode 100644 index f0f43158..00000000 --- a/src/fsfw/cfdp/pdu/NakPduDeserializer.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef FSFW_SRC_FSFW_CFDP_PDU_NAKPDUDESERIALIZER_H_ -#define FSFW_SRC_FSFW_CFDP_PDU_NAKPDUDESERIALIZER_H_ - -#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h" -#include "fsfw/cfdp/pdu/NakInfo.h" - -class NakPduDeserializer : public FileDirectiveDeserializer { - public: - NakPduDeserializer(const uint8_t* pduBuf, size_t maxSize, NakInfo& info); - - /** - * This needs to be called before accessing the PDU fields to avoid segmentation faults. - * @return - */ - virtual ReturnValue_t parseData() override; - - private: - NakInfo& nakInfo; -}; - -#endif /* FSFW_SRC_FSFW_CFDP_PDU_NAKPDUDESERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/NakPduDeserializer.cpp b/src/fsfw/cfdp/pdu/NakPduReader.cpp similarity index 61% rename from src/fsfw/cfdp/pdu/NakPduDeserializer.cpp rename to src/fsfw/cfdp/pdu/NakPduReader.cpp index 9d5f074c..c67774c0 100644 --- a/src/fsfw/cfdp/pdu/NakPduDeserializer.cpp +++ b/src/fsfw/cfdp/pdu/NakPduReader.cpp @@ -1,26 +1,26 @@ -#include "NakPduDeserializer.h" +#include "NakPduReader.h" -NakPduDeserializer::NakPduDeserializer(const uint8_t* pduBuf, size_t maxSize, NakInfo& info) - : FileDirectiveDeserializer(pduBuf, maxSize), nakInfo(info) {} +NakPduReader::NakPduReader(const uint8_t* pduBuf, size_t maxSize, NakInfo& info) + : FileDirectiveReader(pduBuf, maxSize), nakInfo(info) {} -ReturnValue_t NakPduDeserializer::parseData() { - ReturnValue_t result = FileDirectiveDeserializer::parseData(); - if (result != HasReturnvaluesIF::RETURN_OK) { +ReturnValue_t NakPduReader::parseData() { + ReturnValue_t result = FileDirectiveReader::parseData(); + if (result != returnvalue::OK) { return result; } - size_t currentIdx = FileDirectiveDeserializer::getHeaderSize(); - const uint8_t* buffer = rawPtr + currentIdx; - size_t remSize = FileDirectiveDeserializer::getWholePduSize() - currentIdx; + size_t currentIdx = FileDirectiveReader::getHeaderSize(); + const uint8_t* buffer = pointers.rawPtr + currentIdx; + size_t remSize = FileDirectiveReader::getWholePduSize() - currentIdx; if (remSize < 1) { return SerializeIF::STREAM_TOO_SHORT; } result = nakInfo.getStartOfScope().deSerialize(&buffer, &remSize, SerializeIF::Endianness::NETWORK); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = nakInfo.getEndOfScope().deSerialize(&buffer, &remSize, SerializeIF::Endianness::NETWORK); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } nakInfo.setSegmentRequestLen(0); @@ -39,12 +39,12 @@ ReturnValue_t NakPduDeserializer::parseData() { } result = segReqs[idx].first.deSerialize(&buffer, &remSize, SerializeIF::Endianness::NETWORK); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = segReqs[idx].second.deSerialize(&buffer, &remSize, SerializeIF::Endianness::NETWORK); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } idx++; diff --git a/src/fsfw/cfdp/pdu/NakPduReader.h b/src/fsfw/cfdp/pdu/NakPduReader.h new file mode 100644 index 00000000..7e08229d --- /dev/null +++ b/src/fsfw/cfdp/pdu/NakPduReader.h @@ -0,0 +1,21 @@ +#ifndef FSFW_CFDP_PDU_NAKPDUDESERIALIZER_H_ +#define FSFW_CFDP_PDU_NAKPDUDESERIALIZER_H_ + +#include "fsfw/cfdp/pdu/FileDirectiveReader.h" +#include "fsfw/cfdp/pdu/NakInfo.h" + +class NakPduReader : public FileDirectiveReader { + public: + NakPduReader(const uint8_t* pduBuf, size_t maxSize, NakInfo& info); + + /** + * This needs to be called before accessing the PDU fields to avoid segmentation faults. + * @return + */ + ReturnValue_t parseData() override; + + private: + NakInfo& nakInfo; +}; + +#endif /* FSFW_CFDP_PDU_NAKPDUDESERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/PduConfig.cpp b/src/fsfw/cfdp/pdu/PduConfig.cpp index d495f864..ccb20f51 100644 --- a/src/fsfw/cfdp/pdu/PduConfig.cpp +++ b/src/fsfw/cfdp/pdu/PduConfig.cpp @@ -1,12 +1,14 @@ #include "PduConfig.h" -PduConfig::PduConfig(cfdp::TransmissionModes mode, cfdp::TransactionSeqNum seqNum, - cfdp::EntityId sourceId, cfdp::EntityId destId, bool crcFlag, bool largeFile, +#include + +PduConfig::PduConfig(cfdp::EntityId sourceId, cfdp::EntityId destId, cfdp::TransmissionMode mode, + cfdp::TransactionSeqNum seqNum, bool crcFlag, bool largeFile, cfdp::Direction direction) : mode(mode), - seqNum(seqNum), - sourceId(sourceId), - destId(destId), + seqNum(std::move(seqNum)), + sourceId(std::move(sourceId)), + destId(std::move(destId)), crcFlag(crcFlag), largeFile(largeFile), direction(direction) {} diff --git a/src/fsfw/cfdp/pdu/PduConfig.h b/src/fsfw/cfdp/pdu/PduConfig.h index e5b52e52..70f37e38 100644 --- a/src/fsfw/cfdp/pdu/PduConfig.h +++ b/src/fsfw/cfdp/pdu/PduConfig.h @@ -1,36 +1,23 @@ #ifndef FSFW_SRC_FSFW_CFDP_PDU_PDUCONFIG_H_ #define FSFW_SRC_FSFW_CFDP_PDU_PDUCONFIG_H_ -#include "VarLenField.h" - -namespace cfdp { - -struct EntityId : public VarLenField { - public: - EntityId() : VarLenField() {} - EntityId(cfdp::WidthInBytes width, size_t entityId) : VarLenField(width, entityId) {} -}; - -struct TransactionSeqNum : public VarLenField { - public: - TransactionSeqNum() : VarLenField() {} - TransactionSeqNum(cfdp::WidthInBytes width, size_t seqNum) : VarLenField(width, seqNum) {} -}; - -} // namespace cfdp +#include "fsfw/cfdp/VarLenFields.h" +#include "fsfw/cfdp/definitions.h" class PduConfig { public: - PduConfig(cfdp::TransmissionModes mode, cfdp::TransactionSeqNum seqNum, cfdp::EntityId sourceId, - cfdp::EntityId destId, bool crcFlag = false, bool largeFile = false, + PduConfig() = default; + PduConfig(cfdp::EntityId sourceId, cfdp::EntityId destId, cfdp::TransmissionMode mode, + cfdp::TransactionSeqNum seqNum, bool crcFlag = false, bool largeFile = false, cfdp::Direction direction = cfdp::Direction::TOWARDS_RECEIVER); - cfdp::TransmissionModes mode; + + cfdp::TransmissionMode mode = cfdp::TransmissionMode::ACKNOWLEDGED; cfdp::TransactionSeqNum seqNum; cfdp::EntityId sourceId; cfdp::EntityId destId; - bool crcFlag; - bool largeFile; - cfdp::Direction direction; + bool crcFlag = false; + bool largeFile = false; + cfdp::Direction direction = cfdp::Direction::TOWARDS_RECEIVER; }; #endif /* FSFW_SRC_FSFW_CFDP_PDU_PDUCONFIG_H_ */ diff --git a/src/fsfw/cfdp/pdu/PduHeaderIF.h b/src/fsfw/cfdp/pdu/PduHeaderIF.h index f05d95a4..341b0335 100644 --- a/src/fsfw/cfdp/pdu/PduHeaderIF.h +++ b/src/fsfw/cfdp/pdu/PduHeaderIF.h @@ -3,8 +3,8 @@ #include -#include "../definitions.h" #include "PduConfig.h" +#include "fsfw/cfdp/definitions.h" /** * @brief Generic interface to access all fields of a PDU header @@ -13,20 +13,20 @@ */ class PduHeaderIF { public: - virtual ~PduHeaderIF(){}; + virtual ~PduHeaderIF() = default; - virtual size_t getWholePduSize() const = 0; - virtual size_t getPduDataFieldLen() const = 0; - virtual cfdp::PduType getPduType() const = 0; - virtual cfdp::Direction getDirection() const = 0; - virtual cfdp::TransmissionModes getTransmissionMode() const = 0; - virtual bool getCrcFlag() const = 0; - virtual bool getLargeFileFlag() const = 0; - virtual cfdp::SegmentationControl getSegmentationControl() const = 0; - virtual cfdp::WidthInBytes getLenEntityIds() const = 0; - virtual cfdp::WidthInBytes getLenSeqNum() const = 0; - virtual cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const = 0; - virtual bool hasSegmentMetadataFlag() const = 0; + [[nodiscard]] virtual size_t getWholePduSize() const = 0; + [[nodiscard]] virtual size_t getPduDataFieldLen() const = 0; + [[nodiscard]] virtual cfdp::PduType getPduType() const = 0; + [[nodiscard]] virtual cfdp::Direction getDirection() const = 0; + [[nodiscard]] virtual cfdp::TransmissionMode getTransmissionMode() const = 0; + [[nodiscard]] virtual bool getCrcFlag() const = 0; + [[nodiscard]] virtual bool getLargeFileFlag() const = 0; + [[nodiscard]] virtual cfdp::SegmentationControl getSegmentationControl() const = 0; + [[nodiscard]] virtual cfdp::WidthInBytes getLenEntityIds() const = 0; + [[nodiscard]] virtual cfdp::WidthInBytes getLenSeqNum() const = 0; + [[nodiscard]] virtual cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const = 0; + [[nodiscard]] virtual bool hasSegmentMetadataFlag() const = 0; virtual void getSourceId(cfdp::EntityId& sourceId) const = 0; virtual void getDestId(cfdp::EntityId& destId) const = 0; virtual void getTransactionSeqNum(cfdp::TransactionSeqNum& seqNum) const = 0; diff --git a/src/fsfw/cfdp/pdu/PduHeaderReader.h b/src/fsfw/cfdp/pdu/PduHeaderReader.h new file mode 100644 index 00000000..a2e122cd --- /dev/null +++ b/src/fsfw/cfdp/pdu/PduHeaderReader.h @@ -0,0 +1,114 @@ +#ifndef FSFW_SRC_FSFW_CFDP_PDU_HEADERDESERIALIZER_H_ +#define FSFW_SRC_FSFW_CFDP_PDU_HEADERDESERIALIZER_H_ + +#include +#include + +#include "PduConfig.h" +#include "PduHeaderIF.h" +#include "fsfw/serialize/SerializeIF.h" +#include "fsfw/tmtcpacket/RedirectableDataPointerIF.h" + +struct PduHeaderFixedStruct { + uint8_t firstByte; + uint8_t pduDataFieldLenH; + uint8_t pduDataFieldLenL; + uint8_t fourthByte; + uint8_t variableFieldsStart; +}; + +/** + * @brief This class is used to deserialize a PDU header from raw memory. + * @details + * This is a zero-copy implementation and #parseData needs to be called to ensure the data is + * valid. + */ +class PduHeaderReader : public RedirectableDataPointerIF, public PduHeaderIF { + public: + PduHeaderReader() = default; + /** + * Initialize a PDU header from raw data. This is a zero-copy implementation and #parseData + * needs to be called to ensure the data is valid + * @param pduBuf + * @param maxSize + */ + PduHeaderReader(const uint8_t* pduBuf, size_t maxSize); + + /** + * This needs to be called before accessing the PDU fields to avoid segmentation faults. + * @return + * - returnvalue::OK on parse success + * - returnvalue::FAILED Invalid raw data + * - SerializeIF::BUFFER_TOO_SHORT if buffer is shorter than expected + */ + virtual ReturnValue_t parseData(); + explicit operator bool() const; + [[nodiscard]] bool isNull() const; + + /** + * Fill the provided PDU configuration from the fields detected by this reader. + * @param cfg + */ + void fillConfig(PduConfig& cfg) const; + + [[nodiscard]] virtual size_t getHeaderSize() const; + + [[nodiscard]] size_t getPduDataFieldLen() const override; + [[nodiscard]] size_t getWholePduSize() const override; + + [[nodiscard]] cfdp::PduType getPduType() const override; + [[nodiscard]] cfdp::Direction getDirection() const override; + [[nodiscard]] cfdp::TransmissionMode getTransmissionMode() const override; + [[nodiscard]] bool getCrcFlag() const override; + [[nodiscard]] bool getLargeFileFlag() const override; + [[nodiscard]] cfdp::SegmentationControl getSegmentationControl() const override; + [[nodiscard]] cfdp::WidthInBytes getLenEntityIds() const override; + [[nodiscard]] cfdp::WidthInBytes getLenSeqNum() const override; + [[nodiscard]] cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const override; + [[nodiscard]] bool hasSegmentMetadataFlag() const override; + + void getSourceId(cfdp::EntityId& sourceId) const override; + void getDestId(cfdp::EntityId& destId) const override; + void getTransactionSeqNum(cfdp::TransactionSeqNum& seqNum) const override; + + ReturnValue_t deserResult = returnvalue::OK; + + [[nodiscard]] size_t getMaxSize() const; + [[nodiscard]] const uint8_t* getPduDataField() const; + + /** + * Can also be used to reset the pointer to a nullptr, but the getter functions will not + * perform nullptr checks! + * @param dataPtr + * @param maxSize + * @param args + * @return + */ + ReturnValue_t setReadOnlyData(const uint8_t* dataPtr, size_t maxSize); + + protected: + struct Pointers { + PduHeaderFixedStruct* fixedHeader = nullptr; + const uint8_t* dataFieldStart = nullptr; + const uint8_t* rawPtr = nullptr; + }; + + Pointers pointers; + size_t maxSize = 0; + + private: + /** + * This is a reader class and setting mutable data is forbidden. Use @setReadOnlyData instead. + * @param dataPtr + * @param maxSize + * @param args + * @return + */ + ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize, void* args) override; + void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width, void* sourcePtr) const; + void* sourceIdRaw = nullptr; + void* seqNumRaw = nullptr; + void* destIdRaw = nullptr; +}; + +#endif /* FSFW_SRC_FSFW_CFDP_PDU_HEADERDESERIALIZER_H_ */ diff --git a/src/fsfw/cfdp/pdu/PromptPduCreator.cpp b/src/fsfw/cfdp/pdu/PromptPduCreator.cpp new file mode 100644 index 00000000..f4141fdb --- /dev/null +++ b/src/fsfw/cfdp/pdu/PromptPduCreator.cpp @@ -0,0 +1,24 @@ +#include "PromptPduCreator.h" + +PromptPduCreator::PromptPduCreator(PduConfig &conf, cfdp::PromptResponseRequired responseRequired) + : FileDirectiveCreator(conf, cfdp::FileDirective::PROMPT, 1), + responseRequired(responseRequired) {} + +size_t PromptPduCreator::getSerializedSize() const { + return FileDirectiveCreator::getWholePduSize(); +} + +ReturnValue_t PromptPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const { + ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + if (*size + 1 > maxSize) { + return SerializeIF::BUFFER_TOO_SHORT; + } + **buffer = responseRequired << 7; + *buffer += 1; + *size += 1; + return result; +} diff --git a/src/fsfw/cfdp/pdu/PromptPduSerializer.h b/src/fsfw/cfdp/pdu/PromptPduCreator.h similarity index 61% rename from src/fsfw/cfdp/pdu/PromptPduSerializer.h rename to src/fsfw/cfdp/pdu/PromptPduCreator.h index 51500224..ccecab6e 100644 --- a/src/fsfw/cfdp/pdu/PromptPduSerializer.h +++ b/src/fsfw/cfdp/pdu/PromptPduCreator.h @@ -1,13 +1,13 @@ #ifndef FSFW_SRC_FSFW_CFDP_PDU_PROMPTPDUSERIALIZER_H_ #define FSFW_SRC_FSFW_CFDP_PDU_PROMPTPDUSERIALIZER_H_ -#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h" +#include "fsfw/cfdp/pdu/FileDirectiveCreator.h" -class PromptPduSerializer : public FileDirectiveSerializer { +class PromptPduCreator : public FileDirectiveCreator { public: - PromptPduSerializer(PduConfig& conf, cfdp::PromptResponseRequired responseRequired); + PromptPduCreator(PduConfig& conf, cfdp::PromptResponseRequired responseRequired); - size_t getSerializedSize() const override; + [[nodiscard]] size_t getSerializedSize() const override; ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness) const override; diff --git a/src/fsfw/cfdp/pdu/PromptPduDeserializer.cpp b/src/fsfw/cfdp/pdu/PromptPduDeserializer.cpp deleted file mode 100644 index 6a6f5505..00000000 --- a/src/fsfw/cfdp/pdu/PromptPduDeserializer.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "PromptPduDeserializer.h" - -PromptPduDeserializer::PromptPduDeserializer(const uint8_t *pduBuf, size_t maxSize) - : FileDirectiveDeserializer(pduBuf, maxSize) {} - -cfdp::PromptResponseRequired PromptPduDeserializer::getPromptResponseRequired() const { - return responseRequired; -} - -ReturnValue_t PromptPduDeserializer::parseData() { - ReturnValue_t result = FileDirectiveDeserializer::parseData(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - size_t currentIdx = FileDirectiveDeserializer::getHeaderSize(); - if (FileDirectiveDeserializer::getWholePduSize() - currentIdx < 1) { - return SerializeIF::STREAM_TOO_SHORT; - } - responseRequired = static_cast((rawPtr[currentIdx] >> 7) & 0x01); - return HasReturnvaluesIF::RETURN_OK; -} diff --git a/src/fsfw/cfdp/pdu/PromptPduReader.cpp b/src/fsfw/cfdp/pdu/PromptPduReader.cpp new file mode 100644 index 00000000..f554c3c9 --- /dev/null +++ b/src/fsfw/cfdp/pdu/PromptPduReader.cpp @@ -0,0 +1,21 @@ +#include "PromptPduReader.h" + +PromptPduReader::PromptPduReader(const uint8_t *pduBuf, size_t maxSize) + : FileDirectiveReader(pduBuf, maxSize) {} + +cfdp::PromptResponseRequired PromptPduReader::getPromptResponseRequired() const { + return responseRequired; +} + +ReturnValue_t PromptPduReader::parseData() { + ReturnValue_t result = FileDirectiveReader::parseData(); + if (result != returnvalue::OK) { + return result; + } + if (FileDirectiveReader::getWholePduSize() <= FileDirectiveReader::getHeaderSize()) { + return SerializeIF::STREAM_TOO_SHORT; + } + responseRequired = static_cast( + (pointers.rawPtr[FileDirectiveReader::getHeaderSize()] >> 7) & 0x01); + return returnvalue::OK; +} diff --git a/src/fsfw/cfdp/pdu/PromptPduDeserializer.h b/src/fsfw/cfdp/pdu/PromptPduReader.h similarity index 57% rename from src/fsfw/cfdp/pdu/PromptPduDeserializer.h rename to src/fsfw/cfdp/pdu/PromptPduReader.h index 9441f364..2afcb20e 100644 --- a/src/fsfw/cfdp/pdu/PromptPduDeserializer.h +++ b/src/fsfw/cfdp/pdu/PromptPduReader.h @@ -1,13 +1,13 @@ #ifndef FSFW_SRC_FSFW_CFDP_PDU_PROMPTPDUDESERIALIZER_H_ #define FSFW_SRC_FSFW_CFDP_PDU_PROMPTPDUDESERIALIZER_H_ -#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h" +#include "fsfw/cfdp/pdu/FileDirectiveReader.h" -class PromptPduDeserializer : public FileDirectiveDeserializer { +class PromptPduReader : public FileDirectiveReader { public: - PromptPduDeserializer(const uint8_t *pduBuf, size_t maxSize); + PromptPduReader(const uint8_t *pduBuf, size_t maxSize); - cfdp::PromptResponseRequired getPromptResponseRequired() const; + [[nodiscard]] cfdp::PromptResponseRequired getPromptResponseRequired() const; ReturnValue_t parseData() override; private: diff --git a/src/fsfw/cfdp/pdu/PromptPduSerializer.cpp b/src/fsfw/cfdp/pdu/PromptPduSerializer.cpp deleted file mode 100644 index a7287563..00000000 --- a/src/fsfw/cfdp/pdu/PromptPduSerializer.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "PromptPduSerializer.h" - -PromptPduSerializer::PromptPduSerializer(PduConfig &conf, - cfdp::PromptResponseRequired responseRequired) - : FileDirectiveSerializer(conf, cfdp::FileDirectives::PROMPT, 1), - responseRequired(responseRequired) {} - -size_t PromptPduSerializer::getSerializedSize() const { - return FileDirectiveSerializer::getWholePduSize(); -} - -ReturnValue_t PromptPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const { - ReturnValue_t result = - FileDirectiveSerializer::serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - if (*size + 1 > maxSize) { - return SerializeIF::BUFFER_TOO_SHORT; - } - **buffer = this->responseRequired << 7; - *buffer += 1; - *size += 1; - return result; -} diff --git a/src/fsfw/cfdp/pdu/VarLenField.h b/src/fsfw/cfdp/pdu/VarLenField.h deleted file mode 100644 index 590c2dd5..00000000 --- a/src/fsfw/cfdp/pdu/VarLenField.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef FSFW_SRC_FSFW_CFDP_PDU_VARLENFIELD_H_ -#define FSFW_SRC_FSFW_CFDP_PDU_VARLENFIELD_H_ - -#include -#include - -#include "../definitions.h" -#include "fsfw/serialize/SerializeIF.h" - -namespace cfdp { - -class VarLenField : public SerializeIF { - public: - union LengthFieldLen { - uint8_t oneByte; - uint16_t twoBytes; - uint32_t fourBytes; - uint64_t eightBytes; - }; - - VarLenField(); - VarLenField(cfdp::WidthInBytes width, size_t value); - - ReturnValue_t setValue(cfdp::WidthInBytes, size_t value); - - ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const override; - - size_t getSerializedSize() const override; - - ReturnValue_t deSerialize(cfdp::WidthInBytes width, const uint8_t **buffer, size_t *size, - Endianness streamEndianness); - - cfdp::WidthInBytes getWidth() const; - size_t getValue() const; - - private: - ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, - Endianness streamEndianness) override; - - cfdp::WidthInBytes width; - LengthFieldLen value; -}; - -} // namespace cfdp - -#endif /* FSFW_SRC_FSFW_CFDP_PDU_VARLENFIELD_H_ */ diff --git a/src/fsfw/cfdp/tlv/CMakeLists.txt b/src/fsfw/cfdp/tlv/CMakeLists.txt index 24459cf8..617b1b0f 100644 --- a/src/fsfw/cfdp/tlv/CMakeLists.txt +++ b/src/fsfw/cfdp/tlv/CMakeLists.txt @@ -1,10 +1,11 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - EntityIdTlv.cpp - FilestoreRequestTlv.cpp - FilestoreResponseTlv.cpp - Lv.cpp - Tlv.cpp - FlowLabelTlv.cpp - MessageToUserTlv.cpp - FaultHandlerOverrideTlv.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE EntityIdTlv.cpp + FilestoreRequestTlv.cpp + FilestoreResponseTlv.cpp + Lv.cpp + Tlv.cpp + StringLv.cpp + FlowLabelTlv.cpp + MessageToUserTlv.cpp + FaultHandlerOverrideTlv.cpp) diff --git a/src/fsfw/cfdp/tlv/EntityIdTlv.cpp b/src/fsfw/cfdp/tlv/EntityIdTlv.cpp index 87f55db8..d4c4d6a8 100644 --- a/src/fsfw/cfdp/tlv/EntityIdTlv.cpp +++ b/src/fsfw/cfdp/tlv/EntityIdTlv.cpp @@ -11,7 +11,7 @@ ReturnValue_t EntityIdTlv::serialize(uint8_t **buffer, size_t *size, size_t maxS if (maxSize < this->getSerializedSize()) { return BUFFER_TOO_SHORT; } - **buffer = cfdp::TlvTypes::ENTITY_ID; + **buffer = cfdp::TlvType::ENTITY_ID; *size += 1; *buffer += 1; size_t serLen = entityId.getSerializedSize(); @@ -28,8 +28,8 @@ ReturnValue_t EntityIdTlv::deSerialize(const uint8_t **buffer, size_t *size, if (*size < 3) { return STREAM_TOO_SHORT; } - cfdp::TlvTypes type = static_cast(**buffer); - if (type != cfdp::TlvTypes::ENTITY_ID) { + cfdp::TlvType type = static_cast(**buffer); + if (type != cfdp::TlvType::ENTITY_ID) { return cfdp::INVALID_TLV_TYPE; } *buffer += 1; @@ -54,6 +54,6 @@ ReturnValue_t EntityIdTlv::deSerialize(cfdp::Tlv &tlv, Endianness endianness) { uint8_t EntityIdTlv::getLengthField() const { return 1 + entityId.getSerializedSize(); } -cfdp::TlvTypes EntityIdTlv::getType() const { return cfdp::TlvTypes::ENTITY_ID; } +cfdp::TlvType EntityIdTlv::getType() const { return cfdp::TlvType::ENTITY_ID; } cfdp::EntityId &EntityIdTlv::getEntityId() { return entityId; } diff --git a/src/fsfw/cfdp/tlv/EntityIdTlv.h b/src/fsfw/cfdp/tlv/EntityIdTlv.h index 1443cc17..30ef97ff 100644 --- a/src/fsfw/cfdp/tlv/EntityIdTlv.h +++ b/src/fsfw/cfdp/tlv/EntityIdTlv.h @@ -23,11 +23,13 @@ class EntityIdTlv : public TlvIF { */ ReturnValue_t deSerialize(cfdp::Tlv& tlv, Endianness endianness); + using SerializeIF::deSerialize; // we overloaded this function, so this is needed to unconfuse + // the compiler ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) override; uint8_t getLengthField() const override; - cfdp::TlvTypes getType() const override; + cfdp::TlvType getType() const override; cfdp::EntityId& getEntityId(); diff --git a/src/fsfw/cfdp/tlv/FaultHandlerOverrideTlv.cpp b/src/fsfw/cfdp/tlv/FaultHandlerOverrideTlv.cpp index f5f777ea..90b71361 100644 --- a/src/fsfw/cfdp/tlv/FaultHandlerOverrideTlv.cpp +++ b/src/fsfw/cfdp/tlv/FaultHandlerOverrideTlv.cpp @@ -4,7 +4,7 @@ FaultHandlerOverrideTlv::FaultHandlerOverrideTlv(cfdp::ConditionCode conditionCo cfdp::FaultHandlerCode handlerCode) : conditionCode(conditionCode), handlerCode(handlerCode) {} -FaultHandlerOverrideTlv::FaultHandlerOverrideTlv() {} +FaultHandlerOverrideTlv::FaultHandlerOverrideTlv() = default; uint8_t FaultHandlerOverrideTlv::getLengthField() const { return 1; } @@ -22,7 +22,7 @@ ReturnValue_t FaultHandlerOverrideTlv::serialize(uint8_t **buffer, size_t *size, **buffer = this->conditionCode << 4 | this->handlerCode; *buffer += 1; *size += 1; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } size_t FaultHandlerOverrideTlv::getSerializedSize() const { return getLengthField() + 2; } @@ -32,15 +32,15 @@ ReturnValue_t FaultHandlerOverrideTlv::deSerialize(const uint8_t **buffer, size_ if (*size < 3) { return SerializeIF::STREAM_TOO_SHORT; } - auto detectedType = static_cast(**buffer); - if (detectedType != cfdp::TlvTypes::FAULT_HANDLER) { + auto detectedType = static_cast(**buffer); + if (detectedType != cfdp::TlvType::FAULT_HANDLER) { return cfdp::INVALID_TLV_TYPE; } *buffer += 1; *size -= 1; size_t detectedSize = **buffer; if (detectedSize != getLengthField()) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } *buffer += 1; *size += 1; @@ -48,7 +48,7 @@ ReturnValue_t FaultHandlerOverrideTlv::deSerialize(const uint8_t **buffer, size_ this->handlerCode = static_cast(**buffer & 0x0f); *buffer += 1; *size += 1; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } -cfdp::TlvTypes FaultHandlerOverrideTlv::getType() const { return cfdp::TlvTypes::FAULT_HANDLER; } +cfdp::TlvType FaultHandlerOverrideTlv::getType() const { return cfdp::TlvType::FAULT_HANDLER; } diff --git a/src/fsfw/cfdp/tlv/FaultHandlerOverrideTlv.h b/src/fsfw/cfdp/tlv/FaultHandlerOverrideTlv.h index 9f2adbb3..9f5cd486 100644 --- a/src/fsfw/cfdp/tlv/FaultHandlerOverrideTlv.h +++ b/src/fsfw/cfdp/tlv/FaultHandlerOverrideTlv.h @@ -3,18 +3,6 @@ #include "TlvIF.h" -namespace cfdp { - -enum FaultHandlerCode { - RESERVED = 0b0000, - NOTICE_OF_CANCELLATION = 0b0001, - NOTICE_OF_SUSPENSION = 0b0010, - IGNORE_ERROR = 0b0011, - ABANDON_TRANSACTION = 0b0100 -}; - -} - class FaultHandlerOverrideTlv : public TlvIF { public: FaultHandlerOverrideTlv(); @@ -23,12 +11,12 @@ class FaultHandlerOverrideTlv : public TlvIF { ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) const override; - size_t getSerializedSize() const override; + [[nodiscard]] size_t getSerializedSize() const override; ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, Endianness streamEndianness) override; - uint8_t getLengthField() const override; - cfdp::TlvTypes getType() const override; + [[nodiscard]] uint8_t getLengthField() const override; + [[nodiscard]] cfdp::TlvType getType() const override; private: cfdp::ConditionCode conditionCode = cfdp::ConditionCode::NO_CONDITION_FIELD; diff --git a/src/fsfw/cfdp/tlv/FilestoreRequestTlv.cpp b/src/fsfw/cfdp/tlv/FilestoreRequestTlv.cpp index 9ad7c645..1022a7d1 100644 --- a/src/fsfw/cfdp/tlv/FilestoreRequestTlv.cpp +++ b/src/fsfw/cfdp/tlv/FilestoreRequestTlv.cpp @@ -3,10 +3,10 @@ #include "fsfw/FSFW.h" FilestoreRequestTlv::FilestoreRequestTlv(cfdp::FilestoreActionCode actionCode, - cfdp::Lv &firstFileName) + cfdp::StringLv &firstFileName) : FilestoreTlvBase(actionCode, firstFileName) {} -FilestoreRequestTlv::FilestoreRequestTlv(cfdp::Lv &firstFileName) +FilestoreRequestTlv::FilestoreRequestTlv(cfdp::StringLv &firstFileName) : FilestoreTlvBase(cfdp::FilestoreActionCode::INVALID, firstFileName) {} void FilestoreRequestTlv::setSecondFileName(cfdp::Lv *secondFileName) { @@ -16,11 +16,11 @@ void FilestoreRequestTlv::setSecondFileName(cfdp::Lv *secondFileName) { ReturnValue_t FilestoreRequestTlv::serialize(uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result = commonSerialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = firstFileName.serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (requiresSecondFileName()) { @@ -30,13 +30,13 @@ ReturnValue_t FilestoreRequestTlv::serialize(uint8_t **buffer, size_t *size, siz } secondFileName->serialize(buffer, size, maxSize, streamEndianness); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t FilestoreRequestTlv::deSerialize(const uint8_t **buffer, size_t *size, Endianness streamEndianness) { ReturnValue_t result = commonDeserialize(buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return deSerializeFromValue(buffer, size, streamEndianness); @@ -63,17 +63,17 @@ ReturnValue_t FilestoreRequestTlv::deSerializeFromValue(const uint8_t **buffer, *buffer += 1; *size -= 1; ReturnValue_t result = firstFileName.deSerialize(buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (requiresSecondFileName()) { if (secondFileName == nullptr) { secondFileNameMissing(); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } result = secondFileName->deSerialize(buffer, size, streamEndianness); } return result; } -cfdp::TlvTypes FilestoreRequestTlv::getType() const { return cfdp::TlvTypes::FILESTORE_REQUEST; } +cfdp::TlvType FilestoreRequestTlv::getType() const { return cfdp::TlvType::FILESTORE_REQUEST; } diff --git a/src/fsfw/cfdp/tlv/FilestoreRequestTlv.h b/src/fsfw/cfdp/tlv/FilestoreRequestTlv.h index 5acb0ef4..02e639b8 100644 --- a/src/fsfw/cfdp/tlv/FilestoreRequestTlv.h +++ b/src/fsfw/cfdp/tlv/FilestoreRequestTlv.h @@ -9,9 +9,9 @@ class FilestoreRequestTlv : public cfdp::FilestoreTlvBase { public: - FilestoreRequestTlv(cfdp::FilestoreActionCode actionCode, cfdp::Lv &firstFileName); + FilestoreRequestTlv(cfdp::FilestoreActionCode actionCode, cfdp::StringLv &firstFileName); - FilestoreRequestTlv(cfdp::Lv &firstFileName); + explicit FilestoreRequestTlv(cfdp::StringLv &firstFileName); void setSecondFileName(cfdp::Lv *secondFileName); @@ -29,8 +29,8 @@ class FilestoreRequestTlv : public cfdp::FilestoreTlvBase { ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, Endianness streamEndianness) override; - uint8_t getLengthField() const override; - cfdp::TlvTypes getType() const override; + [[nodiscard]] uint8_t getLengthField() const override; + [[nodiscard]] cfdp::TlvType getType() const override; private: cfdp::Lv *secondFileName = nullptr; diff --git a/src/fsfw/cfdp/tlv/FilestoreResponseTlv.cpp b/src/fsfw/cfdp/tlv/FilestoreResponseTlv.cpp index 36945725..38b56077 100644 --- a/src/fsfw/cfdp/tlv/FilestoreResponseTlv.cpp +++ b/src/fsfw/cfdp/tlv/FilestoreResponseTlv.cpp @@ -1,10 +1,10 @@ #include "FilestoreResponseTlv.h" FilestoreResponseTlv::FilestoreResponseTlv(cfdp::FilestoreActionCode actionCode, uint8_t statusCode, - cfdp::Lv &firstFileName, cfdp::Lv *fsMsg) + cfdp::StringLv &firstFileName, cfdp::Lv *fsMsg) : FilestoreTlvBase(actionCode, firstFileName), statusCode(statusCode), filestoreMsg(fsMsg) {} -FilestoreResponseTlv::FilestoreResponseTlv(cfdp::Lv &firstFileName, cfdp::Lv *fsMsg) +FilestoreResponseTlv::FilestoreResponseTlv(cfdp::StringLv &firstFileName, cfdp::Lv *fsMsg) : FilestoreTlvBase(firstFileName), statusCode(0), filestoreMsg(fsMsg) {} uint8_t FilestoreResponseTlv::getLengthField() const { @@ -20,23 +20,23 @@ uint8_t FilestoreResponseTlv::getLengthField() const { return 1 + firstFileName.getSerializedSize() + optFieldsLen; } -void FilestoreResponseTlv::setSecondFileName(cfdp::Lv *secondFileName) { - this->secondFileName = secondFileName; +void FilestoreResponseTlv::setSecondFileName(cfdp::StringLv *secondFileName_) { + this->secondFileName = secondFileName_; } -void FilestoreResponseTlv::setFilestoreMessage(cfdp::Lv *filestoreMsg) { - this->filestoreMsg = filestoreMsg; +void FilestoreResponseTlv::setFilestoreMessage(cfdp::Lv *filestoreMsg_) { + this->filestoreMsg = filestoreMsg_; } ReturnValue_t FilestoreResponseTlv::serialize(uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result = commonSerialize(buffer, size, maxSize, streamEndianness, true, this->statusCode); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = firstFileName.serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (requiresSecondFileName()) { @@ -61,7 +61,7 @@ ReturnValue_t FilestoreResponseTlv::serialize(uint8_t **buffer, size_t *size, si ReturnValue_t FilestoreResponseTlv::deSerialize(const uint8_t **buffer, size_t *size, Endianness streamEndianness) { ReturnValue_t result = commonDeserialize(buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return deSerializeFromValue(buffer, size, streamEndianness); @@ -75,7 +75,7 @@ ReturnValue_t FilestoreResponseTlv::deSerializeFromValue(const uint8_t **buffer, *buffer += 1; *size -= 1; ReturnValue_t result = firstFileName.deSerialize(buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (requiresSecondFileName()) { @@ -83,7 +83,7 @@ ReturnValue_t FilestoreResponseTlv::deSerializeFromValue(const uint8_t **buffer, return cfdp::FILESTORE_REQUIRES_SECOND_FILE; } result = secondFileName->deSerialize(buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } } @@ -98,7 +98,7 @@ ReturnValue_t FilestoreResponseTlv::deSerializeFromValue(const uint8_t **buffer, *size -= 1; *buffer += 1; // Ignore empty filestore message - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } return filestoreMsg->deSerialize(buffer, size, streamEndianness); } @@ -112,4 +112,4 @@ ReturnValue_t FilestoreResponseTlv::deSerialize(const cfdp::Tlv &tlv, Endianness uint8_t FilestoreResponseTlv::getStatusCode() const { return statusCode; } -cfdp::TlvTypes FilestoreResponseTlv::getType() const { return cfdp::TlvTypes::FILESTORE_RESPONSE; } +cfdp::TlvType FilestoreResponseTlv::getType() const { return cfdp::TlvType::FILESTORE_RESPONSE; } diff --git a/src/fsfw/cfdp/tlv/FilestoreResponseTlv.h b/src/fsfw/cfdp/tlv/FilestoreResponseTlv.h index 7b68ba57..d5c805be 100644 --- a/src/fsfw/cfdp/tlv/FilestoreResponseTlv.h +++ b/src/fsfw/cfdp/tlv/FilestoreResponseTlv.h @@ -4,17 +4,18 @@ #include "Lv.h" #include "TlvIF.h" #include "fsfw/cfdp/tlv/FilestoreTlvBase.h" +#include "fsfw/cfdp/tlv/StringLv.h" #include "fsfw/cfdp/tlv/Tlv.h" class FilestoreResponseTlv : public cfdp::FilestoreTlvBase { public: - FilestoreResponseTlv(cfdp::Lv& firstFileName, cfdp::Lv* fsMsg); + FilestoreResponseTlv(cfdp::StringLv& firstFileName, cfdp::Lv* fsMsg); FilestoreResponseTlv(cfdp::FilestoreActionCode actionCode, uint8_t statusCode, - cfdp::Lv& firstFileName, cfdp::Lv* fsMsg); + cfdp::StringLv& firstFileName, cfdp::Lv* fsMsg); - uint8_t getStatusCode() const; - void setSecondFileName(cfdp::Lv* secondFileName); + [[nodiscard]] uint8_t getStatusCode() const; + void setSecondFileName(cfdp::StringLv* secondFileName); void setFilestoreMessage(cfdp::Lv* filestoreMsg); ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, @@ -28,15 +29,17 @@ class FilestoreResponseTlv : public cfdp::FilestoreTlvBase { */ ReturnValue_t deSerialize(const cfdp::Tlv& tlv, Endianness endianness); + using SerializeIF::deSerialize; // we overloaded this function, so this is needed to unconfuse + // the compiler ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) override; - uint8_t getLengthField() const override; - cfdp::TlvTypes getType() const override; + [[nodiscard]] uint8_t getLengthField() const override; + [[nodiscard]] cfdp::TlvType getType() const override; private: uint8_t statusCode; - cfdp::Lv* secondFileName = nullptr; + cfdp::StringLv* secondFileName = nullptr; cfdp::Lv* filestoreMsg = nullptr; ReturnValue_t deSerializeFromValue(const uint8_t** buffer, size_t* size, diff --git a/src/fsfw/cfdp/tlv/FilestoreTlvBase.h b/src/fsfw/cfdp/tlv/FilestoreTlvBase.h index 04012cda..a5974087 100644 --- a/src/fsfw/cfdp/tlv/FilestoreTlvBase.h +++ b/src/fsfw/cfdp/tlv/FilestoreTlvBase.h @@ -11,6 +11,7 @@ #include #include +#include "StringLv.h" #include "fsfw/FSFW.h" namespace cfdp { @@ -65,15 +66,15 @@ static constexpr uint8_t FSR_DENY_DIR_NOT_ALLOWED = 0b0010; class FilestoreTlvBase : public TlvIF { public: - FilestoreTlvBase(cfdp::Lv& firstFileName) : firstFileName(firstFileName){}; - FilestoreTlvBase(FilestoreActionCode actionCode, cfdp::Lv& firstFileName) + explicit FilestoreTlvBase(cfdp::StringLv& firstFileName) : firstFileName(firstFileName){}; + FilestoreTlvBase(FilestoreActionCode actionCode, cfdp::StringLv& firstFileName) : actionCode(actionCode), firstFileName(firstFileName){}; ReturnValue_t commonSerialize(uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness, bool isResponse = false, uint8_t responseStatusCode = 0) const { if (buffer == nullptr or size == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (maxSize < 3) { return SerializeIF::BUFFER_TOO_SHORT; @@ -90,18 +91,18 @@ class FilestoreTlvBase : public TlvIF { } *buffer += 1; *size += 1; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t commonDeserialize(const uint8_t** buffer, size_t* size, SerializeIF::Endianness streamEndianness) { if (buffer == nullptr or size == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (*size < 3) { return SerializeIF::STREAM_TOO_SHORT; } - cfdp::TlvTypes type = static_cast(**buffer); + auto type = static_cast(**buffer); if (type != getType()) { return cfdp::INVALID_TLV_TYPE; } @@ -114,10 +115,10 @@ class FilestoreTlvBase : public TlvIF { if (remainingLength == 0) { return SerializeIF::STREAM_TOO_SHORT; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } - bool requiresSecondFileName() const { + [[nodiscard]] bool requiresSecondFileName() const { using namespace cfdp; if (actionCode == FilestoreActionCode::RENAME_FILE or actionCode == FilestoreActionCode::APPEND_FILE or @@ -141,9 +142,9 @@ class FilestoreTlvBase : public TlvIF { #endif } - FilestoreActionCode getActionCode() const { return actionCode; } + [[nodiscard]] FilestoreActionCode getActionCode() const { return actionCode; } - void setActionCode(FilestoreActionCode actionCode) { this->actionCode = actionCode; } + void setActionCode(FilestoreActionCode actionCode_) { this->actionCode = actionCode_; } cfdp::Lv& getFirstFileName() { return firstFileName; } @@ -152,7 +153,7 @@ class FilestoreTlvBase : public TlvIF { size_t serSize = 0; uint8_t* valueStart = buffer + 2; ReturnValue_t result = this->serialize(&buffer, &serSize, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } tlv.setValue(valueStart, serSize - 2); @@ -160,11 +161,11 @@ class FilestoreTlvBase : public TlvIF { return result; } - size_t getSerializedSize() const override { return getLengthField() + 2; } + [[nodiscard]] size_t getSerializedSize() const override { return getLengthField() + 2; } protected: FilestoreActionCode actionCode = FilestoreActionCode::INVALID; - cfdp::Lv& firstFileName; + cfdp::StringLv& firstFileName; }; } // namespace cfdp diff --git a/src/fsfw/cfdp/tlv/FlowLabelTlv.cpp b/src/fsfw/cfdp/tlv/FlowLabelTlv.cpp index 938af9f4..5f225669 100644 --- a/src/fsfw/cfdp/tlv/FlowLabelTlv.cpp +++ b/src/fsfw/cfdp/tlv/FlowLabelTlv.cpp @@ -1,4 +1,4 @@ #include "FlowLabelTlv.h" FlowLabelTlv::FlowLabelTlv(uint8_t* value, size_t size) - : Tlv(cfdp::TlvTypes::FLOW_LABEL, value, size) {} + : Tlv(cfdp::TlvType::FLOW_LABEL, value, size) {} diff --git a/src/fsfw/cfdp/tlv/Lv.cpp b/src/fsfw/cfdp/tlv/Lv.cpp index 1bb16301..e7fa414a 100644 --- a/src/fsfw/cfdp/tlv/Lv.cpp +++ b/src/fsfw/cfdp/tlv/Lv.cpp @@ -6,6 +6,12 @@ cfdp::Lv::Lv(const uint8_t* value, size_t size) : value(value, size, true) { } } +cfdp::Lv::Lv(const std::vector& data) : value(data.data(), data.size(), true) { + if (!data.empty()) { + zeroLen = false; + } +} + cfdp::Lv::Lv() : value(static_cast(nullptr), 0, true) {} cfdp::Lv::Lv(const Lv& other) @@ -17,11 +23,11 @@ cfdp::Lv::Lv(const Lv& other) cfdp::Lv& cfdp::Lv::operator=(const Lv& other) { size_t otherSize = 0; - uint8_t* value = const_cast(other.getValue(&otherSize)); - if (value == nullptr or otherSize == 0) { + auto* otherVal = const_cast(other.getValue(&otherSize)); + if (otherVal == nullptr or otherSize == 0) { this->zeroLen = true; } - this->value.setBuffer(value, otherSize); + this->value.setConstBuffer(otherVal, otherSize); return *this; } @@ -31,13 +37,13 @@ ReturnValue_t cfdp::Lv::serialize(uint8_t** buffer, size_t* size, size_t maxSize return BUFFER_TOO_SHORT; } if (buffer == nullptr or size == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (zeroLen) { **buffer = 0; *size += 1; *buffer += 1; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } return value.serialize(buffer, size, maxSize, streamEndianness); } @@ -54,7 +60,7 @@ size_t cfdp::Lv::getSerializedSize() const { ReturnValue_t cfdp::Lv::deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { if (buffer == nullptr or size == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (*size < 1) { return SerializeIF::STREAM_TOO_SHORT; @@ -64,16 +70,16 @@ ReturnValue_t cfdp::Lv::deSerialize(const uint8_t** buffer, size_t* size, zeroLen = true; *buffer += 1; *size -= 1; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else if (*size < lengthField + 1) { return SerializeIF::STREAM_TOO_SHORT; } zeroLen = false; // Zero-copy implementation - value.setBuffer(const_cast(*buffer + 1), lengthField); + value.setConstBuffer(*buffer + 1, lengthField); *buffer += 1 + lengthField; *size -= 1 + lengthField; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } const uint8_t* cfdp::Lv::getValue(size_t* size) const { diff --git a/src/fsfw/cfdp/tlv/Lv.h b/src/fsfw/cfdp/tlv/Lv.h index 29764433..efabfdef 100644 --- a/src/fsfw/cfdp/tlv/Lv.h +++ b/src/fsfw/cfdp/tlv/Lv.h @@ -1,5 +1,7 @@ -#ifndef FSFW_SRC_FSFW_CFDP_LV_H_ -#define FSFW_SRC_FSFW_CFDP_LV_H_ +#ifndef FSFW_CFDP_LV_H_ +#define FSFW_CFDP_LV_H_ + +#include #include "fsfw/serialize/SerialBufferAdapter.h" @@ -12,18 +14,17 @@ namespace cfdp { */ class Lv : public SerializeIF { public: + explicit Lv(const std::vector& data); Lv(const uint8_t* value, size_t size); Lv(); - // Delete copy ctor and assingment ctor for now because this class contains a reference to - // data Lv(const Lv&); Lv& operator=(const Lv&); ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness) const override; - size_t getSerializedSize() const override; + [[nodiscard]] size_t getSerializedSize() const override; /** * @brief Deserialize a LV field from a raw buffer @@ -50,4 +51,4 @@ class Lv : public SerializeIF { } // namespace cfdp -#endif /* FSFW_SRC_FSFW_CFDP_LV_H_ */ +#endif /* FSFW_CFDP_LV_H_ */ diff --git a/src/fsfw/cfdp/tlv/MessageToUserTlv.cpp b/src/fsfw/cfdp/tlv/MessageToUserTlv.cpp index 9034552b..9a3e55ff 100644 --- a/src/fsfw/cfdp/tlv/MessageToUserTlv.cpp +++ b/src/fsfw/cfdp/tlv/MessageToUserTlv.cpp @@ -1,6 +1,9 @@ #include "MessageToUserTlv.h" -MessageToUserTlv::MessageToUserTlv(uint8_t *value, size_t size) - : Tlv(cfdp::TlvTypes::MSG_TO_USER, value, size) {} +MessageToUserTlv::MessageToUserTlv(uint8_t* value, size_t size) + : Tlv(cfdp::TlvType::MSG_TO_USER, value, size) {} MessageToUserTlv::MessageToUserTlv() : Tlv() {} + +MessageToUserTlv::MessageToUserTlv(const std::vector& data) + : Tlv(cfdp::TlvType::MSG_TO_USER, data.data(), data.size()) {} diff --git a/src/fsfw/cfdp/tlv/MessageToUserTlv.h b/src/fsfw/cfdp/tlv/MessageToUserTlv.h index 1d00bf31..e7f63ed2 100644 --- a/src/fsfw/cfdp/tlv/MessageToUserTlv.h +++ b/src/fsfw/cfdp/tlv/MessageToUserTlv.h @@ -1,12 +1,15 @@ #ifndef FSFW_SRC_FSFW_CFDP_TLV_MESSAGETOUSERTLV_H_ #define FSFW_SRC_FSFW_CFDP_TLV_MESSAGETOUSERTLV_H_ +#include + #include "Tlv.h" class MessageToUserTlv : public cfdp::Tlv { public: MessageToUserTlv(); MessageToUserTlv(uint8_t* value, size_t size); + explicit MessageToUserTlv(const std::vector& data); private: }; diff --git a/src/fsfw/cfdp/tlv/StringLv.cpp b/src/fsfw/cfdp/tlv/StringLv.cpp new file mode 100644 index 00000000..60c278a7 --- /dev/null +++ b/src/fsfw/cfdp/tlv/StringLv.cpp @@ -0,0 +1,9 @@ +#include "StringLv.h" + +cfdp::StringLv::StringLv(const std::string& fileName) + : Lv(reinterpret_cast(fileName.data()), fileName.size()) {} + +cfdp::StringLv::StringLv(const char* filename, size_t len) + : Lv(reinterpret_cast(filename), len) {} + +cfdp::StringLv::StringLv() : Lv() {} diff --git a/src/fsfw/cfdp/tlv/StringLv.h b/src/fsfw/cfdp/tlv/StringLv.h new file mode 100644 index 00000000..6c200b8b --- /dev/null +++ b/src/fsfw/cfdp/tlv/StringLv.h @@ -0,0 +1,22 @@ +#ifndef FSFW_CFDP_STRINGLV_H +#define FSFW_CFDP_STRINGLV_H + +#include + +#include "Lv.h" + +namespace cfdp { + +class StringLv : public Lv { + public: + StringLv(); + explicit StringLv(const std::string& fileName); + explicit StringLv(const char* filename, size_t len); + + // Delete the move constructor to avoid passing in a temporary + StringLv(const std::string&&) = delete; +}; + +} // namespace cfdp + +#endif // FSFW_CFDP_STRINGLV_H diff --git a/src/fsfw/cfdp/tlv/Tlv.cpp b/src/fsfw/cfdp/tlv/Tlv.cpp index f37ff8d5..c3fce612 100644 --- a/src/fsfw/cfdp/tlv/Tlv.cpp +++ b/src/fsfw/cfdp/tlv/Tlv.cpp @@ -1,6 +1,6 @@ #include "Tlv.h" -cfdp::Tlv::Tlv(TlvTypes type, const uint8_t *value, size_t size) +cfdp::Tlv::Tlv(TlvType type, const uint8_t *value, size_t size) : type(type), value(value, size, true) { if (size > 0) { zeroLen = false; @@ -12,12 +12,12 @@ cfdp::Tlv::Tlv() : value(static_cast(nullptr), 0, true) {} ReturnValue_t cfdp::Tlv::serialize(uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) const { if (buffer == nullptr or size == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (*size + 2 > maxSize) { return BUFFER_TOO_SHORT; } - if (type == TlvTypes::INVALID_TLV) { + if (type == TlvType::INVALID_TLV) { return INVALID_TLV_TYPE; } **buffer = type; @@ -28,10 +28,10 @@ ReturnValue_t cfdp::Tlv::serialize(uint8_t **buffer, size_t *size, size_t maxSiz **buffer = 0; *size += 1; *buffer += 1; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } if (value.getConstBuffer() == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } return value.serialize(buffer, size, maxSize, streamEndianness); } @@ -48,7 +48,7 @@ size_t cfdp::Tlv::getSerializedSize() const { ReturnValue_t cfdp::Tlv::deSerialize(const uint8_t **buffer, size_t *size, Endianness streamEndianness) { if (buffer == nullptr or size == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (*size < 2) { return STREAM_TOO_SHORT; @@ -59,7 +59,7 @@ ReturnValue_t cfdp::Tlv::deSerialize(const uint8_t **buffer, size_t *size, return INVALID_TLV_TYPE; } - type = static_cast(rawType); + type = static_cast(rawType); *buffer += 1; *size -= 1; @@ -68,22 +68,22 @@ ReturnValue_t cfdp::Tlv::deSerialize(const uint8_t **buffer, size_t *size, zeroLen = true; *buffer += 1; *size -= 1; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } if (lengthField + 1 > *size) { return SerializeIF::STREAM_TOO_SHORT; } zeroLen = false; // Zero-copy implementation - value.setBuffer(const_cast(*buffer + 1), lengthField); + value.setConstBuffer(*buffer + 1, lengthField); *buffer += 1 + lengthField; *size -= 1 + lengthField; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } const uint8_t *cfdp::Tlv::getValue() const { return value.getConstBuffer(); } -cfdp::TlvTypes cfdp::Tlv::getType() const { return type; } +cfdp::TlvType cfdp::Tlv::getType() const { return type; } bool cfdp::Tlv::checkType(uint8_t rawType) { if (rawType != 0x03 and rawType <= 6) { @@ -96,9 +96,9 @@ void cfdp::Tlv::setValue(uint8_t *value, size_t len) { if (len > 0) { zeroLen = false; } - this->value.setBuffer(value, len); + this->value.setConstBuffer(value, len); } uint8_t cfdp::Tlv::getLengthField() const { return this->value.getSerializedSize() - 1; } -void cfdp::Tlv::setType(TlvTypes type) { this->type = type; } +void cfdp::Tlv::setType(TlvType type) { this->type = type; } diff --git a/src/fsfw/cfdp/tlv/Tlv.h b/src/fsfw/cfdp/tlv/Tlv.h index a67c6dd1..786a3b79 100644 --- a/src/fsfw/cfdp/tlv/Tlv.h +++ b/src/fsfw/cfdp/tlv/Tlv.h @@ -13,7 +13,7 @@ namespace cfdp { */ class Tlv : public TlvIF { public: - Tlv(TlvTypes type, const uint8_t *value, size_t size); + Tlv(TlvType type, const uint8_t *value, size_t size); Tlv(); /** @@ -23,39 +23,39 @@ class Tlv : public TlvIF { * @param maxSize * @param streamEndianness * @return - * - RETURN_OK on success + * - returnvalue::OK on success * - INVALID_TLV_TYPE * - SerializeIF returncode on wrong serialization parameters */ - virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const override; + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override; - virtual size_t getSerializedSize() const override; + [[nodiscard]] size_t getSerializedSize() const override; /** * @brief Deserialize a LV field from a raw buffer. Zero-copy implementation * @param buffer Raw buffer including the size field * @param size * @param streamEndianness - * - RETURN_OK on success + * - returnvalue::OK on success * - INVALID_TLV_TYPE * - SerializeIF returncode on wrong deserialization parameters */ - virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, - Endianness streamEndianness) override; + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override; void setValue(uint8_t *value, size_t len); - const uint8_t *getValue() const; - void setType(TlvTypes type); - TlvTypes getType() const override; - uint8_t getLengthField() const override; + [[nodiscard]] const uint8_t *getValue() const; + void setType(TlvType type); + [[nodiscard]] TlvType getType() const override; + [[nodiscard]] uint8_t getLengthField() const override; private: bool checkType(uint8_t rawType); bool zeroLen = true; - TlvTypes type = TlvTypes::INVALID_TLV; + TlvType type = TlvType::INVALID_TLV; SerialBufferAdapter value; }; diff --git a/src/fsfw/cfdp/tlv/TlvIF.h b/src/fsfw/cfdp/tlv/TlvIF.h index 9a02b241..317d970a 100644 --- a/src/fsfw/cfdp/tlv/TlvIF.h +++ b/src/fsfw/cfdp/tlv/TlvIF.h @@ -8,7 +8,7 @@ class TlvIF : public SerializeIF { virtual ~TlvIF(){}; virtual uint8_t getLengthField() const = 0; - virtual cfdp::TlvTypes getType() const = 0; + virtual cfdp::TlvType getType() const = 0; }; #endif /* FSFW_SRC_FSFW_CFDP_TLVIF_H_ */ diff --git a/src/fsfw/container/ArrayList.h b/src/fsfw/container/ArrayList.h index 11f40039..92834558 100644 --- a/src/fsfw/container/ArrayList.h +++ b/src/fsfw/container/ArrayList.h @@ -1,9 +1,10 @@ #ifndef FSFW_CONTAINER_ARRAYLIST_H_ #define FSFW_CONTAINER_ARRAYLIST_H_ -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeIF.h" +#include "definitions.h" /** * @brief A List that stores its values in an array. @@ -19,9 +20,6 @@ class ArrayList { friend class SerialArrayListAdapter; public: - static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST; - static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01); - /** * This is the allocating constructor. * It allocates an array of the specified size. @@ -183,15 +181,15 @@ class ArrayList { * @param entry * @return * -@c FULL if the List is full - * -@c RETURN_OK else + * -@c returnvalue::OK else */ ReturnValue_t insert(T entry) { if (size >= maxSize_) { - return FULL; + return containers::LIST_FULL; } entries[size] = entry; ++size; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } /** diff --git a/src/fsfw/container/CMakeLists.txt b/src/fsfw/container/CMakeLists.txt index 13eced1d..52087ff0 100644 --- a/src/fsfw/container/CMakeLists.txt +++ b/src/fsfw/container/CMakeLists.txt @@ -1,5 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - SharedRingBuffer.cpp - SimpleRingBuffer.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE SharedRingBuffer.cpp + SimpleRingBuffer.cpp) diff --git a/src/fsfw/container/DynamicFIFO.h b/src/fsfw/container/DynamicFIFO.h index 96f55938..5d1d46e7 100644 --- a/src/fsfw/container/DynamicFIFO.h +++ b/src/fsfw/container/DynamicFIFO.h @@ -18,7 +18,8 @@ template class DynamicFIFO : public FIFOBase { public: - DynamicFIFO(size_t maxCapacity) : FIFOBase(nullptr, maxCapacity), fifoVector(maxCapacity) { + explicit DynamicFIFO(size_t maxCapacity) + : FIFOBase(nullptr, maxCapacity), fifoVector(maxCapacity) { // trying to pass the pointer of the uninitialized vector // to the FIFOBase constructor directly lead to a super evil bug. // So we do it like this now. diff --git a/src/fsfw/container/FIFOBase.h b/src/fsfw/container/FIFOBase.h index 25c75515..b215dae4 100644 --- a/src/fsfw/container/FIFOBase.h +++ b/src/fsfw/container/FIFOBase.h @@ -4,7 +4,7 @@ #include #include -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" template class FIFOBase { @@ -15,29 +15,29 @@ class FIFOBase { /** Default ctor, takes pointer to first entry of underlying container * and maximum capacity */ - FIFOBase(T* values, const size_t maxCapacity); + FIFOBase(T* values, size_t maxCapacity); /** * Insert value into FIFO * @param value - * @return RETURN_OK on success, FULL if full + * @return returnvalue::OK on success, FULL if full */ ReturnValue_t insert(T value); /** * Retrieve item from FIFO. This removes the item from the FIFO. * @param value Must point to a valid T - * @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed + * @return returnvalue::OK on success, EMPTY if empty and FAILED if nullptr check failed */ ReturnValue_t retrieve(T* value); /** * Retrieve item from FIFO without removing it from FIFO. * @param value Must point to a valid T - * @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed + * @return returnvalue::OK on success, EMPTY if empty and FAILED if nullptr check failed */ ReturnValue_t peek(T* value); /** * Remove item from FIFO. - * @return RETURN_OK on success, EMPTY if empty + * @return returnvalue::OK on success, EMPTY if empty */ ReturnValue_t pop(); @@ -60,7 +60,7 @@ class FIFOBase { * Get maximal capacity of fifo * @return size_t with max capacity of this fifo */ - size_t getMaxCapacity() const; + [[nodiscard]] size_t getMaxCapacity() const; protected: void setContainer(T* data); diff --git a/src/fsfw/container/FIFOBase.tpp b/src/fsfw/container/FIFOBase.tpp index 2e6a3829..63727869 100644 --- a/src/fsfw/container/FIFOBase.tpp +++ b/src/fsfw/container/FIFOBase.tpp @@ -5,89 +5,88 @@ #error Include FIFOBase.h before FIFOBase.tpp! #endif -template -inline FIFOBase::FIFOBase(T* values, const size_t maxCapacity): - maxCapacity(maxCapacity), values(values){}; +template +inline FIFOBase::FIFOBase(T* values, const size_t maxCapacity) + : maxCapacity(maxCapacity), values(values){}; -template +template inline ReturnValue_t FIFOBase::insert(T value) { - if (full()) { - return FULL; - } else { - values[writeIndex] = value; - writeIndex = next(writeIndex); - ++currentSize; - return HasReturnvaluesIF::RETURN_OK; - } + if (full()) { + return FULL; + } else { + values[writeIndex] = value; + writeIndex = next(writeIndex); + ++currentSize; + return returnvalue::OK; + } }; -template +template inline ReturnValue_t FIFOBase::retrieve(T* value) { - if (empty()) { - return EMPTY; - } else { - if (value == nullptr){ - return HasReturnvaluesIF::RETURN_FAILED; - } - *value = values[readIndex]; - readIndex = next(readIndex); - --currentSize; - return HasReturnvaluesIF::RETURN_OK; + if (empty()) { + return EMPTY; + } else { + if (value == nullptr) { + return returnvalue::FAILED; } + *value = values[readIndex]; + readIndex = next(readIndex); + --currentSize; + return returnvalue::OK; + } }; -template +template inline ReturnValue_t FIFOBase::peek(T* value) { - if(empty()) { - return EMPTY; - } else { - if (value == nullptr){ - return HasReturnvaluesIF::RETURN_FAILED; - } - *value = values[readIndex]; - return HasReturnvaluesIF::RETURN_OK; + if (empty()) { + return EMPTY; + } else { + if (value == nullptr) { + return returnvalue::FAILED; } + *value = values[readIndex]; + return returnvalue::OK; + } }; -template +template inline ReturnValue_t FIFOBase::pop() { - T value; - return this->retrieve(&value); + T value; + return this->retrieve(&value); }; -template +template inline bool FIFOBase::empty() { - return (currentSize == 0); + return (currentSize == 0); }; -template +template inline bool FIFOBase::full() { - return (currentSize == maxCapacity); + return (currentSize == maxCapacity); } -template +template inline size_t FIFOBase::size() { - return currentSize; + return currentSize; } -template +template inline size_t FIFOBase::next(size_t current) { - ++current; - if (current == maxCapacity) { - current = 0; - } - return current; + ++current; + if (current == maxCapacity) { + current = 0; + } + return current; } -template +template inline size_t FIFOBase::getMaxCapacity() const { - return maxCapacity; + return maxCapacity; } - -template -inline void FIFOBase::setContainer(T *data) { - this->values = data; +template +inline void FIFOBase::setContainer(T* data) { + this->values = data; } #endif diff --git a/src/fsfw/container/FixedArrayList.h b/src/fsfw/container/FixedArrayList.h index c09a421e..dde8eb16 100644 --- a/src/fsfw/container/FixedArrayList.h +++ b/src/fsfw/container/FixedArrayList.h @@ -2,6 +2,7 @@ #define FIXEDARRAYLIST_H_ #include +#include #include "ArrayList.h" /** @@ -9,10 +10,10 @@ */ template class FixedArrayList : public ArrayList { -#if !defined(_MSC_VER) - static_assert(MAX_SIZE <= (std::pow(2, sizeof(count_t) * 8) - 1), + static_assert(MAX_SIZE <= std::numeric_limits::max(), "count_t is not large enough to hold MAX_SIZE"); -#endif + static_assert(MAX_SIZE > 0, "MAX_SIZE is 0"); + private: T data[MAX_SIZE]; @@ -20,15 +21,19 @@ class FixedArrayList : public ArrayList { FixedArrayList() : ArrayList(data, MAX_SIZE) {} FixedArrayList(const FixedArrayList& other) : ArrayList(data, MAX_SIZE) { - memcpy(this->data, other.data, sizeof(this->data)); this->entries = data; this->size = other.size; + for (size_t idx = 0; idx < this->size; idx++) { + data[idx] = other.data[idx]; + } } FixedArrayList& operator=(FixedArrayList other) { - memcpy(this->data, other.data, sizeof(this->data)); this->entries = data; this->size = other.size; + for (size_t idx = 0; idx < this->size; idx++) { + data[idx] = other.data[idx]; + } return *this; } diff --git a/src/fsfw/container/FixedMap.h b/src/fsfw/container/FixedMap.h index 48822cd5..01d2a6ea 100644 --- a/src/fsfw/container/FixedMap.h +++ b/src/fsfw/container/FixedMap.h @@ -4,8 +4,8 @@ #include #include -#include "../returnvalues/HasReturnvaluesIF.h" #include "ArrayList.h" +#include "definitions.h" /** * @brief Map implementation for maps with a pre-defined size. @@ -24,11 +24,6 @@ class FixedMap : public SerializeIF { "derived class from SerializeIF to be serialize-able"); public: - static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP; - static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); - static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02); - static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03); - private: static const key_t EMPTY_SLOT = -1; ArrayList, uint32_t> theMap; @@ -75,11 +70,11 @@ class FixedMap : public SerializeIF { uint32_t size() const { return _size; } ReturnValue_t insert(key_t key, T value, Iterator* storedValue = nullptr) { - if (exists(key) == HasReturnvaluesIF::RETURN_OK) { - return KEY_ALREADY_EXISTS; + if (exists(key) == returnvalue::OK) { + return containers::KEY_ALREADY_EXISTS; } if (_size == theMap.maxSize()) { - return MAP_FULL; + return containers::MAP_FULL; } theMap[_size].first = key; theMap[_size].second = value; @@ -87,15 +82,15 @@ class FixedMap : public SerializeIF { *storedValue = Iterator(&theMap[_size]); } ++_size; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t insert(std::pair pair) { return insert(pair.first, pair.second); } ReturnValue_t exists(key_t key) const { - ReturnValue_t result = KEY_DOES_NOT_EXIST; + ReturnValue_t result = containers::KEY_DOES_NOT_EXIST; if (findIndex(key) < _size) { - result = HasReturnvaluesIF::RETURN_OK; + result = returnvalue::OK; } return result; } @@ -103,29 +98,29 @@ class FixedMap : public SerializeIF { ReturnValue_t erase(Iterator* iter) { uint32_t i; if ((i = findIndex((*iter).value->first)) >= _size) { - return KEY_DOES_NOT_EXIST; + return containers::KEY_DOES_NOT_EXIST; } theMap[i] = theMap[_size - 1]; --_size; --((*iter).value); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t erase(key_t key) { uint32_t i; if ((i = findIndex(key)) >= _size) { - return KEY_DOES_NOT_EXIST; + return containers::KEY_DOES_NOT_EXIST; } theMap[i] = theMap[_size - 1]; --_size; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } T* findValue(key_t key) const { return &theMap[findIndex(key)].second; } Iterator find(key_t key) const { ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return end(); } return Iterator(&theMap[findIndex(key)]); @@ -133,11 +128,11 @@ class FixedMap : public SerializeIF { ReturnValue_t find(key_t key, T** value) const { ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } *value = &theMap[findIndex(key)].second; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } bool empty() { @@ -160,12 +155,12 @@ class FixedMap : public SerializeIF { uint32_t maxSize() const { return theMap.maxSize(); } - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const { + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override { ReturnValue_t result = SerializeAdapter::serialize(&this->_size, buffer, size, maxSize, streamEndianness); uint32_t i = 0; - while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) { + while ((result == returnvalue::OK) && (i < this->_size)) { result = SerializeAdapter::serialize(&theMap[i].first, buffer, size, maxSize, streamEndianness); result = @@ -175,7 +170,7 @@ class FixedMap : public SerializeIF { return result; } - virtual size_t getSerializedSize() const { + size_t getSerializedSize() const override { uint32_t printSize = sizeof(_size); uint32_t i = 0; @@ -187,15 +182,15 @@ class FixedMap : public SerializeIF { return printSize; } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) { + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override { ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size, buffer, size, streamEndianness); if (this->_size > theMap.maxSize()) { return SerializeIF::TOO_MANY_ELEMENTS; } uint32_t i = 0; - while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) { + while ((result == returnvalue::OK) && (i < this->_size)) { result = SerializeAdapter::deSerialize(&theMap[i].first, buffer, size, streamEndianness); result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size, streamEndianness); ++i; diff --git a/src/fsfw/container/FixedOrderedMultimap.h b/src/fsfw/container/FixedOrderedMultimap.h index 3ef8f8f1..73b010ed 100644 --- a/src/fsfw/container/FixedOrderedMultimap.h +++ b/src/fsfw/container/FixedOrderedMultimap.h @@ -100,7 +100,7 @@ class FixedOrderedMultimap { * @param[in] value Value of the new element * @param[in/out] (optional) storedValue On success this points to the new value, otherwise a * nullptr - * @return RETURN_OK if insert was successful, MAP_FULL if no space is available + * @return returnvalue::OK if insert was successful, MAP_FULL if no space is available */ ReturnValue_t insert(key_t key, T value, Iterator* storedValue = nullptr); @@ -108,14 +108,14 @@ class FixedOrderedMultimap { * Used to insert new pair instead of single values * * @param pair Pair to be inserted - * @return RETURN_OK if insert was successful, MAP_FULL if no space is available + * @return returnvalue::OK if insert was successful, MAP_FULL if no space is available */ ReturnValue_t insert(std::pair pair); /*** * Can be used to check if a certain key is in the map * @param key Key to be checked - * @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise + * @return returnvalue::OK if the key exists KEY_DOES_NOT_EXIST otherwise */ ReturnValue_t exists(key_t key) const; @@ -127,14 +127,14 @@ class FixedOrderedMultimap { * * @warning The iterator needs to be valid and dereferenceable * @param[in/out] iter Pointer to iterator to the element that needs to be ereased - * @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this + * @return returnvalue::OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this */ ReturnValue_t erase(Iterator* iter); /*** * Used to erase by key * @param key Key to be erased - * @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this + * @return returnvalue::OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this */ ReturnValue_t erase(key_t key); @@ -148,7 +148,7 @@ class FixedOrderedMultimap { */ Iterator find(key_t key) const { ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return end(); } return Iterator(&theMap[findFirstIndex(key)]); @@ -160,7 +160,7 @@ class FixedOrderedMultimap { * * @param key Key to search for * @param value Found value - * @return RETURN_OK if it points to the value, + * @return returnvalue::OK if it points to the value, * KEY_DOES_NOT_EXIST if the key is not in the map */ ReturnValue_t find(key_t key, T** value) const; diff --git a/src/fsfw/container/FixedOrderedMultimap.tpp b/src/fsfw/container/FixedOrderedMultimap.tpp index 294a161f..cfdb5331 100644 --- a/src/fsfw/container/FixedOrderedMultimap.tpp +++ b/src/fsfw/container/FixedOrderedMultimap.tpp @@ -1,109 +1,109 @@ #ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ #define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ - -template -inline ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue) { - if (_size == theMap.maxSize()) { - return MAP_FULL; - } - size_t position = findNicePlace(key); - memmove(static_cast(&theMap[position + 1]),static_cast(&theMap[position]), - (_size - position) * sizeof(std::pair)); - theMap[position].first = key; - theMap[position].second = value; - ++_size; - if (storedValue != nullptr) { - *storedValue = Iterator(&theMap[position]); - } - return HasReturnvaluesIF::RETURN_OK; +template +inline ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, + Iterator *storedValue) { + if (_size == theMap.maxSize()) { + return MAP_FULL; + } + size_t position = findNicePlace(key); + memmove(static_cast(&theMap[position + 1]), static_cast(&theMap[position]), + (_size - position) * sizeof(std::pair)); + theMap[position].first = key; + theMap[position].second = value; + ++_size; + if (storedValue != nullptr) { + *storedValue = Iterator(&theMap[position]); + } + return returnvalue::OK; } -template +template inline ReturnValue_t FixedOrderedMultimap::insert(std::pair pair) { - return insert(pair.first, pair.second); + return insert(pair.first, pair.second); } -template +template inline ReturnValue_t FixedOrderedMultimap::exists(key_t key) const { - ReturnValue_t result = KEY_DOES_NOT_EXIST; - if (findFirstIndex(key) < _size) { - result = HasReturnvaluesIF::RETURN_OK; - } - return result; + ReturnValue_t result = KEY_DOES_NOT_EXIST; + if (findFirstIndex(key) < _size) { + result = returnvalue::OK; + } + return result; } -template +template inline ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) { - size_t i; - if ((i = findFirstIndex((*iter).value->first)) >= _size) { - return KEY_DOES_NOT_EXIST; - } - removeFromPosition(i); - if (*iter != begin()) { - (*iter)--; - } else { - *iter = begin(); - } - return HasReturnvaluesIF::RETURN_OK; + size_t i; + if ((i = findFirstIndex((*iter).value->first)) >= _size) { + return KEY_DOES_NOT_EXIST; + } + removeFromPosition(i); + if (*iter != begin()) { + (*iter)--; + } else { + *iter = begin(); + } + return returnvalue::OK; } -template +template inline ReturnValue_t FixedOrderedMultimap::erase(key_t key) { - size_t i; - if ((i = findFirstIndex(key)) >= _size) { - return KEY_DOES_NOT_EXIST; - } - do { - removeFromPosition(i); - i = findFirstIndex(key, i); - } while (i < _size); - return HasReturnvaluesIF::RETURN_OK; + size_t i; + if ((i = findFirstIndex(key)) >= _size) { + return KEY_DOES_NOT_EXIST; + } + do { + removeFromPosition(i); + i = findFirstIndex(key, i); + } while (i < _size); + return returnvalue::OK; } -template +template inline ReturnValue_t FixedOrderedMultimap::find(key_t key, T **value) const { - ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - *value = &theMap[findFirstIndex(key)].second; - return HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = exists(key); + if (result != returnvalue::OK) { + return result; + } + *value = &theMap[findFirstIndex(key)].second; + return returnvalue::OK; } -template -inline size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt) const { - if (startAt >= _size) { - return startAt + 1; +template +inline size_t FixedOrderedMultimap::findFirstIndex(key_t key, + size_t startAt) const { + if (startAt >= _size) { + return startAt + 1; + } + size_t i = startAt; + for (i = startAt; i < _size; ++i) { + if (theMap[i].first == key) { + return i; } - size_t i = startAt; - for (i = startAt; i < _size; ++i) { - if (theMap[i].first == key) { - return i; - } - } - return i; + } + return i; } -template +template inline size_t FixedOrderedMultimap::findNicePlace(key_t key) const { - size_t i = 0; - for (i = 0; i < _size; ++i) { - if (myComp(key, theMap[i].first)) { - return i; - } + size_t i = 0; + for (i = 0; i < _size; ++i) { + if (myComp(key, theMap[i].first)) { + return i; } - return i; + } + return i; } -template +template inline void FixedOrderedMultimap::removeFromPosition(size_t position) { - if (_size <= position) { - return; - } - memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), - (_size - position - 1) * sizeof(std::pair)); - --_size; + if (_size <= position) { + return; + } + memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), + (_size - position - 1) * sizeof(std::pair)); + --_size; } - #endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ */ diff --git a/src/fsfw/container/HybridIterator.h b/src/fsfw/container/HybridIterator.h index e8b24a3d..ad000ec2 100644 --- a/src/fsfw/container/HybridIterator.h +++ b/src/fsfw/container/HybridIterator.h @@ -10,16 +10,23 @@ class HybridIterator : public LinkedElement::Iterator, public ArrayList::Iterator *iter) - : LinkedElement::Iterator(*iter), value(iter->value), linked(true) {} + : LinkedElement::Iterator(*iter), linked(true) { + if (iter != nullptr) { + value = iter->value; + } + } - HybridIterator(LinkedElement *start) - : LinkedElement::Iterator(start), value(start->value), linked(true) {} + HybridIterator(LinkedElement *start) : LinkedElement::Iterator(start), linked(true) { + if (start != nullptr) { + value = start->value; + } + } HybridIterator(typename ArrayList::Iterator start, typename ArrayList::Iterator end) : ArrayList::Iterator(start), value(start.value), linked(false), end(end.value) { if (value == this->end) { - value = NULL; + value = nullptr; } } diff --git a/src/fsfw/container/IndexedRingMemoryArray.h b/src/fsfw/container/IndexedRingMemoryArray.h index b76e7d56..127ed5d7 100644 --- a/src/fsfw/container/IndexedRingMemoryArray.h +++ b/src/fsfw/container/IndexedRingMemoryArray.h @@ -4,7 +4,7 @@ #include #include "../globalfunctions/CRC.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "../serialize/SerialArrayListAdapter.h" #include "../serviceinterface/ServiceInterfaceStream.h" #include "ArrayList.h" @@ -52,15 +52,15 @@ class Index : public SerializeIF { Endianness streamEndianness) const { ReturnValue_t result = SerializeAdapter::serialize(&blockStartAddress, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = indexType.serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&this->size, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = @@ -71,19 +71,19 @@ class Index : public SerializeIF { ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::deSerialize(&blockStartAddress, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = indexType.deSerialize(buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::deSerialize(&this->size, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::deSerialize(&this->storedPackets, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return result; @@ -449,13 +449,13 @@ class IndexedRingMemoryArray : public SerializeIF, public ArrayList, ui // Check Next Block if (!isNextBlockWritable()) { // The Index is full and does not overwrite old - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } // Next block can be written, update Metadata currentWriteBlock = getNextWrite(); currentWriteBlock->setSize(0); currentWriteBlock->setStoredPackets(0); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } /** @@ -475,21 +475,21 @@ class IndexedRingMemoryArray : public SerializeIF, public ArrayList, ui additionalInfo->serialize(buffer, size, maxSize, streamEndianness); } ReturnValue_t result = currentWriteBlock->serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&this->size, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } uint32_t i = 0; - while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->size)) { + while ((result == returnvalue::OK) && (i < this->size)) { result = SerializeAdapter::serialize(&this->entries[i], buffer, size, maxSize, streamEndianness); ++i; } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } uint16_t crc = Calculate_CRC(crcBuffer, (*size - oldSize)); @@ -523,44 +523,44 @@ class IndexedRingMemoryArray : public SerializeIF, public ArrayList, ui */ ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; if (additionalInfo != NULL) { result = additionalInfo->deSerialize(buffer, size, streamEndianness); } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } Index tempIndex; result = tempIndex.deSerialize(buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } uint32_t tempSize = 0; result = SerializeAdapter::deSerialize(&tempSize, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (this->size != tempSize) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } uint32_t i = 0; - while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->size)) { + while ((result == returnvalue::OK) && (i < this->size)) { result = SerializeAdapter::deSerialize(&this->entries[i], buffer, size, streamEndianness); ++i; } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } typename IndexedRingMemoryArray::Iterator cmp(&tempIndex); for (typename IndexedRingMemoryArray::Iterator it = this->begin(); it != this->end(); ++it) { if (*(cmp.value) == *(it.value)) { currentWriteBlock = it; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } } // Reached if current write block iterator is not found - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } uint32_t getIndexAddress() const { return indexAddress; } diff --git a/src/fsfw/container/PlacementFactory.h b/src/fsfw/container/PlacementFactory.h index 936be59d..668e71b8 100644 --- a/src/fsfw/container/PlacementFactory.h +++ b/src/fsfw/container/PlacementFactory.h @@ -40,7 +40,7 @@ class PlacementFactory { store_address_t tempId; uint8_t* pData = nullptr; ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T), &pData); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return nullptr; } T* temp = new (pData) T(std::forward(args)...); @@ -51,12 +51,12 @@ class PlacementFactory { * This must be called by the user. * * @param thisElement Element to be destroyed - * @return RETURN_OK if the element was destroyed, different errors on failure + * @return returnvalue::OK if the element was destroyed, different errors on failure */ template ReturnValue_t destroy(T* thisElement) { if (thisElement == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } // Need to call destructor first, in case something was allocated by the object (shouldn't do // that, however). diff --git a/src/fsfw/container/RingBufferBase.h b/src/fsfw/container/RingBufferBase.h index 98207698..e86f0ee1 100644 --- a/src/fsfw/container/RingBufferBase.h +++ b/src/fsfw/container/RingBufferBase.h @@ -3,7 +3,7 @@ #include -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" template class RingBufferBase { @@ -58,18 +58,18 @@ class RingBufferBase { ReturnValue_t readData(uint32_t amount, uint8_t n = 0) { if (getAvailableReadData(n) >= amount) { incrementRead(amount, n); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } ReturnValue_t writeData(uint32_t amount) { if (availableWriteSpace() >= amount or overwriteOld) { incrementWrite(amount); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } diff --git a/src/fsfw/container/SimpleRingBuffer.cpp b/src/fsfw/container/SimpleRingBuffer.cpp index bcf3cf20..a006df46 100644 --- a/src/fsfw/container/SimpleRingBuffer.cpp +++ b/src/fsfw/container/SimpleRingBuffer.cpp @@ -2,6 +2,9 @@ #include +#include "fsfw/FSFW.h" +#include "fsfw/serviceinterface.h" + SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld, size_t maxExcessBytes) : RingBufferBase<>(0, size, overwriteOld), maxExcessBytes(maxExcessBytes) { if (maxExcessBytes > size) { @@ -29,14 +32,14 @@ ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t** writePointer, size_t am size_t amountTillWrap = writeTillWrap(); if (amountTillWrap < amount) { if ((amount - amountTillWrap + excessBytes) > maxExcessBytes) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } excessBytes = amount - amountTillWrap; } *writePointer = &buffer[write]; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -48,6 +51,19 @@ void SimpleRingBuffer::confirmBytesWritten(size_t amount) { } ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, size_t amount) { + if (data == nullptr) { + return returnvalue::FAILED; + } + if (amount > getMaxSize()) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "SimpleRingBuffer::writeData: Amount of data too large" << std::endl; +#else + sif::printError("SimpleRingBuffer::writeData: Amount of data too large\n"); +#endif +#endif + return returnvalue::FAILED; + } if (availableWriteSpace() >= amount or overwriteOld) { size_t amountTillWrap = writeTillWrap(); if (amountTillWrap >= amount) { @@ -58,9 +74,9 @@ ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, size_t amount) { memcpy(buffer, data + amountTillWrap, amount - amountTillWrap); } incrementWrite(amount); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -73,7 +89,7 @@ ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount, bool incr // more data available than amount specified. amount = availableData; } else { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } if (trueAmount != nullptr) { @@ -89,7 +105,7 @@ ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount, bool incr if (incrementReadPtr) { deleteData(amount, readRemaining); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } size_t SimpleRingBuffer::getExcessBytes() const { return excessBytes; } @@ -108,12 +124,12 @@ ReturnValue_t SimpleRingBuffer::deleteData(size_t amount, bool deleteRemaining, if (deleteRemaining) { amount = availableData; } else { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } if (trueAmount != nullptr) { *trueAmount = amount; } incrementRead(amount, READ_PTR); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/src/fsfw/container/SimpleRingBuffer.h b/src/fsfw/container/SimpleRingBuffer.h index b9762451..a9892c0c 100644 --- a/src/fsfw/container/SimpleRingBuffer.h +++ b/src/fsfw/container/SimpleRingBuffer.h @@ -47,8 +47,8 @@ class SimpleRingBuffer : public RingBufferBase<> { * Write to circular buffer and increment write pointer by amount. * @param data * @param amount - * @return -@c RETURN_OK if write operation was successful - * -@c RETURN_FAILED if + * @return -@c returnvalue::OK if write operation was successful + * -@c returnvalue::FAILED if */ ReturnValue_t writeData(const uint8_t* data, size_t amount); @@ -95,8 +95,8 @@ class SimpleRingBuffer : public RingBufferBase<> { * If readRemaining was set to true, the true amount read will be assigned * to the passed value. * @return - * - @c RETURN_OK if data was read successfully - * - @c RETURN_FAILED if not enough data was available and readRemaining + * - @c returnvalue::OK if data was read successfully + * - @c returnvalue::FAILED if not enough data was available and readRemaining * was set to false. */ ReturnValue_t readData(uint8_t* data, size_t amount, bool incrementReadPtr = false, diff --git a/src/fsfw/container/definitions.h b/src/fsfw/container/definitions.h new file mode 100644 index 00000000..b50ea45d --- /dev/null +++ b/src/fsfw/container/definitions.h @@ -0,0 +1,14 @@ +#ifndef FSFW_CONTAINER_DEFINITIONS_H_ +#define FSFW_CONTAINER_DEFINITIONS_H_ + +#include "fsfw/retval.h" + +namespace containers { +static const ReturnValue_t KEY_ALREADY_EXISTS = returnvalue::makeCode(CLASS_ID::FIXED_MAP, 0x01); +static const ReturnValue_t MAP_FULL = returnvalue::makeCode(CLASS_ID::FIXED_MAP, 0x02); +static const ReturnValue_t KEY_DOES_NOT_EXIST = returnvalue::makeCode(CLASS_ID::FIXED_MAP, 0x03); + +static const ReturnValue_t LIST_FULL = returnvalue::makeCode(CLASS_ID::ARRAY_LIST, 0x01); +} // namespace containers + +#endif /* FSFW_CONTAINER_DEFINITIONS_H_ */ diff --git a/src/fsfw/controller/CMakeLists.txt b/src/fsfw/controller/CMakeLists.txt index 550acfcd..c8c000d8 100644 --- a/src/fsfw/controller/CMakeLists.txt +++ b/src/fsfw/controller/CMakeLists.txt @@ -1,4 +1,2 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - ControllerBase.cpp - ExtendedControllerBase.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE ControllerBase.cpp + ExtendedControllerBase.cpp) diff --git a/src/fsfw/controller/ControllerBase.cpp b/src/fsfw/controller/ControllerBase.cpp index 953dacb4..a9d19ef2 100644 --- a/src/fsfw/controller/ControllerBase.cpp +++ b/src/fsfw/controller/ControllerBase.cpp @@ -20,15 +20,15 @@ ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue ReturnValue_t ControllerBase::initialize() { ReturnValue_t result = SystemObject::initialize(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } MessageQueueId_t parentQueue = 0; if (parentId != objects::NO_OBJECT) { - SubsystemBase* parent = ObjectManager::instance()->get(parentId); + auto* parent = ObjectManager::instance()->get(parentId); if (parent == nullptr) { - return RETURN_FAILED; + return returnvalue::FAILED; } parentQueue = parent->getCommandQueue(); @@ -36,36 +36,36 @@ ReturnValue_t ControllerBase::initialize() { } result = healthHelper.initialize(parentQueue); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = modeHelper.initialize(parentQueue); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } - return RETURN_OK; + return returnvalue::OK; } MessageQueueId_t ControllerBase::getCommandQueue() const { return commandQueue->getId(); } void ControllerBase::handleQueue() { CommandMessage command; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - for (result = commandQueue->receiveMessage(&command); result == RETURN_OK; + ReturnValue_t result; + for (result = commandQueue->receiveMessage(&command); result == returnvalue::OK; result = commandQueue->receiveMessage(&command)) { result = modeHelper.handleModeCommand(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { continue; } result = healthHelper.handleHealthCommand(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { continue; } result = handleCommandMessage(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { continue; } command.setToUnknownCommand(); @@ -73,20 +73,20 @@ void ControllerBase::handleQueue() { } } -void ControllerBase::startTransition(Mode_t mode, Submode_t submode) { +void ControllerBase::startTransition(Mode_t mode_, Submode_t submode_) { changeHK(this->mode, this->submode, false); triggerEvent(CHANGING_MODE, mode, submode); - this->mode = mode; - this->submode = submode; + mode = mode_; + submode = submode_; modeHelper.modeChanged(mode, submode); modeChanged(mode, submode); announceMode(false); changeHK(this->mode, this->submode, true); } -void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) { - *mode = this->mode; - *submode = this->submode; +void ControllerBase::getMode(Mode_t* mode_, Submode_t* submode_) { + *mode_ = this->mode; + *submode_ = this->submode; } void ControllerBase::setToExternalControl() { healthHelper.setHealth(EXTERNAL_CONTROL); } @@ -96,17 +96,17 @@ void ControllerBase::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode ReturnValue_t ControllerBase::performOperation(uint8_t opCode) { handleQueue(); performControlOperation(); - return RETURN_OK; + return returnvalue::OK; } -void ControllerBase::modeChanged(Mode_t mode, Submode_t submode) { return; } +void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {} ReturnValue_t ControllerBase::setHealth(HealthState health) { switch (health) { case HEALTHY: case EXTERNAL_CONTROL: healthHelper.setHealth(health); - return RETURN_OK; + return returnvalue::OK; default: return INVALID_HEALTH_STATE; } @@ -115,6 +115,6 @@ ReturnValue_t ControllerBase::setHealth(HealthState health) { HasHealthIF::HealthState ControllerBase::getHealth() { return healthHelper.getHealth(); } void ControllerBase::setTaskIF(PeriodicTaskIF* task_) { executingTask = task_; } -void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {} +void ControllerBase::changeHK(Mode_t mode_, Submode_t submode_, bool enable) {} -ReturnValue_t ControllerBase::initializeAfterTaskCreation() { return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t ControllerBase::initializeAfterTaskCreation() { return returnvalue::OK; } diff --git a/src/fsfw/controller/ControllerBase.h b/src/fsfw/controller/ControllerBase.h index 7032f817..56c28585 100644 --- a/src/fsfw/controller/ControllerBase.h +++ b/src/fsfw/controller/ControllerBase.h @@ -18,27 +18,26 @@ class ControllerBase : public HasModesIF, public HasHealthIF, public ExecutableObjectIF, - public SystemObject, - public HasReturnvaluesIF { + public SystemObject { public: static const Mode_t MODE_NORMAL = 2; ControllerBase(object_id_t setObjectId, object_id_t parentId, size_t commandQueueDepth = 3); - virtual ~ControllerBase(); + ~ControllerBase() override; /** SystemObject override */ - virtual ReturnValue_t initialize() override; + ReturnValue_t initialize() override; - virtual MessageQueueId_t getCommandQueue() const override; + [[nodiscard]] MessageQueueId_t getCommandQueue() const override; /** HasHealthIF overrides */ - virtual ReturnValue_t setHealth(HealthState health) override; - virtual HasHealthIF::HealthState getHealth() override; + ReturnValue_t setHealth(HealthState health) override; + HasHealthIF::HealthState getHealth() override; /** ExecutableObjectIF overrides */ - virtual ReturnValue_t performOperation(uint8_t opCode) override; - virtual void setTaskIF(PeriodicTaskIF *task) override; - virtual ReturnValue_t initializeAfterTaskCreation() override; + ReturnValue_t performOperation(uint8_t opCode) override; + void setTaskIF(PeriodicTaskIF *task) override; + ReturnValue_t initializeAfterTaskCreation() override; protected: /** @@ -54,8 +53,8 @@ class ControllerBase : public HasModesIF, */ virtual void performControlOperation() = 0; - virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, - uint32_t *msToReachTheMode) = 0; + ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, + uint32_t *msToReachTheMode) override = 0; const object_id_t parentId; @@ -80,10 +79,10 @@ class ControllerBase : public HasModesIF, /** Mode helpers */ virtual void modeChanged(Mode_t mode, Submode_t submode); - virtual void startTransition(Mode_t mode, Submode_t submode); - virtual void getMode(Mode_t *mode, Submode_t *submode); - virtual void setToExternalControl(); - virtual void announceMode(bool recursive); + void startTransition(Mode_t mode, Submode_t submode) override; + void getMode(Mode_t *mode, Submode_t *submode) override; + void setToExternalControl() override; + void announceMode(bool recursive) override; /** HK helpers */ virtual void changeHK(Mode_t mode, Submode_t submode, bool enable); }; diff --git a/src/fsfw/controller/ExtendedControllerBase.cpp b/src/fsfw/controller/ExtendedControllerBase.cpp index 0dfd9dc7..4d5c90c8 100644 --- a/src/fsfw/controller/ExtendedControllerBase.cpp +++ b/src/fsfw/controller/ExtendedControllerBase.cpp @@ -6,13 +6,13 @@ ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, object_id_t poolManager(this, commandQueue), actionHelper(this, commandQueue) {} -ExtendedControllerBase::~ExtendedControllerBase() {} +ExtendedControllerBase::~ExtendedControllerBase() = default; ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t *data, size_t size) { /* Needs to be overriden and implemented by child class. */ - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } object_id_t ExtendedControllerBase::getObjectId() const { return SystemObject::getObjectId(); } @@ -23,7 +23,7 @@ uint32_t ExtendedControllerBase::getPeriodicOperationFrequency() const { ReturnValue_t ExtendedControllerBase::handleCommandMessage(CommandMessage *message) { ReturnValue_t result = actionHelper.handleActionMessage(message); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { return result; } return poolManager.handleHousekeepingMessage(message); @@ -31,31 +31,31 @@ ReturnValue_t ExtendedControllerBase::handleCommandMessage(CommandMessage *messa void ExtendedControllerBase::handleQueue() { CommandMessage command; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - for (result = commandQueue->receiveMessage(&command); result == RETURN_OK; + ReturnValue_t result; + for (result = commandQueue->receiveMessage(&command); result == returnvalue::OK; result = commandQueue->receiveMessage(&command)) { result = actionHelper.handleActionMessage(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { continue; } result = modeHelper.handleModeCommand(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { continue; } result = healthHelper.handleHealthCommand(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { continue; } result = poolManager.handleHousekeepingMessage(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { continue; } result = handleCommandMessage(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { continue; } command.setToUnknownCommand(); @@ -65,11 +65,11 @@ void ExtendedControllerBase::handleQueue() { ReturnValue_t ExtendedControllerBase::initialize() { ReturnValue_t result = ControllerBase::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = actionHelper.initialize(commandQueue); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -86,7 +86,7 @@ ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) { /* We do this after performing control operation because variables will be set changed in this function. */ poolManager.performHkOperation(); - return RETURN_OK; + return returnvalue::OK; } MessageQueueId_t ExtendedControllerBase::getCommandQueue() const { return commandQueue->getId(); } diff --git a/src/fsfw/controller/ExtendedControllerBase.h b/src/fsfw/controller/ExtendedControllerBase.h index 0c64f5b9..b5583a88 100644 --- a/src/fsfw/controller/ExtendedControllerBase.h +++ b/src/fsfw/controller/ExtendedControllerBase.h @@ -18,16 +18,16 @@ class ExtendedControllerBase : public ControllerBase, public HasLocalDataPoolIF { public: ExtendedControllerBase(object_id_t objectId, object_id_t parentId, size_t commandQueueDepth = 3); - virtual ~ExtendedControllerBase(); + ~ExtendedControllerBase() override; /* SystemObjectIF overrides */ - virtual ReturnValue_t initialize() override; + ReturnValue_t initialize() override; - virtual MessageQueueId_t getCommandQueue() const override; + [[nodiscard]] MessageQueueId_t getCommandQueue() const override; /* ExecutableObjectIF overrides */ - virtual ReturnValue_t performOperation(uint8_t opCode) override; - virtual ReturnValue_t initializeAfterTaskCreation() override; + ReturnValue_t performOperation(uint8_t opCode) override; + ReturnValue_t initializeAfterTaskCreation() override; protected: LocalDataPoolManager poolManager; @@ -39,32 +39,32 @@ class ExtendedControllerBase : public ControllerBase, * @param message * @return */ - virtual ReturnValue_t handleCommandMessage(CommandMessage* message) = 0; + ReturnValue_t handleCommandMessage(CommandMessage* message) override = 0; /** * Periodic helper from ControllerBase, implemented by child class. */ - virtual void performControlOperation() = 0; + void performControlOperation() override = 0; /* Handle the four messages mentioned above */ void handleQueue() override; /* HasActionsIF overrides */ - virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, - const uint8_t* data, size_t size) override; + ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) override; /* HasLocalDatapoolIF overrides */ - virtual LocalDataPoolManager* getHkManagerHandle() override; - virtual object_id_t getObjectId() const override; - virtual uint32_t getPeriodicOperationFrequency() const override; + LocalDataPoolManager* getHkManagerHandle() override; + [[nodiscard]] object_id_t getObjectId() const override; + [[nodiscard]] uint32_t getPeriodicOperationFrequency() const override; - virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, - LocalDataPoolManager& poolManager) override = 0; - virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override = 0; + ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override = 0; + LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override = 0; // Mode abstract functions - virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, - uint32_t* msToReachTheMode) override = 0; + ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, + uint32_t* msToReachTheMode) override = 0; }; #endif /* FSFW_CONTROLLER_EXTENDEDCONTROLLERBASE_H_ */ diff --git a/src/fsfw/coordinates/CMakeLists.txt b/src/fsfw/coordinates/CMakeLists.txt index a1fa1e52..15452b1c 100644 --- a/src/fsfw/coordinates/CMakeLists.txt +++ b/src/fsfw/coordinates/CMakeLists.txt @@ -1,5 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - CoordinateTransformations.cpp - Sgp4Propagator.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE CoordinateTransformations.cpp + Sgp4Propagator.cpp) diff --git a/src/fsfw/coordinates/Sgp4Propagator.cpp b/src/fsfw/coordinates/Sgp4Propagator.cpp index 4a43842c..e79ffef5 100644 --- a/src/fsfw/coordinates/Sgp4Propagator.cpp +++ b/src/fsfw/coordinates/Sgp4Propagator.cpp @@ -152,7 +152,7 @@ ReturnValue_t Sgp4Propagator::initialize(const uint8_t* line1, const uint8_t* li return MAKE_RETURN_CODE(result); } else { initialized = true; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } } @@ -195,6 +195,6 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity, time if (result != 0) { return MAKE_RETURN_CODE(result || 0xB0); } else { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } } diff --git a/src/fsfw/coordinates/Sgp4Propagator.h b/src/fsfw/coordinates/Sgp4Propagator.h index 0edaf459..5cbeb3f2 100644 --- a/src/fsfw/coordinates/Sgp4Propagator.h +++ b/src/fsfw/coordinates/Sgp4Propagator.h @@ -7,7 +7,7 @@ #ifndef PLATFORM_WIN #include #endif -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw_contrib/sgp4/sgp4unit.h" class Sgp4Propagator { diff --git a/src/fsfw/datalinklayer/CCSDSReturnValuesIF.h b/src/fsfw/datalinklayer/CCSDSReturnValuesIF.h index 22ff12e4..71d14e60 100644 --- a/src/fsfw/datalinklayer/CCSDSReturnValuesIF.h +++ b/src/fsfw/datalinklayer/CCSDSReturnValuesIF.h @@ -9,12 +9,12 @@ #define CCSDSRETURNVALUESIF_H_ #include "dllConf.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" /** * This is a helper class to collect special return values that come up during CCSDS Handling. * @ingroup ccsds_handling */ -class CCSDSReturnValuesIF : public HasReturnvaluesIF { +class CCSDSReturnValuesIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::CCSDS_HANDLER_IF; //!< Basic ID of the interface. diff --git a/src/fsfw/datalinklayer/CMakeLists.txt b/src/fsfw/datalinklayer/CMakeLists.txt index 148e7c5d..cc18088f 100644 --- a/src/fsfw/datalinklayer/CMakeLists.txt +++ b/src/fsfw/datalinklayer/CMakeLists.txt @@ -1,12 +1,11 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - Clcw.cpp - DataLinkLayer.cpp - Farm1StateLockout.cpp - Farm1StateOpen.cpp - Farm1StateWait.cpp - MapPacketExtraction.cpp - TcTransferFrame.cpp - TcTransferFrameLocal.cpp - VirtualChannelReception.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE Clcw.cpp + DataLinkLayer.cpp + Farm1StateLockout.cpp + Farm1StateOpen.cpp + Farm1StateWait.cpp + MapPacketExtraction.cpp + TcTransferFrame.cpp + TcTransferFrameLocal.cpp + VirtualChannelReception.cpp) diff --git a/src/fsfw/datalinklayer/DataLinkLayer.cpp b/src/fsfw/datalinklayer/DataLinkLayer.cpp index ca607478..6fe3e664 100644 --- a/src/fsfw/datalinklayer/DataLinkLayer.cpp +++ b/src/fsfw/datalinklayer/DataLinkLayer.cpp @@ -28,7 +28,7 @@ ReturnValue_t DataLinkLayer::frameDelimitingAndFillRemoval() { TcTransferFrame frame_candidate(frameBuffer); this->currentFrame = frame_candidate; // should work with shallow copy. - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t DataLinkLayer::frameValidationCheck() { @@ -59,14 +59,14 @@ ReturnValue_t DataLinkLayer::frameValidationCheck() { if (USE_CRC) { return this->frameCheckCRC(); } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t DataLinkLayer::frameCheckCRC() { uint16_t checkValue = CRC::crc16ccitt(this->currentFrame.getFullFrame(), this->currentFrame.getFullSize()); if (checkValue == 0) { - return RETURN_OK; + return returnvalue::OK; } else { return CRC_FAILED; } @@ -74,7 +74,7 @@ ReturnValue_t DataLinkLayer::frameCheckCRC() { ReturnValue_t DataLinkLayer::allFramesReception() { ReturnValue_t status = this->frameDelimitingAndFillRemoval(); - if (status != RETURN_OK) { + if (status != returnvalue::OK) { return status; } return this->frameValidationCheck(); @@ -90,7 +90,7 @@ ReturnValue_t DataLinkLayer::virtualChannelDemultiplexing() { virtualChannelIterator iter = virtualChannels.find(vcId); if (iter == virtualChannels.end()) { // Do not report because passive board will get this error all the time. - return RETURN_OK; + return returnvalue::OK; } else { return (iter->second)->frameAcceptanceAndReportingMechanism(¤tFrame, clcw); } @@ -99,7 +99,7 @@ ReturnValue_t DataLinkLayer::virtualChannelDemultiplexing() { ReturnValue_t DataLinkLayer::processFrame(uint16_t length) { receivedDataLength = length; ReturnValue_t status = allFramesReception(); - if (status != RETURN_OK) { + if (status != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "DataLinkLayer::processFrame: frame reception failed. " "Error code: " @@ -117,14 +117,14 @@ ReturnValue_t DataLinkLayer::addVirtualChannel(uint8_t virtualChannelId, std::pair returnValue = virtualChannels.insert( std::pair(virtualChannelId, object)); if (returnValue.second == true) { - return RETURN_OK; + return returnvalue::OK; } else { - return RETURN_FAILED; + return returnvalue::FAILED; } } ReturnValue_t DataLinkLayer::initialize() { - ReturnValue_t returnValue = RETURN_FAILED; + ReturnValue_t returnValue = returnvalue::FAILED; // Set Virtual Channel ID to first virtual channel instance in this DataLinkLayer instance to // avoid faulty information (e.g. 0) in the VCID. if (virtualChannels.begin() != virtualChannels.end()) { @@ -133,13 +133,13 @@ ReturnValue_t DataLinkLayer::initialize() { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "DataLinkLayer::initialize: No VC assigned to this DLL instance! " << std::endl; #endif - return RETURN_FAILED; + return returnvalue::FAILED; } for (virtualChannelIterator iterator = virtualChannels.begin(); iterator != virtualChannels.end(); iterator++) { returnValue = iterator->second->initialize(); - if (returnValue != RETURN_OK) break; + if (returnValue != returnvalue::OK) break; } return returnValue; } diff --git a/src/fsfw/datalinklayer/DataLinkLayer.h b/src/fsfw/datalinklayer/DataLinkLayer.h index 8735feb6..64d2f96b 100644 --- a/src/fsfw/datalinklayer/DataLinkLayer.h +++ b/src/fsfw/datalinklayer/DataLinkLayer.h @@ -51,7 +51,7 @@ class DataLinkLayer : public CCSDSReturnValuesIF { * This method tries to process a frame that is placed in #frameBuffer. * The procedures described in the Standard are performed. * @param length Length of the incoming frame candidate. - * @return @c RETURN_OK on successful handling, otherwise the return codes of the higher + * @return @c returnvalue::OK on successful handling, otherwise the return codes of the higher * methods. */ ReturnValue_t processFrame(uint16_t length); @@ -61,12 +61,12 @@ class DataLinkLayer : public CCSDSReturnValuesIF { * handle Frames directed to this VC. * @param virtualChannelId Id of the VC. Shall be smaller than 64. * @param object Reference to the object that handles the Frame. - * @return @c RETURN_OK on success, @c RETURN_FAILED otherwise. + * @return @c returnvalue::OK on success, @c returnvalue::FAILED otherwise. */ ReturnValue_t addVirtualChannel(uint8_t virtualChannelId, VirtualChannelReceptionIF* object); /** * The initialization method calls the @c initialize routine of all virtual channels. - * @return The return code of the first failed VC initialization or @c RETURN_OK. + * @return The return code of the first failed VC initialization or @c returnvalue::OK. */ ReturnValue_t initialize(); @@ -91,19 +91,19 @@ class DataLinkLayer : public CCSDSReturnValuesIF { virtualChannels; //!< Map of all virtual channels assigned. /** * Method that performs all possible frame validity checks (as specified). - * @return Various error codes or @c RETURN_OK on success. + * @return Various error codes or @c returnvalue::OK on success. */ ReturnValue_t frameValidationCheck(); /** * First method to call. * Removes start sequence bytes and checks if the complete frame was received. * SHOULDDO: Maybe handling the start sequence must be done more variable. - * @return @c RETURN_OK or @c TOO_SHORT. + * @return @c returnvalue::OK or @c TOO_SHORT. */ ReturnValue_t frameDelimitingAndFillRemoval(); /** * Small helper method to check the CRC of the Frame. - * @return @c RETURN_OK or @c CRC_FAILED. + * @return @c returnvalue::OK or @c CRC_FAILED. */ ReturnValue_t frameCheckCRC(); /** diff --git a/src/fsfw/datalinklayer/Farm1StateOpen.cpp b/src/fsfw/datalinklayer/Farm1StateOpen.cpp index cf3339a7..b27f609c 100644 --- a/src/fsfw/datalinklayer/Farm1StateOpen.cpp +++ b/src/fsfw/datalinklayer/Farm1StateOpen.cpp @@ -11,7 +11,7 @@ ReturnValue_t Farm1StateOpen::handleADFrame(TcTransferFrame* frame, ClcwIF* clcw if (diff == 0) { myVC->vR++; clcw->setRetransmitFlag(false); - return RETURN_OK; + return returnvalue::OK; } else if (diff < myVC->positiveWindow && diff > 0) { clcw->setRetransmitFlag(true); return NS_POSITIVE_W; diff --git a/src/fsfw/datalinklayer/Farm1StateOpen.h b/src/fsfw/datalinklayer/Farm1StateOpen.h index 0bca931d..a1c553ff 100644 --- a/src/fsfw/datalinklayer/Farm1StateOpen.h +++ b/src/fsfw/datalinklayer/Farm1StateOpen.h @@ -37,8 +37,8 @@ class Farm1StateOpen : public Farm1StateIF { * change to Farm1StateLockout. * @param frame The frame to handle. * @param clcw Any changes to the CLCW shall be done with the help of this interface. - * @return If the Sequence Number is ok, it returns #RETURN_OK. Otherwise either #NS_POSITIVE_W, - * #NS_NEGATIVE_W or NS_LOCKOUT is returned. + * @return If the Sequence Number is ok, it returns returnvalue::OK. Otherwise either + * #NS_POSITIVE_W, #NS_NEGATIVE_W or NS_LOCKOUT is returned. */ ReturnValue_t handleADFrame(TcTransferFrame* frame, ClcwIF* clcw); /** diff --git a/src/fsfw/datalinklayer/MapPacketExtraction.cpp b/src/fsfw/datalinklayer/MapPacketExtraction.cpp index 57aa2f08..c074de73 100644 --- a/src/fsfw/datalinklayer/MapPacketExtraction.cpp +++ b/src/fsfw/datalinklayer/MapPacketExtraction.cpp @@ -6,7 +6,7 @@ #include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/storagemanager/StorageManagerIF.h" -#include "fsfw/tmtcpacket/SpacePacketBase.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" #include "fsfw/tmtcservices/AcceptsTelecommandsIF.h" #include "fsfw/tmtcservices/TmTcMessage.h" @@ -31,7 +31,7 @@ ReturnValue_t MapPacketExtraction::extractPackets(TcTransferFrame* frame) { if (packetLength <= MAX_PACKET_SIZE) { memcpy(packetBuffer, frame->getDataField(), packetLength); bufferPosition = &packetBuffer[packetLength]; - status = RETURN_OK; + status = returnvalue::OK; } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "MapPacketExtraction::extractPackets. Packet too large! Size: " @@ -52,7 +52,7 @@ ReturnValue_t MapPacketExtraction::extractPackets(TcTransferFrame* frame) { status = sendCompletePacket(packetBuffer, packetLength); clearBuffers(); } - status = RETURN_OK; + status = returnvalue::OK; } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "MapPacketExtraction::extractPackets. Packet too large! Size: " @@ -95,7 +95,7 @@ ReturnValue_t MapPacketExtraction::unpackBlockingPackets(TcTransferFrame* frame) status = sendCompletePacket(packet.getWholeData(), packet.getFullSize()); totalLength -= packet.getFullSize(); position += packet.getFullSize(); - status = RETURN_OK; + status = returnvalue::OK; } else { status = DATA_CORRUPTED; totalLength = 0; @@ -110,7 +110,7 @@ ReturnValue_t MapPacketExtraction::unpackBlockingPackets(TcTransferFrame* frame) ReturnValue_t MapPacketExtraction::sendCompletePacket(uint8_t* data, uint32_t size) { store_address_t store_id; ReturnValue_t status = this->packetStore->addData(&store_id, data, size); - if (status == RETURN_OK) { + if (status == returnvalue::OK) { TmTcMessage message(store_id); status = MessageQueueSenderIF::sendMessage(tcQueueId, &message); } @@ -130,9 +130,9 @@ ReturnValue_t MapPacketExtraction::initialize() { ObjectManager::instance()->get(packetDestination); if ((packetStore != NULL) && (distributor != NULL)) { tcQueueId = distributor->getRequestQueue(); - return RETURN_OK; + return returnvalue::OK; } else { - return RETURN_FAILED; + return returnvalue::FAILED; } } diff --git a/src/fsfw/datalinklayer/MapPacketExtraction.h b/src/fsfw/datalinklayer/MapPacketExtraction.h index c2673b2e..fab7f3c3 100644 --- a/src/fsfw/datalinklayer/MapPacketExtraction.h +++ b/src/fsfw/datalinklayer/MapPacketExtraction.h @@ -5,7 +5,7 @@ #include "dllConf.h" #include "fsfw/ipc/MessageQueueSenderIF.h" #include "fsfw/objectmanager/ObjectManagerIF.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" class StorageManagerIF; @@ -36,7 +36,7 @@ class MapPacketExtraction : public MapPacketExtractionIF { * Method that is called if the segmentation flag is @c NO_SEGMENTATION. * The method extracts one or more packets within the frame and forwards them to the OBSW. * @param frame The TC Transfer Frame to work on. - * @return @c RETURN_OK if all Packets were extracted. If something is entirely wrong, + * @return @c returnvalue::OK if all Packets were extracted. If something is entirely wrong, * @c DATA_CORRUPTED is returned, if some bytes are left over @c RESIDUAL_DATA. */ ReturnValue_t unpackBlockingPackets(TcTransferFrame* frame); @@ -63,7 +63,7 @@ class MapPacketExtraction : public MapPacketExtractionIF { ReturnValue_t extractPackets(TcTransferFrame* frame); /** * The #packetStore and the default destination of #tcQueue are initialized here. - * @return @c RETURN_OK on success, @c RETURN_FAILED otherwise. + * @return @c returnvalue::OK on success, @c returnvalue::FAILED otherwise. */ ReturnValue_t initialize(); /** diff --git a/src/fsfw/datalinklayer/VirtualChannelReception.cpp b/src/fsfw/datalinklayer/VirtualChannelReception.cpp index 258bc1e6..4c44cf01 100644 --- a/src/fsfw/datalinklayer/VirtualChannelReception.cpp +++ b/src/fsfw/datalinklayer/VirtualChannelReception.cpp @@ -57,18 +57,18 @@ ReturnValue_t VirtualChannelReception::doFARM(TcTransferFrame* frame, ClcwIF* cl ReturnValue_t VirtualChannelReception::frameAcceptanceAndReportingMechanism(TcTransferFrame* frame, ClcwIF* clcw) { - ReturnValue_t result = RETURN_OK; + ReturnValue_t result = returnvalue::OK; result = doFARM(frame, &internalClcw); internalClcw.setReceiverFrameSequenceNumber(vR); internalClcw.setFarmBCount(farmBCounter); clcw->setWhole(internalClcw.getAsWhole()); switch (result) { - case RETURN_OK: + case returnvalue::OK: return mapDemultiplexing(frame); case BC_IS_SET_VR_COMMAND: case BC_IS_UNLOCK_COMMAND: // Need to catch these codes to avoid error reporting later. - return RETURN_OK; + return returnvalue::OK; default: break; } @@ -79,15 +79,15 @@ ReturnValue_t VirtualChannelReception::addMapChannel(uint8_t mapId, MapPacketExt std::pair returnValue = mapChannels.insert(std::pair(mapId, object)); if (returnValue.second == true) { - return RETURN_OK; + return returnvalue::OK; } else { - return RETURN_FAILED; + return returnvalue::FAILED; } } ReturnValue_t VirtualChannelReception::handleBDFrame(TcTransferFrame* frame, ClcwIF* clcw) { farmBCounter++; - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t VirtualChannelReception::handleBCFrame(TcTransferFrame* frame, ClcwIF* clcw) { @@ -107,18 +107,18 @@ ReturnValue_t VirtualChannelReception::handleBCFrame(TcTransferFrame* frame, Clc uint8_t VirtualChannelReception::getChannelId() const { return channelId; } ReturnValue_t VirtualChannelReception::initialize() { - ReturnValue_t returnValue = RETURN_FAILED; + ReturnValue_t returnValue = returnvalue::FAILED; if ((slidingWindowWidth > 254) || (slidingWindowWidth % 2 != 0)) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "VirtualChannelReception::initialize: Illegal sliding window width: " << (int)slidingWindowWidth << std::endl; #endif - return RETURN_FAILED; + return returnvalue::FAILED; } for (mapChannelIterator iterator = mapChannels.begin(); iterator != mapChannels.end(); iterator++) { returnValue = iterator->second->initialize(); - if (returnValue != RETURN_OK) break; + if (returnValue != returnvalue::OK) break; } return returnValue; } diff --git a/src/fsfw/datalinklayer/VirtualChannelReception.h b/src/fsfw/datalinklayer/VirtualChannelReception.h index 6dc17dd8..429ae9de 100644 --- a/src/fsfw/datalinklayer/VirtualChannelReception.h +++ b/src/fsfw/datalinklayer/VirtualChannelReception.h @@ -77,7 +77,7 @@ class VirtualChannelReception : public VirtualChannelReceptionIF, public CCSDSRe * required. * @param frame The Tc Transfer Frame to handle. * @param clcw Any changes on the CLCW shall be done with this method. - * @return Always returns @c RETURN_OK. + * @return Always returns @c returnvalue::OK. */ ReturnValue_t handleBDFrame(TcTransferFrame* frame, ClcwIF* clcw); /** @@ -102,13 +102,14 @@ class VirtualChannelReception : public VirtualChannelReceptionIF, public CCSDSRe * Helper method to simplify adding a mapChannel during construction. * @param mapId The mapId of the object to add. * @param object Pointer to the MapPacketExtraction object itself. - * @return @c RETURN_OK if the channel was successfully inserted, @c RETURN_FAILED otherwise. + * @return @c returnvalue::OK if the channel was successfully inserted, @c returnvalue::FAILED + * otherwise. */ ReturnValue_t addMapChannel(uint8_t mapId, MapPacketExtractionIF* object); /** * The initialization routine checks the set #slidingWindowWidth and initializes all MAP * channels. - * @return @c RETURN_OK on successful initialization, @c RETURN_FAILED otherwise. + * @return @c returnvalue::OK on successful initialization, @c returnvalue::FAILED otherwise. */ ReturnValue_t initialize(); /** diff --git a/src/fsfw/datalinklayer/VirtualChannelReceptionIF.h b/src/fsfw/datalinklayer/VirtualChannelReceptionIF.h index 3426f21c..9239ee0e 100644 --- a/src/fsfw/datalinklayer/VirtualChannelReceptionIF.h +++ b/src/fsfw/datalinklayer/VirtualChannelReceptionIF.h @@ -11,7 +11,7 @@ #include "ClcwIF.h" #include "TcTransferFrame.h" #include "dllConf.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" /** * This is the interface for Virtual Channel reception classes. @@ -33,13 +33,13 @@ class VirtualChannelReceptionIF { * Handling the Frame includes forwarding to higher-level procedures. * @param frame The Tc Transfer Frame that was received and checked. * @param clcw Any changes to the CLCW value are forwarded by using this parameter. - * @return The return Value shall indicate successful processing with @c RETURN_OK. + * @return The return Value shall indicate successful processing with @c returnvalue::OK. */ virtual ReturnValue_t frameAcceptanceAndReportingMechanism(TcTransferFrame* frame, ClcwIF* clcw) = 0; /** * If any other System Objects are required for operation they shall be initialized here. - * @return @c RETURN_OK for successful initialization. + * @return @c returnvalue::OK for successful initialization. */ virtual ReturnValue_t initialize() = 0; /** diff --git a/src/fsfw/datapool/CMakeLists.txt b/src/fsfw/datapool/CMakeLists.txt index be4606aa..b2ac592c 100644 --- a/src/fsfw/datapool/CMakeLists.txt +++ b/src/fsfw/datapool/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - PoolDataSetBase.cpp - PoolEntry.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE PoolDataSetBase.cpp PoolEntry.cpp) diff --git a/src/fsfw/datapool/DataSetIF.h b/src/fsfw/datapool/DataSetIF.h index 492bcf29..3d4be351 100644 --- a/src/fsfw/datapool/DataSetIF.h +++ b/src/fsfw/datapool/DataSetIF.h @@ -1,7 +1,7 @@ #ifndef FSFW_DATAPOOL_DATASETIF_H_ #define FSFW_DATAPOOL_DATASETIF_H_ -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "../timemanager/Clock.h" class PoolVariableIF; diff --git a/src/fsfw/datapool/PoolDataSetBase.cpp b/src/fsfw/datapool/PoolDataSetBase.cpp index b31f4725..0df21d2a 100644 --- a/src/fsfw/datapool/PoolDataSetBase.cpp +++ b/src/fsfw/datapool/PoolDataSetBase.cpp @@ -14,7 +14,7 @@ PoolDataSetBase::~PoolDataSetBase() {} ReturnValue_t PoolDataSetBase::registerVariable(PoolVariableIF* variable) { if (registeredVariables == nullptr) { /* Underlying container invalid */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (state != States::STATE_SET_UNINITIALISED) { #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -42,17 +42,17 @@ ReturnValue_t PoolDataSetBase::registerVariable(PoolVariableIF* variable) { } registeredVariables[fillCount] = variable; fillCount++; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t PoolDataSetBase::read(MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; ReturnValue_t error = result; if (state == States::STATE_SET_UNINITIALISED) { lockDataPool(timeoutType, lockTimeout); for (uint16_t count = 0; count < fillCount; count++) { result = readVariable(count); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { error = result; } } @@ -71,7 +71,7 @@ ReturnValue_t PoolDataSetBase::read(MutexIF::TimeoutType timeoutType, uint32_t l result = SET_WAS_ALREADY_READ; } - if (error != HasReturnvaluesIF::RETURN_OK) { + if (error != returnvalue::OK) { result = error; } return result; @@ -80,10 +80,10 @@ ReturnValue_t PoolDataSetBase::read(MutexIF::TimeoutType timeoutType, uint32_t l uint16_t PoolDataSetBase::getFillCount() const { return fillCount; } ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; if (registeredVariables[count] == nullptr) { /* Configuration error. */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } /* These checks are often performed by the respective variable implementation too, but I guess @@ -98,7 +98,7 @@ ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) { result = ReadCommitIFAttorney::readWithoutLock(registeredVariables[count]); } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { result = INVALID_PARAMETER_DEFINITION; } } @@ -108,7 +108,7 @@ ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) { ReturnValue_t PoolDataSetBase::commit(MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) { if (state == States::STATE_SET_WAS_READ) { handleAlreadyReadDatasetCommit(timeoutType, lockTimeout); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { return handleUnreadDatasetCommit(timeoutType, lockTimeout); } @@ -134,7 +134,7 @@ void PoolDataSetBase::handleAlreadyReadDatasetCommit(MutexIF::TimeoutType timeou ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; lockDataPool(timeoutType, lockTimeout); for (uint16_t count = 0; count < fillCount; count++) { if ((registeredVariables[count]->getReadWriteMode() == PoolVariableIF::VAR_WRITE) and @@ -165,17 +165,17 @@ ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(MutexIF::TimeoutType ti ReturnValue_t PoolDataSetBase::lockDataPool(MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } -ReturnValue_t PoolDataSetBase::unlockDataPool() { return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t PoolDataSetBase::unlockDataPool() { return returnvalue::OK; } ReturnValue_t PoolDataSetBase::serialize(uint8_t** buffer, size_t* size, const size_t maxSize, SerializeIF::Endianness streamEndianness) const { - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t result = returnvalue::FAILED; for (uint16_t count = 0; count < fillCount; count++) { result = registeredVariables[count]->serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } } @@ -184,10 +184,10 @@ ReturnValue_t PoolDataSetBase::serialize(uint8_t** buffer, size_t* size, const s ReturnValue_t PoolDataSetBase::deSerialize(const uint8_t** buffer, size_t* size, SerializeIF::Endianness streamEndianness) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t result = returnvalue::FAILED; for (uint16_t count = 0; count < fillCount; count++) { result = registeredVariables[count]->deSerialize(buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } } diff --git a/src/fsfw/datapool/PoolDataSetBase.h b/src/fsfw/datapool/PoolDataSetBase.h index 1b4bacda..621dd8cc 100644 --- a/src/fsfw/datapool/PoolDataSetBase.h +++ b/src/fsfw/datapool/PoolDataSetBase.h @@ -29,20 +29,20 @@ * @author Bastian Baetz * @ingroup data_pool */ -class PoolDataSetBase : public PoolDataSetIF, public SerializeIF, public HasReturnvaluesIF { +class PoolDataSetBase : public PoolDataSetIF, public SerializeIF { public: /** * @brief Creates an empty dataset. Use registerVariable or * supply a pointer to this dataset to PoolVariable * initializations to register pool variables. */ - PoolDataSetBase(PoolVariableIF** registeredVariablesArray, const size_t maxFillCount); + PoolDataSetBase(PoolVariableIF** registeredVariablesArray, size_t maxFillCount); /* Forbidden for now */ PoolDataSetBase(const PoolDataSetBase& otherSet) = delete; const PoolDataSetBase& operator=(const PoolDataSetBase& otherSet) = delete; - virtual ~PoolDataSetBase(); + ~PoolDataSetBase() override; /** * @brief The read call initializes reading out all registered variables. @@ -58,14 +58,14 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF, public HasRetu * freed afterwards. It is mandatory to call commit after a read call, * even if the read operation is not successful! * @return - * - @c RETURN_OK if all variables were read successfully. + * - @c returnvalue::OK if all variables were read successfully. * - @c INVALID_PARAMETER_DEFINITION if a pool entry does not exist or there * is a type conflict. * - @c SET_WAS_ALREADY_READ if read() is called twice without calling * commit() in between */ - virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, - uint32_t lockTimeout = 20) override; + ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t lockTimeout = 20) override; /** * @brief The commit call initializes writing back the registered variables. * @details @@ -80,24 +80,24 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF, public HasRetu * commit() can only be called after read(). If the set only contains * variables which are write only, commit() can be called without a * preceding read() call. Every read call must be followed by a commit call! - * @return - @c RETURN_OK if all variables were read successfully. + * @return - @c returnvalue::OK if all variables were read successfully. * - @c COMMITING_WITHOUT_READING if set was not read yet and * contains non write-only variables */ - virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, - uint32_t lockTimeout = 20) override; + ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t lockTimeout = 20) override; /** * Register the passed pool variable instance into the data set. * @param variable * @return */ - virtual ReturnValue_t registerVariable(PoolVariableIF* variable) override; + ReturnValue_t registerVariable(PoolVariableIF* variable) override; /** * Provides the means to lock the underlying data structure to ensure * thread-safety. Default implementation is empty - * @return Always returns -@c RETURN_OK + * @return Always returns -@c returnvalue::OK */ virtual ReturnValue_t lockDataPool( MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, @@ -105,11 +105,11 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF, public HasRetu /** * Provides the means to unlock the underlying data structure to ensure * thread-safety. Default implementation is empty - * @return Always returns -@c RETURN_OK + * @return Always returns -@c returnvalue::OK */ virtual ReturnValue_t unlockDataPool() override; - virtual uint16_t getFillCount() const; + virtual uint16_t getFillCount() const override; /* SerializeIF implementations */ virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize, diff --git a/src/fsfw/datapool/PoolEntry.cpp b/src/fsfw/datapool/PoolEntry.cpp index fd110e6c..9138a705 100644 --- a/src/fsfw/datapool/PoolEntry.cpp +++ b/src/fsfw/datapool/PoolEntry.cpp @@ -7,24 +7,26 @@ #include "fsfw/serviceinterface/ServiceInterface.h" template -PoolEntry::PoolEntry(std::initializer_list initValue, bool setValid) - : length(static_cast(initValue.size())), valid(setValid) { - this->address = new T[this->length]; - if (initValue.size() == 0) { - std::memset(this->address, 0, this->getByteSize()); - } else { - std::copy(initValue.begin(), initValue.end(), this->address); +PoolEntry::PoolEntry(uint8_t len, bool setValid) : length(len), valid(setValid) { + this->address = new T[this->length](); + std::memset(this->address, 0, this->getByteSize()); +} + +template +PoolEntry::PoolEntry(std::initializer_list initValues, bool setValid) + : length(static_cast(initValues.size())), valid(setValid) { + this->address = new T[this->length](); + if (initValues.size() > 0) { + std::copy(initValues.begin(), initValues.end(), this->address); } } template -PoolEntry::PoolEntry(T* initValue, uint8_t setLength, bool setValid) +PoolEntry::PoolEntry(const T* initValue, uint8_t setLength, bool setValid) : length(setLength), valid(setValid) { - this->address = new T[this->length]; + this->address = new T[this->length](); if (initValue != nullptr) { std::memcpy(this->address, initValue, this->getByteSize()); - } else { - std::memset(this->address, 0, this->getByteSize()); } } diff --git a/src/fsfw/datapool/PoolEntry.h b/src/fsfw/datapool/PoolEntry.h index d3d80f09..4010f78d 100644 --- a/src/fsfw/datapool/PoolEntry.h +++ b/src/fsfw/datapool/PoolEntry.h @@ -33,6 +33,9 @@ class PoolEntry : public PoolEntryIF { "instead! The ECSS standard defines a boolean as a one bit " "field. Therefore it is preferred to store a boolean as an " "uint8_t"); + + PoolEntry(uint8_t len = 1, bool setValid = false); + /** * @brief In the classe's constructor, space is allocated on the heap and * potential initialization values are copied to that space. @@ -49,7 +52,7 @@ class PoolEntry : public PoolEntryIF { * @param setValid * Sets the initialization flag. It is invalid by default. */ - PoolEntry(std::initializer_list initValue = {0}, bool setValid = false); + PoolEntry(std::initializer_list initValue, bool setValid = false); /** * @brief In the classe's constructor, space is allocated on the heap and @@ -62,7 +65,7 @@ class PoolEntry : public PoolEntryIF { * @param setValid * Sets the initialization flag. It is invalid by default. */ - PoolEntry(T* initValue, uint8_t setLength = 1, bool setValid = false); + PoolEntry(const T* initValue, uint8_t setLength = 1, bool setValid = false); //! Explicitely deleted copy ctor, copying is not allowed. PoolEntry(const PoolEntry&) = delete; diff --git a/src/fsfw/datapool/PoolReadGuard.h b/src/fsfw/datapool/PoolReadGuard.h index 24d98933..f9bf35fe 100644 --- a/src/fsfw/datapool/PoolReadGuard.h +++ b/src/fsfw/datapool/PoolReadGuard.h @@ -17,7 +17,7 @@ class PoolReadGuard { : readObject(readObject), mutexTimeout(mutexTimeout) { if (readObject != nullptr) { readResult = readObject->read(timeoutType, mutexTimeout); - if (readResult != HasReturnvaluesIF::RETURN_OK) { + if (readResult != returnvalue::OK) { #if FSFW_VERBOSE_LEVEL == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "PoolReadHelper: Read failed!" << std::endl; @@ -47,7 +47,7 @@ class PoolReadGuard { private: ReadCommitIF* readObject = nullptr; - ReturnValue_t readResult = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t readResult = returnvalue::OK; bool noCommit = false; MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; uint32_t mutexTimeout = 20; diff --git a/src/fsfw/datapool/PoolVariableIF.h b/src/fsfw/datapool/PoolVariableIF.h index 95cf898e..69074310 100644 --- a/src/fsfw/datapool/PoolVariableIF.h +++ b/src/fsfw/datapool/PoolVariableIF.h @@ -1,7 +1,7 @@ #ifndef FSFW_DATAPOOL_POOLVARIABLEIF_H_ #define FSFW_DATAPOOL_POOLVARIABLEIF_H_ -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "../serialize/SerializeIF.h" #include "ReadCommitIF.h" diff --git a/src/fsfw/datapool/ReadCommitIF.h b/src/fsfw/datapool/ReadCommitIF.h index 08554be1..ca074dec 100644 --- a/src/fsfw/datapool/ReadCommitIF.h +++ b/src/fsfw/datapool/ReadCommitIF.h @@ -2,7 +2,7 @@ #define FSFW_DATAPOOL_READCOMMITIF_H_ #include "../ipc/MutexIF.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" /** * @brief Common interface for all software objects which employ read-commit diff --git a/src/fsfw/datapool/ReadCommitIFAttorney.h b/src/fsfw/datapool/ReadCommitIFAttorney.h index ea39ffe5..cca76c97 100644 --- a/src/fsfw/datapool/ReadCommitIFAttorney.h +++ b/src/fsfw/datapool/ReadCommitIFAttorney.h @@ -2,7 +2,7 @@ #define FSFW_DATAPOOL_READCOMMITIFATTORNEY_H_ #include -#include +#include /** * @brief This class determines which members are allowed to access protected members @@ -12,14 +12,14 @@ class ReadCommitIFAttorney { private: static ReturnValue_t readWithoutLock(ReadCommitIF* readCommitIF) { if (readCommitIF == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } return readCommitIF->readWithoutLock(); } static ReturnValue_t commitWithoutLock(ReadCommitIF* readCommitIF) { if (readCommitIF == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } return readCommitIF->commitWithoutLock(); } diff --git a/src/fsfw/datapoollocal/CMakeLists.txt b/src/fsfw/datapoollocal/CMakeLists.txt index e2db39eb..749ef688 100644 --- a/src/fsfw/datapoollocal/CMakeLists.txt +++ b/src/fsfw/datapoollocal/CMakeLists.txt @@ -1,10 +1,6 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - LocalDataPoolManager.cpp - LocalDataSet.cpp - LocalPoolDataSetBase.cpp - LocalPoolObjectBase.cpp - SharedLocalDataSet.cpp -) +target_sources( + ${LIB_FSFW_NAME} + PRIVATE LocalDataPoolManager.cpp LocalDataSet.cpp LocalPoolDataSetBase.cpp + LocalPoolObjectBase.cpp SharedLocalDataSet.cpp) -add_subdirectory(internal) \ No newline at end of file +add_subdirectory(internal) diff --git a/src/fsfw/datapoollocal/HasLocalDataPoolIF.h b/src/fsfw/datapoollocal/HasLocalDataPoolIF.h index a2925a46..488e0cd4 100644 --- a/src/fsfw/datapoollocal/HasLocalDataPoolIF.h +++ b/src/fsfw/datapoollocal/HasLocalDataPoolIF.h @@ -3,11 +3,11 @@ #include -#include "../datapool/PoolEntryIF.h" -#include "../housekeeping/HousekeepingMessage.h" -#include "../ipc/MessageQueueSenderIF.h" -#include "../serviceinterface/ServiceInterface.h" #include "LocalDataPoolManager.h" +#include "fsfw/datapool/PoolEntryIF.h" +#include "fsfw/housekeeping/HousekeepingMessage.h" +#include "fsfw/ipc/MessageQueueSenderIF.h" +#include "fsfw/serviceinterface.h" #include "localPoolDefinitions.h" class AccessPoolManagerIF; @@ -79,8 +79,7 @@ class HasLocalDataPoolIF { * @param clearMessage If this is set to true, the pool manager will take care of * clearing the store automatically */ - virtual void handleChangedDataset(sid_t sid, - store_address_t storeId = storeId::INVALID_STORE_ADDRESS, + virtual void handleChangedDataset(sid_t sid, store_address_t storeId = store_address_t::invalid(), bool* clearMessage = nullptr) { if (clearMessage != nullptr) { *clearMessage = true; @@ -100,7 +99,7 @@ class HasLocalDataPoolIF { * after the callback. */ virtual void handleChangedPoolVariable(gp_id_t gpid, - store_address_t storeId = storeId::INVALID_STORE_ADDRESS, + store_address_t storeId = store_address_t::invalid(), bool* clearMessage = nullptr) { if (clearMessage != nullptr) { *clearMessage = true; @@ -111,10 +110,10 @@ class HasLocalDataPoolIF { * These function can be implemented by pool owner, if they are required * and used by the housekeeping message interface. * */ - virtual ReturnValue_t addDataSet(sid_t sid) { return HasReturnvaluesIF::RETURN_FAILED; }; - virtual ReturnValue_t removeDataSet(sid_t sid) { return HasReturnvaluesIF::RETURN_FAILED; }; + virtual ReturnValue_t addDataSet(sid_t sid) { return returnvalue::FAILED; }; + virtual ReturnValue_t removeDataSet(sid_t sid) { return returnvalue::FAILED; }; virtual ReturnValue_t changeCollectionInterval(sid_t sid, float newIntervalSeconds) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; }; /** diff --git a/src/fsfw/datapoollocal/LocalDataPoolManager.cpp b/src/fsfw/datapoollocal/LocalDataPoolManager.cpp index 6053bd43..fa76d2a7 100644 --- a/src/fsfw/datapoollocal/LocalDataPoolManager.cpp +++ b/src/fsfw/datapoollocal/LocalDataPoolManager.cpp @@ -1,6 +1,5 @@ #include "fsfw/datapoollocal/LocalDataPoolManager.h" -#include #include #include "fsfw/datapoollocal.h" @@ -15,21 +14,22 @@ #include "internal/HasLocalDpIFManagerAttorney.h" #include "internal/LocalPoolDataSetAttorney.h" +// TODO: Get rid of this. This should be a constructor argument, not something hardcoded in any way object_id_t LocalDataPoolManager::defaultHkDestination = objects::PUS_SERVICE_3_HOUSEKEEPING; LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse, bool appendValidityBuffer) : appendValidityBuffer(appendValidityBuffer) { if (owner == nullptr) { - printWarningOrError(sif::OutputTypes::OUT_WARNING, "LocalDataPoolManager", - HasReturnvaluesIF::RETURN_FAILED, "Invalid supplied owner"); + printWarningOrError(sif::OutputTypes::OUT_WARNING, "LocalDataPoolManager", returnvalue::FAILED, + "Invalid supplied owner"); return; } this->owner = owner; mutex = MutexFactory::instance()->createMutex(); if (mutex == nullptr) { - printWarningOrError(sif::OutputTypes::OUT_ERROR, "LocalDataPoolManager", - HasReturnvaluesIF::RETURN_FAILED, "Could not create mutex"); + printWarningOrError(sif::OutputTypes::OUT_ERROR, "LocalDataPoolManager", returnvalue::FAILED, + "Could not create mutex"); } hkQueue = queueToUse; @@ -51,13 +51,13 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) { ipcStore = ObjectManager::instance()->get(objects::IPC_STORE); if (ipcStore == nullptr) { /* Error, all destinations invalid */ - printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize", HasReturnvaluesIF::RETURN_FAILED, + printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize", returnvalue::FAILED, "Could not set IPC store."); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (defaultHkDestination != objects::NO_OBJECT) { - AcceptsHkPacketsIF* hkPacketReceiver = + auto* hkPacketReceiver = ObjectManager::instance()->get(defaultHkDestination); if (hkPacketReceiver != nullptr) { hkDestinationId = hkPacketReceiver->getHkQueue(); @@ -67,7 +67,7 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) { } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation(uint8_t nonDiagInvlFactor) { @@ -78,19 +78,19 @@ ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation(uint8_t nonDiagI ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() { if (not mapInitialized) { ReturnValue_t result = owner->initializeLocalDataPool(localPoolMap, *this); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { mapInitialized = true; } return result; } printWarningOrError(sif::OutputTypes::OUT_WARNING, "initializeHousekeepingPoolEntriesOnce", - HasReturnvaluesIF::RETURN_FAILED, "The map should only be initialized once"); - return HasReturnvaluesIF::RETURN_OK; + returnvalue::FAILED, "The map should only be initialized once"); + return returnvalue::OK; } ReturnValue_t LocalDataPoolManager::performHkOperation() { - ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t status = returnvalue::OK; for (auto& receiver : hkReceivers) { switch (receiver.reportingType) { case (ReportingType::PERIODIC): { @@ -115,7 +115,7 @@ ReturnValue_t LocalDataPoolManager::performHkOperation() { } default: // This should never happen. - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } resetHkUpdateResetHelper(); @@ -125,7 +125,7 @@ ReturnValue_t LocalDataPoolManager::performHkOperation() { ReturnValue_t LocalDataPoolManager::handleHkUpdate(HkReceiver& receiver, ReturnValue_t& status) { if (receiver.dataType == DataType::LOCAL_POOL_VARIABLE) { /* Update packets shall only be generated from datasets. */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, receiver.dataId.sid); @@ -135,12 +135,12 @@ ReturnValue_t LocalDataPoolManager::handleHkUpdate(HkReceiver& receiver, ReturnV if (dataSet->hasChanged()) { /* Prepare and send update notification */ ReturnValue_t result = generateHousekeepingPacket(receiver.dataId.sid, dataSet, true); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { status = result; } } handleChangeResetLogic(receiver.dataType, receiver.dataId, dataSet); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receiver, @@ -160,7 +160,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive HousekeepingMessage::setUpdateNotificationVariableCommand( ¬ification, gp_id_t(owner->getObjectId(), receiver.dataId.localPoolId)); ReturnValue_t result = hkQueue->sendMessage(receiver.destinationQueue, ¬ification); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { status = result; } toReset = poolObj; @@ -179,7 +179,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive CommandMessage notification; HousekeepingMessage::setUpdateNotificationSetCommand(¬ification, receiver.dataId.sid); ReturnValue_t result = hkQueue->sendMessage(receiver.destinationQueue, ¬ification); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { status = result; } toReset = dataSet; @@ -188,7 +188,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive if (toReset != nullptr) { handleChangeResetLogic(receiver.dataType, receiver.dataId, toReset); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(HkReceiver& receiver, @@ -205,13 +205,13 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(HkReceiver& recei } if (not poolObj->hasChanged()) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } /* Prepare and send update snapshot */ - timeval now; + timeval now{}; Clock::getClock_timeval(&now); - CCSDSTime::CDS_short cds; + CCSDSTime::CDS_short cds{}; CCSDSTime::convertToCcsds(&cds, &now); HousekeepingSnapshot updatePacket( reinterpret_cast(&cds), sizeof(cds), @@ -219,7 +219,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(HkReceiver& recei store_address_t storeId; ReturnValue_t result = addUpdateToStore(updatePacket, storeId); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -227,7 +227,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(HkReceiver& recei HousekeepingMessage::setUpdateSnapshotVariableCommand( ¬ification, gp_id_t(owner->getObjectId(), receiver.dataId.localPoolId), storeId); result = hkQueue->sendMessage(receiver.destinationQueue, ¬ification); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { status = result; } toReset = poolObj; @@ -241,13 +241,13 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(HkReceiver& recei } if (not dataSet->hasChanged()) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } /* Prepare and send update snapshot */ - timeval now; + timeval now{}; Clock::getClock_timeval(&now); - CCSDSTime::CDS_short cds; + CCSDSTime::CDS_short cds{}; CCSDSTime::convertToCcsds(&cds, &now); HousekeepingSnapshot updatePacket( reinterpret_cast(&cds), sizeof(cds), @@ -255,14 +255,14 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(HkReceiver& recei store_address_t storeId; ReturnValue_t result = addUpdateToStore(updatePacket, storeId); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } CommandMessage notification; HousekeepingMessage::setUpdateSnapshotSetCommand(¬ification, receiver.dataId.sid, storeId); result = hkQueue->sendMessage(receiver.destinationQueue, ¬ification); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { status = result; } toReset = dataSet; @@ -270,7 +270,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(HkReceiver& recei if (toReset != nullptr) { handleChangeResetLogic(receiver.dataType, receiver.dataId, toReset); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t LocalDataPoolManager::addUpdateToStore(HousekeepingSnapshot& updatePacket, @@ -279,7 +279,7 @@ ReturnValue_t LocalDataPoolManager::addUpdateToStore(HousekeepingSnapshot& updat uint8_t* storePtr = nullptr; ReturnValue_t result = ipcStore->getFreeElement(&storeId, updatePacket.getSerializedSize(), &storePtr); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } size_t serializedSize = 0; @@ -291,12 +291,7 @@ ReturnValue_t LocalDataPoolManager::addUpdateToStore(HousekeepingSnapshot& updat void LocalDataPoolManager::handleChangeResetLogic(DataType type, DataId dataId, MarkChangedIF* toReset) { - if (hkUpdateResetList == nullptr) { - /* Config error */ - return; - } - HkUpdateResetList& listRef = *hkUpdateResetList; - for (auto& changeInfo : listRef) { + for (auto& changeInfo : hkUpdateResetList) { if (changeInfo.dataType != type) { continue; } @@ -326,72 +321,74 @@ void LocalDataPoolManager::handleChangeResetLogic(DataType type, DataId dataId, } void LocalDataPoolManager::resetHkUpdateResetHelper() { - if (hkUpdateResetList == nullptr) { - return; - } - - for (auto& changeInfo : *hkUpdateResetList) { + for (auto& changeInfo : hkUpdateResetList) { changeInfo.currentUpdateCounter = changeInfo.updateCounter; } } -ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, bool enableReporting, - float collectionInterval, - bool isDiagnostics, - object_id_t packetDestination) { - AcceptsHkPacketsIF* hkReceiverObject = - ObjectManager::instance()->get(packetDestination); - if (hkReceiverObject == nullptr) { - printWarningOrError(sif::OutputTypes::OUT_WARNING, "subscribeForPeriodicPacket", - QUEUE_OR_DESTINATION_INVALID); - return QUEUE_OR_DESTINATION_INVALID; - } +ReturnValue_t LocalDataPoolManager::subscribeForRegularPeriodicPacket( + subdp::RegularHkPeriodicParams params) { + return subscribeForPeriodicPacket(params); +} +ReturnValue_t LocalDataPoolManager::subscribeForDiagPeriodicPacket( + subdp::DiagnosticsHkPeriodicParams params) { + return subscribeForPeriodicPacket(params); +} + +ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(subdp::ParamsBase& params) { struct HkReceiver hkReceiver; - hkReceiver.dataId.sid = sid; + hkReceiver.dataId.sid = params.sid; hkReceiver.reportingType = ReportingType::PERIODIC; hkReceiver.dataType = DataType::DATA_SET; - hkReceiver.destinationQueue = hkReceiverObject->getHkQueue(); + if (params.receiver == MessageQueueIF::NO_QUEUE) { + hkReceiver.destinationQueue = hkDestinationId; + } else { + hkReceiver.destinationQueue = params.receiver; + } - LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); + LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid); if (dataSet != nullptr) { - LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enableReporting); - LocalPoolDataSetAttorney::setDiagnostic(*dataSet, isDiagnostics); - LocalPoolDataSetAttorney::initializePeriodicHelper(*dataSet, collectionInterval, + LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, params.enableReporting); + LocalPoolDataSetAttorney::setDiagnostic(*dataSet, params.isDiagnostics()); + LocalPoolDataSetAttorney::initializePeriodicHelper(*dataSet, params.collectionInterval, owner->getPeriodicOperationFrequency()); } hkReceivers.push_back(hkReceiver); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } -ReturnValue_t LocalDataPoolManager::subscribeForUpdatePacket(sid_t sid, bool isDiagnostics, - bool reportingEnabled, - object_id_t packetDestination) { - AcceptsHkPacketsIF* hkReceiverObject = - ObjectManager::instance()->get(packetDestination); - if (hkReceiverObject == nullptr) { - printWarningOrError(sif::OutputTypes::OUT_WARNING, "subscribeForPeriodicPacket", - QUEUE_OR_DESTINATION_INVALID); - return QUEUE_OR_DESTINATION_INVALID; - } +ReturnValue_t LocalDataPoolManager::subscribeForRegularUpdatePacket( + subdp::RegularHkUpdateParams params) { + return subscribeForUpdatePacket(params); +} +ReturnValue_t LocalDataPoolManager::subscribeForDiagUpdatePacket( + subdp::DiagnosticsHkUpdateParams params) { + return subscribeForUpdatePacket(params); +} +ReturnValue_t LocalDataPoolManager::subscribeForUpdatePacket(subdp::ParamsBase& params) { struct HkReceiver hkReceiver; - hkReceiver.dataId.sid = sid; + hkReceiver.dataId.sid = params.sid; hkReceiver.reportingType = ReportingType::UPDATE_HK; hkReceiver.dataType = DataType::DATA_SET; - hkReceiver.destinationQueue = hkReceiverObject->getHkQueue(); + if (params.receiver == MessageQueueIF::NO_QUEUE) { + hkReceiver.destinationQueue = hkDestinationId; + } else { + hkReceiver.destinationQueue = params.receiver; + } - LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); + LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid); if (dataSet != nullptr) { LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, true); - LocalPoolDataSetAttorney::setDiagnostic(*dataSet, isDiagnostics); + LocalPoolDataSetAttorney::setDiagnostic(*dataSet, params.isDiagnostics()); } hkReceivers.push_back(hkReceiver); handleHkUpdateResetListInsertion(hkReceiver.dataType, hkReceiver.dataId); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t LocalDataPoolManager::subscribeForSetUpdateMessage(const uint32_t setId, @@ -412,7 +409,7 @@ ReturnValue_t LocalDataPoolManager::subscribeForSetUpdateMessage(const uint32_t hkReceivers.push_back(hkReceiver); handleHkUpdateResetListInsertion(hkReceiver.dataType, hkReceiver.dataId); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t LocalDataPoolManager::subscribeForVariableUpdateMessage( @@ -432,15 +429,11 @@ ReturnValue_t LocalDataPoolManager::subscribeForVariableUpdateMessage( hkReceivers.push_back(hkReceiver); handleHkUpdateResetListInsertion(hkReceiver.dataType, hkReceiver.dataId); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void LocalDataPoolManager::handleHkUpdateResetListInsertion(DataType dataType, DataId dataId) { - if (hkUpdateResetList == nullptr) { - hkUpdateResetList = new std::vector(); - } - - for (auto& updateResetStruct : *hkUpdateResetList) { + for (auto& updateResetStruct : hkUpdateResetList) { if (dataType == DataType::DATA_SET) { if (updateResetStruct.dataId.sid == dataId.sid) { updateResetStruct.updateCounter++; @@ -464,13 +457,13 @@ void LocalDataPoolManager::handleHkUpdateResetListInsertion(DataType dataType, D } else { hkUpdateResetHelper.dataId.localPoolId = dataId.localPoolId; } - hkUpdateResetList->push_back(hkUpdateResetHelper); + hkUpdateResetList.push_back(hkUpdateResetHelper); } ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* message) { Command_t command = message->getCommand(); sid_t sid = HousekeepingMessage::getSid(message); - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; switch (command) { // Houskeeping interface handling. case (HousekeepingMessage::ENABLE_PERIODIC_DIAGNOSTICS_GENERATION): { @@ -495,7 +488,7 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me case (HousekeepingMessage::REPORT_DIAGNOSTICS_REPORT_STRUCTURES): { result = generateSetStructurePacket(sid, true); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { return result; } break; @@ -503,7 +496,7 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me case (HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES): { result = generateSetStructurePacket(sid, false); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { return result; } break; @@ -543,12 +536,12 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me /* Notification handling */ case (HousekeepingMessage::UPDATE_NOTIFICATION_SET): { owner->handleChangedDataset(sid); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } case (HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE): { gp_id_t globPoolId = HousekeepingMessage::getUpdateNotificationVariableCommand(message); owner->handleChangedPoolVariable(globPoolId); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } case (HousekeepingMessage::UPDATE_SNAPSHOT_SET): { store_address_t storeId; @@ -558,7 +551,7 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me if (clearMessage) { message->clear(); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } case (HousekeepingMessage::UPDATE_SNAPSHOT_VARIABLE): { store_address_t storeId; @@ -568,7 +561,7 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me if (clearMessage) { message->clear(); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } default: @@ -576,7 +569,7 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me } CommandMessage reply; - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { HousekeepingMessage::setHkRequestFailureReply(&reply, sid, result); } else { HousekeepingMessage::setHkRequestSuccessReply(&reply, sid); @@ -593,7 +586,7 @@ ReturnValue_t LocalDataPoolManager::printPoolEntry(lp_id_t localPoolId) { return localpool::POOL_ENTRY_NOT_FOUND; } poolIter->second->print(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } MutexIF* LocalDataPoolManager::getMutexHandle() { return mutex; } @@ -616,7 +609,7 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid, size_t serializedSize = 0; ReturnValue_t result = serializeHkPacketIntoStore(hkPacket, storeId, forDownlink, &serializedSize); - if (result != HasReturnvaluesIF::RETURN_OK or serializedSize == 0) { + if (result != returnvalue::OK or serializedSize == 0) { return result; } @@ -639,6 +632,7 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid, /* Error, all destinations invalid */ printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateHousekeepingPacket", QUEUE_OR_DESTINATION_INVALID); + return QUEUE_OR_DESTINATION_INVALID; } destination = hkDestinationId; } @@ -653,7 +647,7 @@ ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore(HousekeepingPacke uint8_t* dataPtr = nullptr; const size_t maxSize = hkPacket.getSerializedSize(); ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize, &dataPtr); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -693,12 +687,13 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) { } ReturnValue_t result = generateHousekeepingPacket(sid, dataSet, true); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { /* Configuration error */ #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "LocalDataPoolManager::performHkOperation: HK generation failed." << std::endl; + sif::warning << "LocalDataPoolManager::performPeriodicHkOperation: HK generation failed." + << std::endl; #else - sif::printWarning("LocalDataPoolManager::performHkOperation: HK generation failed.\n"); + sif::printWarning("LocalDataPoolManager::performPeriodicHkOperation: HK generation failed.\n"); #endif } } @@ -723,7 +718,7 @@ ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool ena } LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enable); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float newCollectionInterval, @@ -749,7 +744,7 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float ne } periodicHelper->changeCollectionInterval(newCollectionInterval); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool isDiagnostics) { @@ -777,24 +772,22 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool i uint8_t* storePtr = nullptr; store_address_t storeId; ReturnValue_t result = ipcStore->getFreeElement(&storeId, expectedSize, &storePtr); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { printWarningOrError(sif::OutputTypes::OUT_ERROR, "generateSetStructurePacket", - HasReturnvaluesIF::RETURN_FAILED, - "Could not get free element from IPC store."); + returnvalue::FAILED, "Could not get free element from IPC store."); return result; } // Serialize set packet into store. size_t size = 0; result = setPacket.serialize(&storePtr, &size, expectedSize, SerializeIF::Endianness::BIG); - if(result != HasReturnvaluesIF::RETURN_OK) { - ipcStore->deleteData(storeId); - return result; + if (result != returnvalue::OK) { + ipcStore->deleteData(storeId); + return result; } if (expectedSize != size) { printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateSetStructurePacket", - HasReturnvaluesIF::RETURN_FAILED, - "Expected size is not equal to serialized size"); + returnvalue::FAILED, "Expected size is not equal to serialized size"); } // Send structure reporting reply. @@ -806,8 +799,8 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool i } result = hkQueue->reply(&reply); - if(result != HasReturnvaluesIF::RETURN_OK) { - ipcStore->deleteData(storeId); + if (result != returnvalue::OK) { + ipcStore->deleteData(storeId); } return result; } @@ -816,9 +809,7 @@ void LocalDataPoolManager::clearReceiversList() { /* Clear the vector completely and releases allocated memory. */ HkReceivers().swap(hkReceivers); /* Also clear the reset helper if it exists */ - if (hkUpdateResetList != nullptr) { - HkUpdateResetList().swap(*hkUpdateResetList); - } + HkUpdateResetList().swap(hkUpdateResetList); } MutexIF* LocalDataPoolManager::getLocalPoolMutex() { return this->mutex; } @@ -834,7 +825,7 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType, errorPrint = "Dataset not found"; } else if (error == POOLOBJECT_NOT_FOUND) { errorPrint = "Pool Object not found"; - } else if (error == HasReturnvaluesIF::RETURN_FAILED) { + } else if (error == returnvalue::FAILED) { if (outputType == sif::OutputTypes::OUT_WARNING) { errorPrint = "Generic Warning"; } else { @@ -878,3 +869,7 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType, } LocalDataPoolManager* LocalDataPoolManager::getPoolManagerHandle() { return this; } + +void LocalDataPoolManager::setHkDestinationId(MessageQueueId_t hkDestId) { + hkDestinationId = hkDestId; +} diff --git a/src/fsfw/datapoollocal/LocalDataPoolManager.h b/src/fsfw/datapoollocal/LocalDataPoolManager.h index e7ec0b6f..8f369ea0 100644 --- a/src/fsfw/datapoollocal/LocalDataPoolManager.h +++ b/src/fsfw/datapoollocal/LocalDataPoolManager.h @@ -8,6 +8,7 @@ #include "ProvidesDataPoolSubscriptionIF.h" #include "fsfw/datapool/DataSetIF.h" #include "fsfw/datapool/PoolEntry.h" +#include "fsfw/housekeeping/AcceptsHkPacketsIF.h" #include "fsfw/housekeeping/HousekeepingMessage.h" #include "fsfw/housekeeping/HousekeepingPacketDownlink.h" #include "fsfw/housekeeping/PeriodicHousekeepingHelper.h" @@ -80,7 +81,9 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces */ LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse, bool appendValidityBuffer = true); - virtual ~LocalDataPoolManager(); + ~LocalDataPoolManager() override; + + void setHkDestinationId(MessageQueueId_t hkDestId); /** * Assigns the queue to use. Make sure to call this in the #initialize @@ -112,31 +115,6 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces */ virtual ReturnValue_t performHkOperation(); - /** - * @brief Subscribe for the generation of periodic packets. - * @details - * This subscription mechanism will generally be used by the data creator - * to generate housekeeping packets which are downlinked directly. - * @return - */ - ReturnValue_t subscribeForPeriodicPacket( - sid_t sid, bool enableReporting, float collectionInterval, bool isDiagnostics, - object_id_t packetDestination = defaultHkDestination) override; - - /** - * @brief Subscribe for the generation of packets if the dataset - * is marked as changed. - * @details - * This subscription mechanism will generally be used by the data creator. - * @param sid - * @param isDiagnostics - * @param packetDestination - * @return - */ - ReturnValue_t subscribeForUpdatePacket( - sid_t sid, bool reportingEnabled, bool isDiagnostics, - object_id_t packetDestination = defaultHkDestination) override; - /** * @brief Subscribe for a notification message which will be sent * if a dataset has changed. @@ -151,7 +129,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces * Otherwise, only an notification message is sent. * @return */ - ReturnValue_t subscribeForSetUpdateMessage(const uint32_t setId, object_id_t destinationObject, + ReturnValue_t subscribeForSetUpdateMessage(uint32_t setId, object_id_t destinationObject, MessageQueueId_t targetQueueId, bool generateSnapshot) override; @@ -169,7 +147,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces * Otherwise, only an notification message is sent. * @return */ - ReturnValue_t subscribeForVariableUpdateMessage(const lp_id_t localPoolId, + ReturnValue_t subscribeForVariableUpdateMessage(lp_id_t localPoolId, object_id_t destinationObject, MessageQueueId_t targetQueueId, bool generateSnapshot) override; @@ -252,7 +230,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces */ void clearReceiversList(); - object_id_t getCreatorObjectId() const; + [[nodiscard]] object_id_t getCreatorObjectId() const; /** * Get the pointer to the mutex. Can be used to lock the data pool @@ -262,9 +240,17 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces */ MutexIF* getMutexHandle(); - virtual LocalDataPoolManager* getPoolManagerHandle() override; + LocalDataPoolManager* getPoolManagerHandle() override; + ReturnValue_t subscribeForRegularPeriodicPacket(subdp::RegularHkPeriodicParams params) override; + ReturnValue_t subscribeForDiagPeriodicPacket(subdp::DiagnosticsHkPeriodicParams params) override; + + ReturnValue_t subscribeForRegularUpdatePacket(subdp::RegularHkUpdateParams params) override; + ReturnValue_t subscribeForDiagUpdatePacket(subdp::DiagnosticsHkUpdateParams params) override; protected: + ReturnValue_t subscribeForPeriodicPacket(subdp::ParamsBase& params); + ReturnValue_t subscribeForUpdatePacket(subdp::ParamsBase& params); + /** Core data structure for the actual pool data */ localpool::DataPool localPoolMap; /** Every housekeeping data manager has a mutex to protect access @@ -312,8 +298,8 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces using HkUpdateResetList = std::vector; /** This list is used to manage creating multiple update packets and only resetting - the update flag if all of them were created. Will only be created when needed. */ - HkUpdateResetList* hkUpdateResetList = nullptr; + the update flag if all of them were created. */ + HkUpdateResetList hkUpdateResetList = HkUpdateResetList(); /** This is the map holding the actual data. Should only be initialized * once ! */ @@ -376,7 +362,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces ReturnValue_t addUpdateToStore(HousekeepingSnapshot& updatePacket, store_address_t& storeId); void printWarningOrError(sif::OutputTypes outputType, const char* functionName, - ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED, + ReturnValue_t errorCode = returnvalue::FAILED, const char* errorPrint = nullptr); }; @@ -384,7 +370,7 @@ template inline ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId, PoolEntry** poolEntry) { if (poolEntry == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } auto poolIter = localPoolMap.find(localPoolId); @@ -400,7 +386,7 @@ inline ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId, localpool::POOL_ENTRY_TYPE_CONFLICT); return localpool::POOL_ENTRY_TYPE_CONFLICT; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } #endif /* FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_ */ diff --git a/src/fsfw/datapoollocal/LocalPoolDataSetBase.cpp b/src/fsfw/datapoollocal/LocalPoolDataSetBase.cpp index 4a076212..38aad828 100644 --- a/src/fsfw/datapoollocal/LocalPoolDataSetBase.cpp +++ b/src/fsfw/datapoollocal/LocalPoolDataSetBase.cpp @@ -85,22 +85,23 @@ ReturnValue_t LocalPoolDataSetBase::lockDataPool(MutexIF::TimeoutType timeoutTyp if (mutexIfSingleDataCreator != nullptr) { return mutexIfSingleDataCreator->lockMutex(timeoutType, timeoutMs); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer( uint8_t **buffer, size_t *size, size_t maxSize, SerializeIF::Endianness streamEndianness) const { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; const uint8_t validityMaskSize = std::ceil(static_cast(fillCount) / 8.0); uint8_t *validityPtr = nullptr; -#ifdef _MSC_VER - /* Use a std::vector here because MSVC will (rightly) not create a fixed size array - with a non constant size specifier */ - std::vector validityMask(validityMaskSize); +#if defined(_MSC_VER) || defined(__clang__) + // Use a std::vector here because MSVC will (rightly) not create a fixed size array + // with a non constant size specifier. The Apple compiler (LLVM) will not accept + // the initialization of a variable sized array + std::vector validityMask(validityMaskSize, 0); validityPtr = validityMask.data(); #else - uint8_t validityMask[validityMaskSize] = {0}; + uint8_t validityMask[validityMaskSize] = {}; validityPtr = validityMask; #endif uint8_t validBufferIndex = 0; @@ -118,7 +119,7 @@ ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer( } result = registeredVariables[count]->serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } } @@ -134,10 +135,10 @@ ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer( ReturnValue_t LocalPoolDataSetBase::deSerializeWithValidityBuffer( const uint8_t **buffer, size_t *size, SerializeIF::Endianness streamEndianness) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t result = returnvalue::FAILED; for (uint16_t count = 0; count < fillCount; count++) { result = registeredVariables[count]->deSerialize(buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } } @@ -168,7 +169,7 @@ ReturnValue_t LocalPoolDataSetBase::unlockDataPool() { if (mutexIfSingleDataCreator != nullptr) { return mutexIfSingleDataCreator->unlockMutex(); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t **buffer, size_t *size, @@ -184,7 +185,7 @@ ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t **buffer, size lp_id_t currentPoolId = registeredVariables[count]->getDataPoolId(); auto result = SerializeAdapter::serialize(¤tPoolId, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "LocalPoolDataSetBase::serializeLocalPoolIds: " << "Serialization error!" << std::endl; @@ -196,7 +197,7 @@ ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t **buffer, size return result; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } uint8_t LocalPoolDataSetBase::getLocalPoolIdsSerializedSize(bool serializeFillCount) const { diff --git a/src/fsfw/datapoollocal/LocalPoolObjectBase.cpp b/src/fsfw/datapoollocal/LocalPoolObjectBase.cpp index 82aefc18..5575c3d8 100644 --- a/src/fsfw/datapoollocal/LocalPoolObjectBase.cpp +++ b/src/fsfw/datapoollocal/LocalPoolObjectBase.cpp @@ -48,12 +48,12 @@ LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, if (hkOwner == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "LocalPoolVariable: The supplied pool owner 0x" << std::hex << poolOwner - << std::dec << " did not implement the correct interface " + << std::dec << " does not exist or does not implement the correct interface " << "HasLocalDataPoolIF" << std::endl; #else sif::printError( - "LocalPoolVariable: The supplied pool owner 0x%08x did not implement the correct " - "interface HasLocalDataPoolIF\n", + "LocalPoolVariable: The supplied pool owner 0x%08x does not exist or does not implement " + "the correct interface HasLocalDataPoolIF\n", poolOwner); #endif return; diff --git a/src/fsfw/datapoollocal/LocalPoolObjectBase.h b/src/fsfw/datapoollocal/LocalPoolObjectBase.h index 56e190df..a4ecbd55 100644 --- a/src/fsfw/datapoollocal/LocalPoolObjectBase.h +++ b/src/fsfw/datapoollocal/LocalPoolObjectBase.h @@ -4,7 +4,7 @@ #include "MarkChangedIF.h" #include "fsfw/datapool/PoolVariableIF.h" #include "fsfw/objectmanager/SystemObjectIF.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "localPoolDefinitions.h" class LocalDataPoolManager; @@ -15,7 +15,7 @@ class HasLocalDataPoolIF; * @brief This class serves as a non-template base for pool objects like pool variables * or pool vectors. */ -class LocalPoolObjectBase : public PoolVariableIF, public HasReturnvaluesIF, public MarkChangedIF { +class LocalPoolObjectBase : public PoolVariableIF, public MarkChangedIF { public: LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet, pool_rwm_t setReadWriteMode); @@ -23,8 +23,8 @@ class LocalPoolObjectBase : public PoolVariableIF, public HasReturnvaluesIF, pub LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, DataSetIF* dataSet = nullptr, pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE); - void setReadWriteMode(pool_rwm_t newReadWriteMode); - pool_rwm_t getReadWriteMode() const; + void setReadWriteMode(pool_rwm_t newReadWriteMode) override; + pool_rwm_t getReadWriteMode() const override; bool isValid() const override; void setValid(bool valid) override; diff --git a/src/fsfw/datapoollocal/LocalPoolVariable.h b/src/fsfw/datapoollocal/LocalPoolVariable.h index 818e4883..76b36503 100644 --- a/src/fsfw/datapoollocal/LocalPoolVariable.h +++ b/src/fsfw/datapoollocal/LocalPoolVariable.h @@ -87,9 +87,9 @@ class LocalPoolVariable : public LocalPoolObjectBase { ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, SerializeIF::Endianness streamEndianness) const override; - virtual size_t getSerializedSize() const override; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - SerializeIF::Endianness streamEndianness) override; + size_t getSerializedSize() const override; + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override; /** * @brief This is a call to read the array's values diff --git a/src/fsfw/datapoollocal/LocalPoolVariable.tpp b/src/fsfw/datapoollocal/LocalPoolVariable.tpp index 9bb30611..969a047b 100644 --- a/src/fsfw/datapoollocal/LocalPoolVariable.tpp +++ b/src/fsfw/datapoollocal/LocalPoolVariable.tpp @@ -5,205 +5,189 @@ #error Include LocalPoolVariable.h before LocalPoolVariable.tpp! #endif -template -inline LocalPoolVariable::LocalPoolVariable(HasLocalDataPoolIF* hkOwner, - lp_id_t poolId, DataSetIF* dataSet, pool_rwm_t setReadWriteMode): - LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {} +template +inline LocalPoolVariable::LocalPoolVariable(HasLocalDataPoolIF* hkOwner, lp_id_t poolId, + DataSetIF* dataSet, pool_rwm_t setReadWriteMode) + : LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {} -template -inline LocalPoolVariable::LocalPoolVariable(object_id_t poolOwner, - lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode): - LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {} +template +inline LocalPoolVariable::LocalPoolVariable(object_id_t poolOwner, lp_id_t poolId, + DataSetIF* dataSet, pool_rwm_t setReadWriteMode) + : LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {} +template +inline LocalPoolVariable::LocalPoolVariable(gp_id_t globalPoolId, DataSetIF* dataSet, + pool_rwm_t setReadWriteMode) + : LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, dataSet, + setReadWriteMode) {} -template -inline LocalPoolVariable::LocalPoolVariable(gp_id_t globalPoolId, - DataSetIF *dataSet, pool_rwm_t setReadWriteMode): - LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, - dataSet, setReadWriteMode){} - - -template -inline ReturnValue_t LocalPoolVariable::read( - MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { - if(hkManager == nullptr) { - return readWithoutLock(); - } - MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager); - ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - result = readWithoutLock(); - mutex->unlockMutex(); +template +inline ReturnValue_t LocalPoolVariable::read(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + if (hkManager == nullptr) { + return readWithoutLock(); + } + MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager); + ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs); + if (result != returnvalue::OK) { return result; + } + result = readWithoutLock(); + mutex->unlockMutex(); + return result; } -template +template inline ReturnValue_t LocalPoolVariable::readWithoutLock() { - if(readWriteMode == pool_rwm_t::VAR_WRITE) { - object_id_t targetObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVector", - PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId, - localPoolId); - return PoolVariableIF::INVALID_READ_WRITE_MODE; - } + if (readWriteMode == pool_rwm_t::VAR_WRITE) { + object_id_t targetObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, true, + targetObjectId, localPoolId); + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } - PoolEntry* poolEntry = nullptr; - ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, - &poolEntry); - if(result != RETURN_OK) { - object_id_t ownerObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVariable", result, - false, ownerObjectId, localPoolId); - return result; - } - - this->value = *(poolEntry->getDataPtr()); - this->valid = poolEntry->getValid(); - return RETURN_OK; -} - -template -inline ReturnValue_t LocalPoolVariable::commit(bool setValid, - MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { - this->setValid(setValid); - return commit(timeoutType, timeoutMs); -} - -template -inline ReturnValue_t LocalPoolVariable::commit( - MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { - if(hkManager == nullptr) { - return commitWithoutLock(); - } - MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager); - ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - result = commitWithoutLock(); - mutex->unlockMutex(); + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = + LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry); + if (result != returnvalue::OK) { + object_id_t ownerObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVariable", result, false, ownerObjectId, localPoolId); return result; + } + + this->value = *(poolEntry->getDataPtr()); + this->valid = poolEntry->getValid(); + return returnvalue::OK; } -template +template +inline ReturnValue_t LocalPoolVariable::commit(bool setValid, MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + this->setValid(setValid); + return commit(timeoutType, timeoutMs); +} + +template +inline ReturnValue_t LocalPoolVariable::commit(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + if (hkManager == nullptr) { + return commitWithoutLock(); + } + MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager); + ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs); + if (result != returnvalue::OK) { + return result; + } + result = commitWithoutLock(); + mutex->unlockMutex(); + return result; +} + +template inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { - if(readWriteMode == pool_rwm_t::VAR_READ) { - object_id_t targetObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVector", - PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId, - localPoolId); - return PoolVariableIF::INVALID_READ_WRITE_MODE; - } + if (readWriteMode == pool_rwm_t::VAR_READ) { + object_id_t targetObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, false, + targetObjectId, localPoolId); + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } - PoolEntry* poolEntry = nullptr; - ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, - &poolEntry); - if(result != RETURN_OK) { - object_id_t ownerObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVariable", result, - false, ownerObjectId, localPoolId); - return result; - } + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = + LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry); + if (result != returnvalue::OK) { + object_id_t ownerObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVariable", result, false, ownerObjectId, localPoolId); + return result; + } - *(poolEntry->getDataPtr()) = this->value; - poolEntry->setValid(this->valid); - return RETURN_OK; + *(poolEntry->getDataPtr()) = this->value; + poolEntry->setValid(this->valid); + return returnvalue::OK; } -template -inline ReturnValue_t LocalPoolVariable::serialize(uint8_t** buffer, - size_t* size, const size_t max_size, - SerializeIF::Endianness streamEndianness) const { - return SerializeAdapter::serialize(&value, - buffer, size ,max_size, streamEndianness); +template +inline ReturnValue_t LocalPoolVariable::serialize( + uint8_t** buffer, size_t* size, const size_t max_size, + SerializeIF::Endianness streamEndianness) const { + return SerializeAdapter::serialize(&value, buffer, size, max_size, streamEndianness); } -template +template inline size_t LocalPoolVariable::getSerializedSize() const { - return SerializeAdapter::getSerializedSize(&value); + return SerializeAdapter::getSerializedSize(&value); } -template -inline ReturnValue_t LocalPoolVariable::deSerialize(const uint8_t** buffer, - size_t* size, SerializeIF::Endianness streamEndianness) { - return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness); +template +inline ReturnValue_t LocalPoolVariable::deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) { + return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness); } #if FSFW_CPP_OSTREAM_ENABLED == 1 -template -inline std::ostream& operator<< (std::ostream &out, - const LocalPoolVariable &var) { - out << var.value; - return out; +template +inline std::ostream& operator<<(std::ostream& out, const LocalPoolVariable& var) { + out << var.value; + return out; } #endif -template +template inline LocalPoolVariable::operator T() const { - return value; + return value; } -template -inline LocalPoolVariable & LocalPoolVariable::operator=( - const T& newValue) { - value = newValue; - return *this; +template +inline LocalPoolVariable& LocalPoolVariable::operator=(const T& newValue) { + value = newValue; + return *this; } -template -inline LocalPoolVariable& LocalPoolVariable::operator =( - const LocalPoolVariable& newPoolVariable) { - value = newPoolVariable.value; - return *this; +template +inline LocalPoolVariable& LocalPoolVariable::operator=( + const LocalPoolVariable& newPoolVariable) { + value = newPoolVariable.value; + return *this; } -template -inline bool LocalPoolVariable::operator ==( - const LocalPoolVariable &other) const { - return this->value == other.value; +template +inline bool LocalPoolVariable::operator==(const LocalPoolVariable& other) const { + return this->value == other.value; } -template -inline bool LocalPoolVariable::operator ==(const T &other) const { - return this->value == other; +template +inline bool LocalPoolVariable::operator==(const T& other) const { + return this->value == other; } - -template -inline bool LocalPoolVariable::operator !=( - const LocalPoolVariable &other) const { - return not (*this == other); +template +inline bool LocalPoolVariable::operator!=(const LocalPoolVariable& other) const { + return not(*this == other); } -template -inline bool LocalPoolVariable::operator !=(const T &other) const { - return not (*this == other); +template +inline bool LocalPoolVariable::operator!=(const T& other) const { + return not(*this == other); } - -template -inline bool LocalPoolVariable::operator <( - const LocalPoolVariable &other) const { - return this->value < other.value; +template +inline bool LocalPoolVariable::operator<(const LocalPoolVariable& other) const { + return this->value < other.value; } -template -inline bool LocalPoolVariable::operator <(const T &other) const { - return this->value < other; +template +inline bool LocalPoolVariable::operator<(const T& other) const { + return this->value < other; } - -template -inline bool LocalPoolVariable::operator >( - const LocalPoolVariable &other) const { - return not (*this < other); +template +inline bool LocalPoolVariable::operator>(const LocalPoolVariable& other) const { + return not(*this < other); } -template -inline bool LocalPoolVariable::operator >(const T &other) const { - return not (*this < other); +template +inline bool LocalPoolVariable::operator>(const T& other) const { + return not(*this < other); } #endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ */ diff --git a/src/fsfw/datapoollocal/LocalPoolVector.h b/src/fsfw/datapoollocal/LocalPoolVector.h index aaaa051d..d340f2de 100644 --- a/src/fsfw/datapoollocal/LocalPoolVector.h +++ b/src/fsfw/datapoollocal/LocalPoolVector.h @@ -98,11 +98,11 @@ class LocalPoolVector : public LocalPoolObjectBase { T& operator[](size_t i); const T& operator[](size_t i) const; - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize, - SerializeIF::Endianness streamEndiannes) const override; - virtual size_t getSerializedSize() const override; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - SerializeIF::Endianness streamEndianness) override; + ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize, + SerializeIF::Endianness streamEndiannes) const override; + size_t getSerializedSize() const override; + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override; /** * @brief This is a call to read the array's values diff --git a/src/fsfw/datapoollocal/LocalPoolVector.tpp b/src/fsfw/datapoollocal/LocalPoolVector.tpp index 044b8fa7..939405a9 100644 --- a/src/fsfw/datapoollocal/LocalPoolVector.tpp +++ b/src/fsfw/datapoollocal/LocalPoolVector.tpp @@ -5,174 +5,172 @@ #error Include LocalPoolVector.h before LocalPoolVector.tpp! #endif -template -inline LocalPoolVector::LocalPoolVector( - HasLocalDataPoolIF* hkOwner, lp_id_t poolId, DataSetIF* dataSet, - pool_rwm_t setReadWriteMode): - LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {} +template +inline LocalPoolVector::LocalPoolVector(HasLocalDataPoolIF* hkOwner, lp_id_t poolId, + DataSetIF* dataSet, + pool_rwm_t setReadWriteMode) + : LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {} -template -inline LocalPoolVector::LocalPoolVector(object_id_t poolOwner, - lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode): - LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {} +template +inline LocalPoolVector::LocalPoolVector(object_id_t poolOwner, lp_id_t poolId, + DataSetIF* dataSet, + pool_rwm_t setReadWriteMode) + : LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {} -template -inline LocalPoolVector::LocalPoolVector(gp_id_t globalPoolId, - DataSetIF *dataSet, pool_rwm_t setReadWriteMode): - LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, - dataSet, setReadWriteMode) {} +template +inline LocalPoolVector::LocalPoolVector(gp_id_t globalPoolId, DataSetIF* dataSet, + pool_rwm_t setReadWriteMode) + : LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, dataSet, + setReadWriteMode) {} -template -inline ReturnValue_t LocalPoolVector::read( - MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { - MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs); - return readWithoutLock(); +template +inline ReturnValue_t LocalPoolVector::read(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs); + return readWithoutLock(); } -template +template inline ReturnValue_t LocalPoolVector::readWithoutLock() { - if(readWriteMode == pool_rwm_t::VAR_WRITE) { - object_id_t targetObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVector", - PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId, - localPoolId); - return PoolVariableIF::INVALID_READ_WRITE_MODE; - } + if (readWriteMode == pool_rwm_t::VAR_WRITE) { + object_id_t targetObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, true, + targetObjectId, localPoolId); + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } - PoolEntry* poolEntry = nullptr; - ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, - &poolEntry); - memset(this->value, 0, vectorSize * sizeof(T)); + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = + LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry); + memset(this->value, 0, vectorSize * sizeof(T)); - if(result != RETURN_OK) { - object_id_t targetObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVector", result, true, targetObjectId, - localPoolId); - return result; - } - std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize()); - this->valid = poolEntry->getValid(); - return RETURN_OK; + if (result != returnvalue::OK) { + object_id_t targetObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVector", result, true, targetObjectId, localPoolId); + return result; + } + std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize()); + this->valid = poolEntry->getValid(); + return returnvalue::OK; } -template +template inline ReturnValue_t LocalPoolVector::commit(bool valid, - MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { - this->setValid(valid); - return commit(timeoutType, timeoutMs); + MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + this->setValid(valid); + return commit(timeoutType, timeoutMs); } -template -inline ReturnValue_t LocalPoolVector::commit( - MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { - MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs); - return commitWithoutLock(); +template +inline ReturnValue_t LocalPoolVector::commit(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs); + return commitWithoutLock(); } -template +template inline ReturnValue_t LocalPoolVector::commitWithoutLock() { - if(readWriteMode == pool_rwm_t::VAR_READ) { - object_id_t targetObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVector", - PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId, - localPoolId); - return PoolVariableIF::INVALID_READ_WRITE_MODE; - } - PoolEntry* poolEntry = nullptr; - ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, - &poolEntry); - if(result != RETURN_OK) { - object_id_t targetObjectId = hkManager->getCreatorObjectId(); - reportReadCommitError("LocalPoolVector", result, false, targetObjectId, - localPoolId); - return result; - } - std::memcpy(poolEntry->getDataPtr(), this->value, poolEntry->getByteSize()); - poolEntry->setValid(this->valid); - return RETURN_OK; -} - -template -inline T& LocalPoolVector::operator [](size_t i) { - if(i < vectorSize) { - return value[i]; - } - // If this happens, I have to set some value. I consider this - // a configuration error, but I wont exit here. -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "LocalPoolVector: Invalid index. Setting or returning" - " last value!" << std::endl; -#else - sif::printWarning("LocalPoolVector: Invalid index. Setting or returning" - " last value!\n"); -#endif - return value[vectorSize - 1]; -} - -template -inline const T& LocalPoolVector::operator [](size_t i) const { - if(i < vectorSize) { - return value[i]; - } - // If this happens, I have to set some value. I consider this - // a configuration error, but I wont exit here. -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "LocalPoolVector: Invalid index. Setting or returning" - " last value!" << std::endl; -#else - sif::printWarning("LocalPoolVector: Invalid index. Setting or returning" - " last value!\n"); -#endif - return value[vectorSize - 1]; -} - -template -inline ReturnValue_t LocalPoolVector::serialize(uint8_t** buffer, - size_t* size, size_t maxSize, - SerializeIF::Endianness streamEndianness) const { - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - for (uint16_t i = 0; i < vectorSize; i++) { - result = SerializeAdapter::serialize(&(value[i]), buffer, size, - maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - break; - } - } + if (readWriteMode == pool_rwm_t::VAR_READ) { + object_id_t targetObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, false, + targetObjectId, localPoolId); + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = + LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry); + if (result != returnvalue::OK) { + object_id_t targetObjectId = hkManager->getCreatorObjectId(); + reportReadCommitError("LocalPoolVector", result, false, targetObjectId, localPoolId); return result; + } + std::memcpy(poolEntry->getDataPtr(), this->value, poolEntry->getByteSize()); + poolEntry->setValid(this->valid); + return returnvalue::OK; } -template +template +inline T& LocalPoolVector::operator[](size_t i) { + if (i < vectorSize) { + return value[i]; + } + // If this happens, I have to set some value. I consider this + // a configuration error, but I wont exit here. +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "LocalPoolVector: Invalid index. Setting or returning" + " last value!" + << std::endl; +#else + sif::printWarning( + "LocalPoolVector: Invalid index. Setting or returning" + " last value!\n"); +#endif + return value[vectorSize - 1]; +} + +template +inline const T& LocalPoolVector::operator[](size_t i) const { + if (i < vectorSize) { + return value[i]; + } + // If this happens, I have to set some value. I consider this + // a configuration error, but I wont exit here. +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "LocalPoolVector: Invalid index. Setting or returning" + " last value!" + << std::endl; +#else + sif::printWarning( + "LocalPoolVector: Invalid index. Setting or returning" + " last value!\n"); +#endif + return value[vectorSize - 1]; +} + +template +inline ReturnValue_t LocalPoolVector::serialize( + uint8_t** buffer, size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const { + ReturnValue_t result = returnvalue::FAILED; + for (uint16_t i = 0; i < vectorSize; i++) { + result = SerializeAdapter::serialize(&(value[i]), buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + break; + } + } + return result; +} + +template inline size_t LocalPoolVector::getSerializedSize() const { - return vectorSize * SerializeAdapter::getSerializedSize(value); + return vectorSize * SerializeAdapter::getSerializedSize(value); } -template +template inline ReturnValue_t LocalPoolVector::deSerialize( - const uint8_t** buffer, size_t* size, - SerializeIF::Endianness streamEndianness) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - for (uint16_t i = 0; i < vectorSize; i++) { - result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, - streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - break; - } + const uint8_t** buffer, size_t* size, SerializeIF::Endianness streamEndianness) { + ReturnValue_t result = returnvalue::FAILED; + for (uint16_t i = 0; i < vectorSize; i++) { + result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, streamEndianness); + if (result != returnvalue::OK) { + break; } - return result; + } + return result; } #if FSFW_CPP_OSTREAM_ENABLED == 1 -template -inline std::ostream& operator<< (std::ostream &out, - const LocalPoolVector &var) { - out << "Vector: ["; - for(int i = 0;i < vectorSize; i++) { - out << var.value[i]; - if(i < vectorSize - 1) { - out << ", "; - } +template +inline std::ostream& operator<<(std::ostream& out, const LocalPoolVector& var) { + out << "Vector: ["; + for (int i = 0; i < vectorSize; i++) { + out << var.value[i]; + if (i < vectorSize - 1) { + out << ", "; } - out << "]"; - return out; + } + out << "]"; + return out; } #endif diff --git a/src/fsfw/datapoollocal/ProvidesDataPoolSubscriptionIF.h b/src/fsfw/datapoollocal/ProvidesDataPoolSubscriptionIF.h index 1f13a09d..baf91796 100644 --- a/src/fsfw/datapoollocal/ProvidesDataPoolSubscriptionIF.h +++ b/src/fsfw/datapoollocal/ProvidesDataPoolSubscriptionIF.h @@ -1,24 +1,90 @@ #ifndef FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_ #define FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_ -#include "../ipc/messageQueueDefinitions.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "fsfw/housekeeping/AcceptsHkPacketsIF.h" +#include "fsfw/ipc/MessageQueueIF.h" +#include "fsfw/ipc/messageQueueDefinitions.h" +#include "fsfw/returnvalues/returnvalue.h" #include "localPoolDefinitions.h" +namespace subdp { + +struct ParamsBase { + ParamsBase(sid_t sid, bool enableReporting, float collectionInterval, bool diagnostics) + : sid(sid), + enableReporting(enableReporting), + collectionInterval(collectionInterval), + diagnostics(diagnostics) {} + + [[nodiscard]] bool isDiagnostics() const { return diagnostics; } + + sid_t sid; + bool enableReporting; + float collectionInterval; + MessageQueueId_t receiver = MessageQueueIF::NO_QUEUE; + + protected: + bool diagnostics; +}; + +struct RegularHkPeriodicParams : public ParamsBase { + RegularHkPeriodicParams(sid_t sid, bool enableReporting, float collectionInterval) + : ParamsBase(sid, enableReporting, collectionInterval, false) {} +}; + +struct DiagnosticsHkPeriodicParams : public ParamsBase { + DiagnosticsHkPeriodicParams(sid_t sid, bool enableReporting, float collectionInterval) + : ParamsBase(sid, enableReporting, collectionInterval, true) {} +}; + +struct RegularHkUpdateParams : public ParamsBase { + RegularHkUpdateParams(sid_t sid, bool enableReporting) + : ParamsBase(sid, enableReporting, 0.0, false) {} +}; + +struct DiagnosticsHkUpdateParams : public ParamsBase { + DiagnosticsHkUpdateParams(sid_t sid, bool enableReporting) + : ParamsBase(sid, enableReporting, 0.0, true) {} +}; +} // namespace subdp + class ProvidesDataPoolSubscriptionIF { public: - virtual ~ProvidesDataPoolSubscriptionIF(){}; - + virtual ~ProvidesDataPoolSubscriptionIF() = default; /** - * @brief Subscribe for the generation of periodic packets. + * @brief Subscribe for the generation of periodic packets. Used for regular HK packets * @details * This subscription mechanism will generally be used by the data creator * to generate housekeeping packets which are downlinked directly. * @return */ - virtual ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting, - float collectionInterval, bool isDiagnostics, - object_id_t packetDestination) = 0; + virtual ReturnValue_t subscribeForRegularPeriodicPacket( + subdp::RegularHkPeriodicParams params) = 0; + /** + * @brief Subscribe for the generation of periodic packets. Used for diagnostic packets + * @details + * This subscription mechanism will generally be used by the data creator + * to generate housekeeping packets which are downlinked directly. + * @return + */ + virtual ReturnValue_t subscribeForDiagPeriodicPacket( + subdp::DiagnosticsHkPeriodicParams params) = 0; + + [[deprecated( + "Please use the new API which takes all arguments as one wrapper " + "struct")]] virtual ReturnValue_t + subscribeForPeriodicPacket(sid_t sid, bool enableReporting, float collectionInterval, + bool isDiagnostics, + object_id_t packetDestination = objects::NO_OBJECT) { + if (isDiagnostics) { + subdp::DiagnosticsHkPeriodicParams params(sid, enableReporting, collectionInterval); + return subscribeForDiagPeriodicPacket(params); + } else { + subdp::RegularHkPeriodicParams params(sid, enableReporting, collectionInterval); + return subscribeForRegularPeriodicPacket(params); + } + } + /** * @brief Subscribe for the generation of packets if the dataset * is marked as changed. @@ -29,9 +95,28 @@ class ProvidesDataPoolSubscriptionIF { * @param packetDestination * @return */ - virtual ReturnValue_t subscribeForUpdatePacket(sid_t sid, bool reportingEnabled, - bool isDiagnostics, - object_id_t packetDestination) = 0; + virtual ReturnValue_t subscribeForRegularUpdatePacket(subdp::RegularHkUpdateParams params) = 0; + virtual ReturnValue_t subscribeForDiagUpdatePacket(subdp::DiagnosticsHkUpdateParams params) = 0; + + // virtual ReturnValue_t + // subscribeForUpdatePacket(sid_t sid, bool reportingEnabled, bool isDiagnostics) { + // return subscribeForUpdatePacket(sid, reportingEnabled, isDiagnostics, objects::NO_OBJECT); + // } + + [[deprecated( + "Please use the new API which takes all arguments as one wrapper " + "struct")]] virtual ReturnValue_t + subscribeForUpdatePacket(sid_t sid, bool reportingEnabled, bool isDiagnostics, + object_id_t packetDestination = objects::NO_OBJECT) { + if (isDiagnostics) { + subdp::DiagnosticsHkUpdateParams params(sid, reportingEnabled); + return subscribeForDiagUpdatePacket(params); + } else { + subdp::RegularHkUpdateParams params(sid, reportingEnabled); + return subscribeForRegularUpdatePacket(params); + } + } + /** * @brief Subscribe for a notification message which will be sent * if a dataset has changed. @@ -46,8 +131,7 @@ class ProvidesDataPoolSubscriptionIF { * Otherwise, only an notification message is sent. * @return */ - virtual ReturnValue_t subscribeForSetUpdateMessage(const uint32_t setId, - object_id_t destinationObject, + virtual ReturnValue_t subscribeForSetUpdateMessage(uint32_t setId, object_id_t destinationObject, MessageQueueId_t targetQueueId, bool generateSnapshot) = 0; /** @@ -64,7 +148,7 @@ class ProvidesDataPoolSubscriptionIF { * only an notification message is sent. * @return */ - virtual ReturnValue_t subscribeForVariableUpdateMessage(const lp_id_t localPoolId, + virtual ReturnValue_t subscribeForVariableUpdateMessage(lp_id_t localPoolId, object_id_t destinationObject, MessageQueueId_t targetQueueId, bool generateSnapshot) = 0; diff --git a/src/fsfw/datapoollocal/SharedLocalDataSet.cpp b/src/fsfw/datapoollocal/SharedLocalDataSet.cpp index 248c1577..6d0b0b11 100644 --- a/src/fsfw/datapoollocal/SharedLocalDataSet.cpp +++ b/src/fsfw/datapoollocal/SharedLocalDataSet.cpp @@ -20,7 +20,7 @@ ReturnValue_t SharedLocalDataSet::lockDataset(MutexIF::TimeoutType timeoutType, if (datasetLock != nullptr) { return datasetLock->lockMutex(timeoutType, mutexTimeout); } - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } SharedLocalDataSet::~SharedLocalDataSet() { MutexFactory::instance()->deleteMutex(datasetLock); } @@ -29,5 +29,5 @@ ReturnValue_t SharedLocalDataSet::unlockDataset() { if (datasetLock != nullptr) { return datasetLock->unlockMutex(); } - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } diff --git a/src/fsfw/datapoollocal/internal/CMakeLists.txt b/src/fsfw/datapoollocal/internal/CMakeLists.txt index 554f3b88..6585d06e 100644 --- a/src/fsfw/datapoollocal/internal/CMakeLists.txt +++ b/src/fsfw/datapoollocal/internal/CMakeLists.txt @@ -1,5 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - HasLocalDpIFUserAttorney.cpp - HasLocalDpIFManagerAttorney.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE HasLocalDpIFUserAttorney.cpp + HasLocalDpIFManagerAttorney.cpp) diff --git a/src/fsfw/devicehandlers/AssemblyBase.cpp b/src/fsfw/devicehandlers/AssemblyBase.cpp index c29022e5..63178ab9 100644 --- a/src/fsfw/devicehandlers/AssemblyBase.cpp +++ b/src/fsfw/devicehandlers/AssemblyBase.cpp @@ -50,7 +50,7 @@ bool AssemblyBase::isInTransition() { bool AssemblyBase::handleChildrenChanged() { if (childrenChangedMode) { ReturnValue_t result = checkChildrenState(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { handleChildrenLostMode(result); } return true; @@ -116,7 +116,7 @@ void AssemblyBase::handleChildrenTransition() { break; } ReturnValue_t result = checkChildrenState(); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { handleModeReached(); } else { handleModeTransitionFailed(result); @@ -149,7 +149,7 @@ void AssemblyBase::handleModeTransitionFailed(ReturnValue_t result) { void AssemblyBase::sendHealthCommand(MessageQueueId_t sendTo, HealthState health) { CommandMessage command; HealthMessage::setHealthMessage(&command, HealthMessage::HEALTH_SET, health); - if (commandQueue->sendMessage(sendTo, &command) == RETURN_OK) { + if (commandQueue->sendMessage(sendTo, &command) == returnvalue::OK) { commandsOutstanding++; } } @@ -164,25 +164,25 @@ ReturnValue_t AssemblyBase::checkChildrenState() { ReturnValue_t AssemblyBase::checkChildrenStateOff() { for (const auto& childIter : childrenMap) { - if (checkChildOff(childIter.first) != RETURN_OK) { + if (checkChildOff(childIter.first) != returnvalue::OK) { return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE; } } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t AssemblyBase::checkChildOff(uint32_t objectId) { ChildInfo childInfo = childrenMap.find(objectId)->second; if (healthHelper.healthTable->isCommandable(objectId)) { if (childInfo.submode != SUBMODE_NONE) { - return RETURN_FAILED; + return returnvalue::FAILED; } else { if ((childInfo.mode != MODE_OFF) && (childInfo.mode != DeviceHandlerIF::MODE_ERROR_ON)) { - return RETURN_FAILED; + return returnvalue::FAILED; } } } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t AssemblyBase::checkModeCommand(Mode_t mode, Submode_t submode, @@ -192,7 +192,7 @@ ReturnValue_t AssemblyBase::checkModeCommand(Mode_t mode, Submode_t submode, if (submode != SUBMODE_NONE) { return INVALID_SUBMODE; } - return RETURN_OK; + return returnvalue::OK; } if ((mode != MODE_ON) && (mode != DeviceHandlerIF::MODE_NORMAL)) { @@ -212,7 +212,7 @@ ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) { if (health != EXTERNAL_CONTROL) { updateChildChangedHealth(message->getSender(), true); } - return RETURN_OK; + return returnvalue::OK; } if (message->getCommand() == HealthMessage::REPLY_HEALTH_SET || (message->getCommand() == CommandMessage::REPLY_REJECTED && @@ -220,9 +220,9 @@ ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) { if (isInTransition()) { commandsOutstanding--; } - return RETURN_OK; + return returnvalue::OK; } - return RETURN_FAILED; + return returnvalue::FAILED; } bool AssemblyBase::checkAndHandleRecovery() { diff --git a/src/fsfw/devicehandlers/AssemblyBase.h b/src/fsfw/devicehandlers/AssemblyBase.h index 3e235928..ec0847f1 100644 --- a/src/fsfw/devicehandlers/AssemblyBase.h +++ b/src/fsfw/devicehandlers/AssemblyBase.h @@ -53,7 +53,7 @@ class AssemblyBase : public SubsystemBase { * @param mode * @param submode * @return - * - @c RETURN_OK if ok + * - @c returnvalue::OK if ok * - @c NEED_SECOND_STEP if children need to be commanded again */ virtual ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) = 0; @@ -79,7 +79,7 @@ class AssemblyBase : public SubsystemBase { * @param submode The targeted submmode * @return Any information why this combination is invalid from HasModesIF * like HasModesIF::INVALID_SUBMODE. - * On success return HasReturnvaluesIF::RETURN_OK + * On success return returnvalue::OK */ virtual ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) = 0; diff --git a/src/fsfw/devicehandlers/CMakeLists.txt b/src/fsfw/devicehandlers/CMakeLists.txt index 50c1008f..180a89da 100644 --- a/src/fsfw/devicehandlers/CMakeLists.txt +++ b/src/fsfw/devicehandlers/CMakeLists.txt @@ -1,11 +1,10 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - AssemblyBase.cpp - ChildHandlerBase.cpp - ChildHandlerFDIR.cpp - DeviceHandlerBase.cpp - DeviceHandlerFailureIsolation.cpp - DeviceHandlerMessage.cpp - DeviceTmReportingWrapper.cpp - HealthDevice.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE AssemblyBase.cpp + ChildHandlerBase.cpp + ChildHandlerFDIR.cpp + DeviceHandlerBase.cpp + DeviceHandlerFailureIsolation.cpp + DeviceHandlerMessage.cpp + DeviceTmReportingWrapper.cpp + HealthDevice.cpp) diff --git a/src/fsfw/devicehandlers/ChildHandlerBase.cpp b/src/fsfw/devicehandlers/ChildHandlerBase.cpp index be4f4798..ecd4cfc8 100644 --- a/src/fsfw/devicehandlers/ChildHandlerBase.cpp +++ b/src/fsfw/devicehandlers/ChildHandlerBase.cpp @@ -19,7 +19,7 @@ ChildHandlerBase::~ChildHandlerBase() {} ReturnValue_t ChildHandlerBase::initialize() { ReturnValue_t result = DeviceHandlerBase::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -28,7 +28,7 @@ ReturnValue_t ChildHandlerBase::initialize() { if (parentId != objects::NO_OBJECT) { SubsystemBase* parent = ObjectManager::instance()->get(parentId); if (parent == NULL) { - return RETURN_FAILED; + return returnvalue::FAILED; } parentQueue = parent->getCommandQueue(); @@ -39,5 +39,5 @@ ReturnValue_t ChildHandlerBase::initialize() { modeHelper.setParentQueue(parentQueue); - return RETURN_OK; + return returnvalue::OK; } diff --git a/src/fsfw/devicehandlers/DeviceCommunicationIF.h b/src/fsfw/devicehandlers/DeviceCommunicationIF.h index 7a860411..a5546a36 100644 --- a/src/fsfw/devicehandlers/DeviceCommunicationIF.h +++ b/src/fsfw/devicehandlers/DeviceCommunicationIF.h @@ -1,7 +1,7 @@ #ifndef FSFW_DEVICES_DEVICECOMMUNICATIONIF_H_ #define FSFW_DEVICES_DEVICECOMMUNICATIONIF_H_ -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "CookieIF.h" #include "DeviceHandlerIF.h" /** @@ -34,7 +34,7 @@ * @ingroup interfaces * @ingroup comm */ -class DeviceCommunicationIF : public HasReturnvaluesIF { +class DeviceCommunicationIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_COMMUNICATION_IF; @@ -61,7 +61,7 @@ class DeviceCommunicationIF : public HasReturnvaluesIF { * initialization. * @param cookie * @return - * - @c RETURN_OK if initialization was successfull + * - @c returnvalue::OK if initialization was successfull * - Everything else triggers failure event with returnvalue as parameter 1 */ virtual ReturnValue_t initializeInterface(CookieIF *cookie) = 0; @@ -74,7 +74,7 @@ class DeviceCommunicationIF : public HasReturnvaluesIF { * @param data * @param len If this is 0, nothing shall be sent. * @return - * - @c RETURN_OK for successfull send + * - @c returnvalue::OK for successfull send * - Everything else triggers failure event with returnvalue as parameter 1 */ virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen) = 0; @@ -84,7 +84,7 @@ class DeviceCommunicationIF : public HasReturnvaluesIF { * Get send confirmation that the data in sendMessage() was sent successfully. * @param cookie * @return - * - @c RETURN_OK if data was sent successfully but a reply is expected + * - @c returnvalue::OK if data was sent successfully but a reply is expected * - NO_REPLY_EXPECTED if data was sent successfully and no reply is expected * - Everything else to indicate failure */ @@ -99,7 +99,7 @@ class DeviceCommunicationIF : public HasReturnvaluesIF { * * @param cookie * @param requestLen Size of data to read - * @return - @c RETURN_OK to confirm the request for data has been sent. + * @return - @c returnvalue::OK to confirm the request for data has been sent. * - Everything else triggers failure event with * returnvalue as parameter 1 */ @@ -113,7 +113,7 @@ class DeviceCommunicationIF : public HasReturnvaluesIF { * @param buffer [out] Set reply here (by using *buffer = ...) * @param size [out] size pointer to set (by using *size = ...). * Set to 0 if no reply was received - * @return - @c RETURN_OK for successfull receive + * @return - @c returnvalue::OK for successfull receive * - @c NO_REPLY_RECEIVED if not reply was received. Setting size to * 0 has the same effect * - Everything else triggers failure event with diff --git a/src/fsfw/devicehandlers/DeviceHandlerBase.cpp b/src/fsfw/devicehandlers/DeviceHandlerBase.cpp index 0e2802ac..bc528128 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerBase.cpp +++ b/src/fsfw/devicehandlers/DeviceHandlerBase.cpp @@ -1,5 +1,6 @@ #include "fsfw/devicehandlers/DeviceHandlerBase.h" +#include "fsfw/datapool/PoolReadGuard.h" #include "fsfw/datapoollocal/LocalPoolVariable.h" #include "fsfw/devicehandlers/AcceptsDeviceResponsesIF.h" #include "fsfw/devicehandlers/DeviceTmReportingWrapper.h" @@ -8,6 +9,7 @@ #include "fsfw/ipc/MessageQueueMessage.h" #include "fsfw/ipc/QueueFactory.h" #include "fsfw/objectmanager/ObjectManager.h" +#include "fsfw/serialize/SerialBufferAdapter.h" #include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/storagemanager/StorageManagerIF.h" #include "fsfw/subsystem/SubsystemBase.h" @@ -32,7 +34,7 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device parameterHelper(this), actionHelper(this, nullptr), poolManager(this, nullptr), - childTransitionFailure(RETURN_OK), + childTransitionFailure(returnvalue::OK), fdirInstance(fdirInstance), defaultFDIRUsed(fdirInstance == nullptr), switchOffWasReported(false), @@ -45,8 +47,8 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device cookieInfo.state = COOKIE_UNUSED; cookieInfo.pendingCommand = deviceCommandMap.end(); if (comCookie == nullptr) { - printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase", - HasReturnvaluesIF::RETURN_FAILED, "Invalid cookie"); + printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase", returnvalue::FAILED, + "Invalid cookie"); } if (this->fdirInstance == nullptr) { this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, defaultFdirParentId); @@ -65,7 +67,9 @@ void DeviceHandlerBase::setThermalStateRequestPoolIds(lp_id_t thermalStatePoolId } DeviceHandlerBase::~DeviceHandlerBase() { - delete comCookie; + if (comCookie != nullptr) { + delete comCookie; + } if (defaultFDIRUsed) { delete fdirInstance; } @@ -77,7 +81,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { this->lastStep = this->pstStep; if (getComAction() == CommunicationAction::NOTHING) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } if (getComAction() == CommunicationAction::PERFORM_OPERATION) { @@ -88,11 +92,11 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { decrementDeviceReplyMap(); fdirInstance->checkForFailures(); performOperationHook(); - return RETURN_OK; + return returnvalue::OK; } if (mode == MODE_OFF) { - return RETURN_OK; + return returnvalue::OK; } switch (getComAction()) { @@ -118,12 +122,12 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { default: break; } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t DeviceHandlerBase::initialize() { ReturnValue_t result = SystemObject::initialize(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -136,7 +140,7 @@ ReturnValue_t DeviceHandlerBase::initialize() { } result = communicationInterface->initializeInterface(comCookie); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize", ObjectManagerIF::CHILD_INIT_FAILED, "ComIF initialization failed"); return result; @@ -190,30 +194,30 @@ ReturnValue_t DeviceHandlerBase::initialize() { } result = healthHelper.initialize(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = modeHelper.initialize(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = actionHelper.initialize(commandQueue); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = fdirInstance->initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = parameterHelper.initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = poolManager.initialize(commandQueue); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -222,28 +226,37 @@ ReturnValue_t DeviceHandlerBase::initialize() { if (thermalSet != nullptr) { // Set temperature target state to NON_OP. result = thermalSet->read(); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; thermalSet->heaterRequest.setValid(true); thermalSet->commit(); } } - return RETURN_OK; + return returnvalue::OK; } void DeviceHandlerBase::decrementDeviceReplyMap() { + bool timedOut = false; for (std::pair& replyPair : deviceReplyMap) { - if (replyPair.second.delayCycles != 0) { + if (replyPair.second.countdown != nullptr && replyPair.second.active) { + if (replyPair.second.countdown->hasTimedOut()) { + resetTimeoutControlledReply(&replyPair.second); + timedOut = true; + } + } + if (replyPair.second.delayCycles != 0 && replyPair.second.countdown == nullptr) { replyPair.second.delayCycles--; if (replyPair.second.delayCycles == 0) { - if (replyPair.second.periodic) { - replyPair.second.delayCycles = replyPair.second.maxDelayCycles; - } - replyToReply(replyPair.first, replyPair.second, TIMEOUT); - missedReply(replyPair.first); + resetDelayCyclesControlledReply(&replyPair.second); + timedOut = true; } } + if (timedOut) { + replyToReply(replyPair.first, replyPair.second, TIMEOUT); + missedReply(replyPair.first); + timedOut = false; + } } } @@ -254,42 +267,42 @@ void DeviceHandlerBase::readCommandQueue() { CommandMessage command; ReturnValue_t result = commandQueue->receiveMessage(&command); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return; } result = healthHelper.handleHealthCommand(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { return; } result = modeHelper.handleModeCommand(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { return; } result = actionHelper.handleActionMessage(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { return; } result = parameterHelper.handleParameterMessage(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { return; } result = poolManager.handleHousekeepingMessage(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { return; } result = handleDeviceHandlerMessage(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { return; } result = letChildHandleMessage(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { return; } @@ -317,7 +330,7 @@ void DeviceHandlerBase::doStateMachine() { sprintf(printout, "Transition timeout (%lu) occured !", static_cast(childTransitionDelay)); /* Common configuration error for development, so print it */ - printWarningOrError(sif::OutputTypes::OUT_WARNING, "doStateMachine", RETURN_FAILED, + printWarningOrError(sif::OutputTypes::OUT_WARNING, "doStateMachine", returnvalue::FAILED, printout); #endif triggerEvent(MODE_TRANSITION_FAILED, childTransitionFailure, 0); @@ -347,6 +360,8 @@ void DeviceHandlerBase::doStateMachine() { if ((switchState == PowerSwitchIF::SWITCH_ON) || (switchState == NO_SWITCH)) { // NOTE: TransitionSourceMode and -SubMode are set by handleCommandedModeTransition childTransitionFailure = CHILD_TIMEOUT; + transitionSourceMode = _MODE_SHUT_DOWN; + transitionSourceSubMode = SUBMODE_NONE; setMode(_MODE_START_UP); callChildStatemachine(); } @@ -359,7 +374,6 @@ void DeviceHandlerBase::doStateMachine() { setMode(MODE_OFF); break; } - if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) { triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0); setMode(MODE_ERROR_ON); @@ -397,7 +411,7 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, Submode_t s case MODE_NORMAL: case MODE_RAW: if (submode == SUBMODE_NONE) { - return RETURN_OK; + return returnvalue::OK; } else { return INVALID_SUBMODE; } @@ -408,20 +422,22 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, Submode_t s ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap( DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet, - size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) { + size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId, + Countdown* countdown) { // No need to check, as we may try to insert multiple times. insertInCommandMap(deviceCommand, hasDifferentReplyId, replyId); if (hasDifferentReplyId) { - return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic); + return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic, countdown); } else { - return insertInReplyMap(deviceCommand, maxDelayCycles, replyDataSet, replyLen, periodic); + return insertInReplyMap(deviceCommand, maxDelayCycles, replyDataSet, replyLen, periodic, + countdown); } } ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet, size_t replyLen, - bool periodic) { + bool periodic, Countdown* countdown) { DeviceReplyInfo info; info.maxDelayCycles = maxDelayCycles; info.periodic = periodic; @@ -429,11 +445,12 @@ ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, info.replyLen = replyLen; info.dataSet = dataSet; info.command = deviceCommandMap.end(); + info.countdown = countdown; auto resultPair = deviceReplyMap.emplace(replyId, info); if (resultPair.second) { - return RETURN_OK; + return returnvalue::OK; } else { - return RETURN_FAILED; + return returnvalue::FAILED; } } @@ -444,13 +461,13 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceComm info.expectedReplies = 0; info.isExecuting = false; info.sendReplyTo = NO_COMMANDER; - info.useAlternativeReplyId = alternativeReplyId; + info.useAlternativeReplyId = useAlternativeReply; info.alternativeReplyId = alternativeReplyId; auto resultPair = deviceCommandMap.emplace(deviceCommand, info); if (resultPair.second) { - return RETURN_OK; + return returnvalue::OK; } else { - return RETURN_FAILED; + return returnvalue::FAILED; } } @@ -458,16 +475,16 @@ size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) { DeviceCommandId_t replyId = NO_COMMAND_ID; DeviceCommandMap::iterator command = cookieInfo.pendingCommand; if (command->second.useAlternativeReplyId) { - replyId = command->second.alternativeReplyId; - } - else { - replyId = commandId; + replyId = command->second.alternativeReplyId; + } else { + replyId = commandId; } DeviceReplyIter iter = deviceReplyMap.find(replyId); if (iter != deviceReplyMap.end()) { - if (iter->second.delayCycles != 0) { - return iter->second.replyLen; - } + if ((iter->second.delayCycles != 0 && iter->second.countdown == nullptr) || + (iter->second.active && iter->second.countdown != nullptr)) { + return iter->second.replyLen; + } } return 0; } @@ -486,7 +503,7 @@ ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceRep } info->delayCycles = delayCycles; info->periodic = periodic; - return RETURN_OK; + return returnvalue::OK; } } @@ -501,22 +518,32 @@ ReturnValue_t DeviceHandlerBase::updatePeriodicReply(bool enable, DeviceCommandI return COMMAND_NOT_SUPPORTED; } if (enable) { - info->delayCycles = info->maxDelayCycles; + info->active = true; + if (info->countdown != nullptr) { + info->countdown->resetTimer(); + } else { + info->delayCycles = info->maxDelayCycles; + } } else { - info->delayCycles = 0; + info->active = false; + if (info->countdown != nullptr) { + info->countdown->timeOut(); + } else { + info->delayCycles = 0; + } } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId, LocalPoolDataSetBase* dataSet) { auto replyIter = deviceReplyMap.find(replyId); if (replyIter == deviceReplyMap.end()) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } replyIter->second.dataSet = dataSet; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void DeviceHandlerBase::callChildStatemachine() { @@ -555,7 +582,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { if (mode == MODE_OFF and thermalSet != nullptr) { ReturnValue_t result = thermalSet->read(); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { if (thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) { thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; } @@ -570,7 +597,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode) { setMode(newMode, submode); } void DeviceHandlerBase::replyReturnvalueToCommand(ReturnValue_t status, uint32_t parameter) { // This is actually the reply protocol for raw and misc DH commands. - if (status == RETURN_OK) { + if (status == returnvalue::OK) { CommandMessage reply(CommandMessage::REPLY_COMMAND_OK, 0, parameter); commandQueue->reply(&reply); } else { @@ -583,7 +610,7 @@ void DeviceHandlerBase::replyToCommand(ReturnValue_t status, uint32_t parameter) // Check if we reply to a raw command. if (cookieInfo.pendingCommand->first == RAW_COMMAND_ID) { if (status == NO_REPLY_EXPECTED) { - status = RETURN_OK; + status = returnvalue::OK; } replyReturnvalueToCommand(status, parameter); // Always delete data from a raw command. @@ -594,7 +621,7 @@ void DeviceHandlerBase::replyToCommand(ReturnValue_t status, uint32_t parameter) if (cookieInfo.pendingCommand->second.sendReplyTo != NO_COMMANDER) { MessageQueueId_t queueId = cookieInfo.pendingCommand->second.sendReplyTo; if (status == NO_REPLY_EXPECTED) { - actionHelper.finish(true, queueId, cookieInfo.pendingCommand->first, RETURN_OK); + actionHelper.finish(true, queueId, cookieInfo.pendingCommand->first, returnvalue::OK); } else { actionHelper.step(1, queueId, cookieInfo.pendingCommand->first, status); } @@ -611,8 +638,8 @@ void DeviceHandlerBase::replyToReply(const DeviceCommandId_t command, DeviceRepl } DeviceCommandInfo* info = &replyInfo.command->second; if (info == nullptr) { - printWarningOrError(sif::OutputTypes::OUT_ERROR, "replyToReply", - HasReturnvaluesIF::RETURN_FAILED, "Command pointer not found"); + printWarningOrError(sif::OutputTypes::OUT_ERROR, "replyToReply", returnvalue::FAILED, + "Command pointer not found"); return; } @@ -626,7 +653,7 @@ void DeviceHandlerBase::replyToReply(const DeviceCommandId_t command, DeviceRepl // Don't send any replies in that case. if (info->sendReplyTo != NO_COMMANDER) { bool success = false; - if (status == HasReturnvaluesIF::RETURN_OK) { + if (status == returnvalue::OK) { success = true; } actionHelper.finish(success, info->sendReplyTo, command, status); @@ -639,7 +666,7 @@ void DeviceHandlerBase::doSendWrite() { if (cookieInfo.state == COOKIE_WRITE_READY) { ReturnValue_t result = communicationInterface->sendMessage(comCookie, rawPacket, rawPacketLen); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { cookieInfo.state = COOKIE_WRITE_SENT; } else { // always generate a failure event, so that FDIR knows what's up @@ -657,7 +684,7 @@ void DeviceHandlerBase::doGetWrite() { } cookieInfo.state = COOKIE_UNUSED; ReturnValue_t result = communicationInterface->getSendSuccess(comCookie); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { if (wiretappingMode == RAW) { replyRawData(rawPacket, rawPacketLen, requestedRawTraffic, true); } @@ -671,7 +698,7 @@ void DeviceHandlerBase::doGetWrite() { // always generate a failure event, so that FDIR knows what's up triggerEvent(DEVICE_SENDING_COMMAND_FAILED, result, cookieInfo.pendingCommand->first); } - if (result != RETURN_OK) { + if (result != returnvalue::OK) { cookieInfo.pendingCommand->second.isExecuting = false; } replyToCommand(result); @@ -681,7 +708,7 @@ void DeviceHandlerBase::doSendRead() { ReturnValue_t result; result = doSendReadHook(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return; } @@ -692,7 +719,7 @@ void DeviceHandlerBase::doSendRead() { result = communicationInterface->requestReceiveMessage(comCookie, replyLen); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { cookieInfo.state = COOKIE_READ_SENT; } else { triggerEvent(DEVICE_REQUESTING_REPLY_FAILED, result); @@ -718,7 +745,7 @@ void DeviceHandlerBase::doGetRead() { ReturnValue_t result = communicationInterface->readReceivedMessage(comCookie, &receivedData, &receivedDataLen); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { triggerEvent(DEVICE_REQUESTING_REPLY_FAILED, result); // I think we can allow to ignore one missedReply. ignoreMissedRepliesCount++; @@ -741,7 +768,7 @@ void DeviceHandlerBase::doGetRead() { } void DeviceHandlerBase::parseReply(const uint8_t* receivedData, size_t receivedDataLen) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t result = returnvalue::FAILED; DeviceCommandId_t foundId = DeviceHandlerIF::NO_COMMAND_ID; size_t foundLen = 0; /* The loop may not execute more often than the number of received bytes @@ -750,7 +777,7 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData, size_t receivedD for (uint32_t count = 0; count < receivedDataLen; count++) { result = scanForReply(receivedData, remainingLength, &foundId, &foundLen); switch (result) { - case RETURN_OK: + case returnvalue::OK: handleReply(receivedData, foundId, foundLen); if (foundLen == 0) { printWarningOrError(sif::OutputTypes::OUT_WARNING, "parseReply", @@ -760,7 +787,7 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData, size_t receivedD break; case APERIODIC_REPLY: { result = interpretDeviceReply(foundId, receivedData); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { replyRawReplyIfnotWiretapped(receivedData, foundLen); triggerEvent(DEVICE_INTERPRETING_REPLY_FAILED, result, foundId); } @@ -809,20 +836,21 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceCommandId DeviceReplyInfo* info = &(iter->second); - if (info->delayCycles != 0) { + if ((info->delayCycles != 0 && info->countdown == nullptr) || + (info->active && info->countdown != nullptr)) { result = interpretDeviceReply(foundId, receivedData); if (result == IGNORE_REPLY_DATA) { return; } - if (info->periodic) { - info->delayCycles = info->maxDelayCycles; - } else { - info->delayCycles = 0; + if (info->active && info->countdown != nullptr) { + resetTimeoutControlledReply(info); + } else if (info->delayCycles != 0) { + resetDelayCyclesControlledReply(info); } - if (result != RETURN_OK) { + if (result != returnvalue::OK) { // Report failed interpretation to FDIR. replyRawReplyIfnotWiretapped(receivedData, foundLen); triggerEvent(DEVICE_INTERPRETING_REPLY_FAILED, result, foundId); @@ -838,6 +866,24 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceCommandId } } +void DeviceHandlerBase::resetTimeoutControlledReply(DeviceReplyInfo* info) { + if (info->periodic) { + info->countdown->resetTimer(); + } else { + info->active = false; + info->countdown->timeOut(); + } +} + +void DeviceHandlerBase::resetDelayCyclesControlledReply(DeviceReplyInfo* info) { + if (info->periodic) { + info->delayCycles = info->maxDelayCycles; + } else { + info->delayCycles = 0; + info->active = false; + } +} + ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, uint8_t** data, size_t* len) { size_t lenTmp; @@ -845,12 +891,12 @@ ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, if (IPCStore == nullptr) { *data = nullptr; *len = 0; - return RETURN_FAILED; + return returnvalue::FAILED; } ReturnValue_t result = IPCStore->modifyData(storageAddress, data, &lenTmp); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { *len = lenTmp; - return RETURN_OK; + return returnvalue::OK; } else { triggerEvent(StorageManagerIF::GET_DATA_FAILED, result, storageAddress.raw); *data = nullptr; @@ -867,7 +913,7 @@ void DeviceHandlerBase::replyRawData(const uint8_t* data, size_t len, MessageQue store_address_t address; ReturnValue_t result = IPCStore->addData(&address, data, len); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { triggerEvent(StorageManagerIF::STORE_DATA_FAILED, result); return; } @@ -879,7 +925,7 @@ void DeviceHandlerBase::replyRawData(const uint8_t* data, size_t len, MessageQue result = commandQueue->sendMessage(sendTo, &command); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { IPCStore->deleteData(address); // Silently discard data, this indicates heavy TM traffic which // should not be increased by additional events. @@ -915,7 +961,7 @@ MessageQueueId_t DeviceHandlerBase::getCommandQueue() const { return commandQueu void DeviceHandlerBase::buildRawDeviceCommand(CommandMessage* commandMessage) { storedRawData = DeviceHandlerMessage::getStoreAddress(commandMessage); ReturnValue_t result = getStorageData(storedRawData, &rawPacket, &rawPacketLen); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { replyReturnvalueToCommand(result, RAW_COMMAND_ID); storedRawData.raw = StorageManagerIF::INVALID_ADDRESS; } else { @@ -932,7 +978,7 @@ void DeviceHandlerBase::commandSwitch(ReturnValue_t onOff) { const uint8_t* switches; uint8_t numberOfSwitches = 0; ReturnValue_t result = getSwitches(&switches, &numberOfSwitches); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { while (numberOfSwitches > 0) { powerSwitcher->sendSwitchCommand(switches[numberOfSwitches - 1], onOff); numberOfSwitches--; @@ -940,7 +986,7 @@ void DeviceHandlerBase::commandSwitch(ReturnValue_t onOff) { } } -ReturnValue_t DeviceHandlerBase::doSendReadHook() { return RETURN_OK; } +ReturnValue_t DeviceHandlerBase::doSendReadHook() { return returnvalue::OK; } ReturnValue_t DeviceHandlerBase::getSwitches(const uint8_t** switches, uint8_t* numberOfSwitches) { return DeviceHandlerBase::NO_SWITCH; @@ -960,10 +1006,16 @@ ReturnValue_t DeviceHandlerBase::enableReplyInReplyMap(DeviceCommandMap::iterato } if (iter != deviceReplyMap.end()) { DeviceReplyInfo* info = &(iter->second); + // If a countdown has been set, the delay cycles will be ignored and the reply times out + // as soon as the countdown has expired info->delayCycles = info->maxDelayCycles; info->command = command; command->second.expectedReplies = expectedReplies; - return RETURN_OK; + if (info->countdown != nullptr) { + info->countdown->resetTimer(); + } + info->active = true; + return returnvalue::OK; } else { return NO_REPLY_EXPECTED; } @@ -981,7 +1033,7 @@ ReturnValue_t DeviceHandlerBase::getStateOfSwitches(void) { const uint8_t* switches; ReturnValue_t result = getSwitches(&switches, &numberOfSwitches); - if ((result == RETURN_OK) && (numberOfSwitches != 0)) { + if ((result == returnvalue::OK) && (numberOfSwitches != 0)) { while (numberOfSwitches > 0) { if (powerSwitcher->getSwitchState(switches[numberOfSwitches - 1]) == PowerSwitchIF::SWITCH_OFF) { @@ -1026,7 +1078,7 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, Submode_ if ((commandedMode == MODE_ON) && (mode == MODE_OFF) and (thermalSet != nullptr)) { ReturnValue_t result = thermalSet->read(); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { if ((thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) and (not ThermalComponentIF::isOperational(thermalSet->thermalState.value))) { triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalSet->thermalState.value); @@ -1086,7 +1138,7 @@ void DeviceHandlerBase::handleTransitionToOnMode(Mode_t commandedMode, Submode_t triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode); if (thermalSet != nullptr) { ReturnValue_t result = thermalSet->read(); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { if (thermalSet->heaterRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { thermalSet->heaterRequest = ThermalComponentIF::STATE_REQUEST_OPERATIONAL; thermalSet->commit(); @@ -1121,7 +1173,7 @@ HasHealthIF::HealthState DeviceHandlerBase::getHealth() { return healthHelper.ge ReturnValue_t DeviceHandlerBase::setHealth(HealthState health) { healthHelper.setHealth(health); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void DeviceHandlerBase::checkSwitchState() { @@ -1143,7 +1195,7 @@ ReturnValue_t DeviceHandlerBase::acceptExternalDeviceCommands() { if ((mode != MODE_ON) && (mode != MODE_NORMAL)) { return WRONG_MODE_FOR_COMMAND; } - return RETURN_OK; + return returnvalue::OK; } void DeviceHandlerBase::replyRawReplyIfnotWiretapped(const uint8_t* data, size_t len) { @@ -1172,10 +1224,10 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage(CommandMessage* mess default: replyReturnvalueToCommand(INVALID_COMMAND_PARAMETER); wiretappingMode = OFF; - return RETURN_OK; + return returnvalue::OK; } - replyReturnvalueToCommand(RETURN_OK); - return RETURN_OK; + replyReturnvalueToCommand(returnvalue::OK); + return returnvalue::OK; case DeviceHandlerMessage::CMD_RAW: if ((mode != MODE_RAW)) { DeviceHandlerMessage::clear(message); @@ -1183,9 +1235,9 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage(CommandMessage* mess } else { buildRawDeviceCommand(message); } - return RETURN_OK; + return returnvalue::OK; default: - return RETURN_FAILED; + return returnvalue::FAILED; } } @@ -1197,7 +1249,8 @@ void DeviceHandlerBase::setParentQueue(MessageQueueId_t parentQueueId) { bool DeviceHandlerBase::isAwaitingReply() { std::map::iterator iter; for (iter = deviceReplyMap.begin(); iter != deviceReplyMap.end(); ++iter) { - if (iter->second.delayCycles != 0) { + if ((iter->second.delayCycles != 0 && iter->second.countdown == nullptr) || + (iter->second.active && iter->second.countdown != nullptr)) { return true; } } @@ -1205,31 +1258,33 @@ bool DeviceHandlerBase::isAwaitingReply() { } ReturnValue_t DeviceHandlerBase::letChildHandleMessage(CommandMessage* message) { - return RETURN_FAILED; + return returnvalue::FAILED; } -void DeviceHandlerBase::handleDeviceTM(SerializeIF* dataSet, DeviceCommandId_t replyId, - bool forceDirectTm) { - if (dataSet == nullptr) { - return; - } +void DeviceHandlerBase::handleDeviceTm(const uint8_t* rawData, size_t rawDataLen, + DeviceCommandId_t replyId, bool forceDirectTm) { + SerialBufferAdapter bufferWrapper(rawData, rawDataLen); + handleDeviceTm(bufferWrapper, replyId, forceDirectTm); +} - DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId); +void DeviceHandlerBase::handleDeviceTm(const SerializeIF& dataSet, DeviceCommandId_t replyId, + bool forceDirectTm) { + auto iter = deviceReplyMap.find(replyId); if (iter == deviceReplyMap.end()) { triggerEvent(DEVICE_UNKNOWN_REPLY, replyId); return; } - /* Regular replies to a command */ + // Regular replies to a command if (iter->second.command != deviceCommandMap.end()) { MessageQueueId_t queueId = iter->second.command->second.sendReplyTo; if (queueId != NO_COMMANDER) { - /* This may fail, but we'll ignore the fault. */ - actionHelper.reportData(queueId, replyId, dataSet); + // This may fail, but we'll ignore the fault. + actionHelper.reportData(queueId, replyId, const_cast(&dataSet)); } - /* This check should make sure we get any TM but don't get anything doubled. */ + // This check should make sure we get any TM but don't get anything doubled. if (wiretappingMode == TM && (requestedRawTraffic != queueId)) { DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataSet); actionHelper.reportData(requestedRawTraffic, replyId, &wrapper); @@ -1240,22 +1295,17 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* dataSet, DeviceCommandId_t r // hiding of sender needed so the service will handle it as // unexpected Data, no matter what state (progress or completed) // it is in - actionHelper.reportData(defaultRawReceiver, replyId, dataSet, true); + actionHelper.reportData(defaultRawReceiver, replyId, const_cast(&dataSet), + true); } } - /* Unrequested or aperiodic replies */ + // Unrequested or aperiodic replies else { DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataSet); if (wiretappingMode == TM) { actionHelper.reportData(requestedRawTraffic, replyId, &wrapper); } if (forceDirectTm and defaultRawReceiver != MessageQueueIF::NO_QUEUE) { - // sid_t setSid = sid_t(this->getObjectId(), replyId); - // LocalPoolDataSetBase* dataset = getDataSetHandle(setSid); - // if(dataset != nullptr) { - // poolManager.generateHousekeepingPacket(setSid, dataset, true); - // } - // hiding of sender needed so the service will handle it as // unexpected Data, no matter what state (progress or completed) // it is in @@ -1267,7 +1317,7 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* dataSet, DeviceCommandId_t r ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size) { ReturnValue_t result = acceptExternalDeviceCommands(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } DeviceCommandMap::iterator iter = deviceCommandMap.find(actionId); @@ -1276,10 +1326,10 @@ ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, MessageQueue } else if (iter->second.isExecuting) { result = COMMAND_ALREADY_SENT; } else { + iter->second.sendReplyTo = commandedBy; result = buildCommandFromCommand(actionId, data, size); } - if (result == RETURN_OK) { - iter->second.sendReplyTo = commandedBy; + if (result == returnvalue::OK) { iter->second.isExecuting = true; cookieInfo.pendingCommand = iter; cookieInfo.state = COOKIE_WRITE_READY; @@ -1296,7 +1346,7 @@ void DeviceHandlerBase::buildInternalCommand(void) { if (result == BUSY) { /* So we can track misconfigurations */ printWarningOrError(sif::OutputTypes::OUT_WARNING, "buildInternalCommand", - HasReturnvaluesIF::RETURN_FAILED, "Busy."); + returnvalue::FAILED, "Busy."); /* No need to report this */ result = NOTHING_TO_SEND; } @@ -1312,7 +1362,7 @@ void DeviceHandlerBase::buildInternalCommand(void) { if (result == NOTHING_TO_SEND) { return; } - if (result == RETURN_OK) { + if (result == returnvalue::OK) { DeviceCommandMap::iterator iter = deviceCommandMap.find(deviceCommandId); if (iter == deviceCommandMap.end()) { #if FSFW_VERBOSE_LEVEL >= 1 @@ -1329,7 +1379,7 @@ void DeviceHandlerBase::buildInternalCommand(void) { sprintf(output, "Command 0x%08x is executing", static_cast(deviceCommandId)); // so we can track misconfigurations printWarningOrError(sif::OutputTypes::OUT_WARNING, "buildInternalCommand", - HasReturnvaluesIF::RETURN_FAILED, output); + returnvalue::FAILED, output); #endif // this is an internal command, no need to report a failure here, // missed reply will track if a reply is too late, otherwise, it's ok @@ -1341,7 +1391,7 @@ void DeviceHandlerBase::buildInternalCommand(void) { cookieInfo.state = COOKIE_WRITE_READY; } } - if (result != RETURN_OK) { + if (result != returnvalue::OK) { triggerEvent(DEVICE_BUILDING_COMMAND_FAILED, result, deviceCommandId); } } @@ -1352,6 +1402,13 @@ uint8_t DeviceHandlerBase::getReplyDelayCycles(DeviceCommandId_t deviceCommand) DeviceReplyMap::iterator iter = deviceReplyMap.find(deviceCommand); if (iter == deviceReplyMap.end()) { return 0; + } else if (iter->second.countdown != nullptr) { + // fake a useful return value for legacy code + if (iter->second.active) { + return 1; + } else { + return 0; + } } return iter->second.delayCycles; } @@ -1410,7 +1467,7 @@ ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& lo localDataPoolMap.emplace(thermalSet->heaterRequestPoolId, new PoolEntry); } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() { @@ -1424,7 +1481,7 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() { if (setStartupImmediately) { startTransition(MODE_ON, SUBMODE_NONE); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } LocalPoolDataSetBase* DeviceHandlerBase::getDataSetHandle(sid_t sid) { @@ -1452,7 +1509,10 @@ DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const { void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() { for (const auto& reply : deviceReplyMap) { if (reply.second.dataSet != nullptr) { - reply.second.dataSet->setValidity(false, true); + PoolReadGuard pg(reply.second.dataSet); + if (pg.getReadResult() == returnvalue::OK) { + reply.second.dataSet->setValidity(false, true); + } } } } @@ -1462,7 +1522,7 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType, const ch if (errorPrint == nullptr) { if (errorCode == ObjectManagerIF::CHILD_INIT_FAILED) { errorPrint = "Initialization error"; - } else if (errorCode == HasReturnvaluesIF::RETURN_FAILED) { + } else if (errorCode == returnvalue::FAILED) { if (errorType == sif::OutputTypes::OUT_WARNING) { errorPrint = "Generic Warning"; } else { diff --git a/src/fsfw/devicehandlers/DeviceHandlerBase.h b/src/fsfw/devicehandlers/DeviceHandlerBase.h index 5e974831..700e960d 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerBase.h +++ b/src/fsfw/devicehandlers/DeviceHandlerBase.h @@ -18,7 +18,7 @@ #include "fsfw/objectmanager/SystemObject.h" #include "fsfw/parameters/ParameterHelper.h" #include "fsfw/power/PowerSwitchIF.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/serviceInterfaceDefintions.h" #include "fsfw/tasks/ExecutableObjectIF.h" @@ -78,7 +78,6 @@ class StorageManagerIF; * @ingroup devices */ class DeviceHandlerBase : public DeviceHandlerIF, - public HasReturnvaluesIF, public ExecutableObjectIF, public SystemObject, public HasModesIF, @@ -145,7 +144,7 @@ class DeviceHandlerBase : public DeviceHandlerIF, * 4. Decrements counter for timeout of replies by calling * decrementDeviceReplyMap() * 5. Performs FDIR check for failures - * 6. If the device mode is MODE_OFF, return RETURN_OK. + * 6. If the device mode is MODE_OFF, return returnvalue::OK. * Otherwise, perform the Action property and performs depending * on value specified by input value counter (incremented in PST). * The child class tells base class what to do by setting this value. @@ -161,9 +160,9 @@ class DeviceHandlerBase : public DeviceHandlerIF, * - GET_READ: Access requested reading data by calling doGetRead() * which calls readReceivedMessage of #communicationInterface * @param counter Specifies which Action to perform - * @return RETURN_OK for successful execution + * @return returnvalue::OK for successful execution */ - virtual ReturnValue_t performOperation(uint8_t counter); + virtual ReturnValue_t performOperation(uint8_t counter) override; /** * @brief Initializes the device handler @@ -173,7 +172,7 @@ class DeviceHandlerBase : public DeviceHandlerIF, * Calls fillCommandAndReplyMap(). * @return */ - virtual ReturnValue_t initialize(); + virtual ReturnValue_t initialize() override; /** * @brief Intialization steps performed after all tasks have been created. @@ -282,7 +281,7 @@ class DeviceHandlerBase : public DeviceHandlerIF, * * @param[out] id the device command id that has been built * @return - * - @c RETURN_OK to send command after setting #rawPacket and + * - @c returnvalue::OK to send command after setting #rawPacket and * #rawPacketLen. * - @c NOTHING_TO_SEND when no command is to be sent. * - Anything else triggers an even with the returnvalue as a parameter. @@ -306,7 +305,7 @@ class DeviceHandlerBase : public DeviceHandlerIF, * * @param[out] id the device command id built * @return - * - @c RETURN_OK when a command is to be sent + * - @c returnvalue::OK when a command is to be sent * - @c NOTHING_TO_SEND when no command is to be sent * - Anything else triggers an even with the returnvalue as a parameter */ @@ -328,7 +327,7 @@ class DeviceHandlerBase : public DeviceHandlerIF, * @param commandData Pointer to the data from the direct command * @param commandDataLen Length of commandData * @return - * - @c RETURN_OK to send command after #rawPacket and #rawPacketLen + * - @c returnvalue::OK to send command after #rawPacket and #rawPacketLen * have been set. * - @c HasActionsIF::EXECUTION_COMPLETE to generate a finish reply immediately. This can * be used if no reply is expected @@ -358,8 +357,8 @@ class DeviceHandlerBase : public DeviceHandlerIF, * @param[out] foundLen length of the data found. Is to be set in function, * buffer is scanned at previous position + foundLen. * @return - * - @c RETURN_OK a valid packet was found at @c start, @c foundLen is valid - * - @c RETURN_FAILED no reply could be found starting at @c start, + * - @c returnvalue::OK a valid packet was found at @c start, @c foundLen is valid + * - @c returnvalue::FAILED no reply could be found starting at @c start, * implies @c foundLen is not valid, base class will call scanForReply() * again with ++start * - @c DeviceHandlerIF::INVALID_DATA a packet was found but it is invalid, @@ -388,10 +387,10 @@ class DeviceHandlerBase : public DeviceHandlerIF, * @param id the id found by scanForReply() * @param packet * @return - * - @c RETURN_OK when the reply was interpreted. + * - @c returnvalue::OK when the reply was interpreted. * - @c IGNORE_REPLY_DATA Ignore the reply and don't reset reply cycle * counter. - * - @c RETURN_FAILED when the reply could not be interpreted, + * - @c returnvalue::FAILED when the reply could not be interpreted, * e.g. logical errors or range violations occurred */ virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) = 0; @@ -448,14 +447,18 @@ class DeviceHandlerBase : public DeviceHandlerIF, * by the device repeatedly without request) or not. Default is aperiodic (0). * Please note that periodic replies are disabled by default. You can enable them with * #updatePeriodicReply - * @return - @c RETURN_OK when the command was successfully inserted, - * - @c RETURN_FAILED else. + * @param countdown Instead of using maxDelayCycles to timeout a device reply it is also possible + * to provide a pointer to a Countdown object which will signal the timeout + * when expired + * @return - @c returnvalue::OK when the command was successfully inserted, + * - @c returnvalue::FAILED else. */ ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase *replyDataSet = nullptr, size_t replyLen = 0, bool periodic = false, bool hasDifferentReplyId = false, - DeviceCommandId_t replyId = 0); + DeviceCommandId_t replyId = 0, + Countdown *countdown = nullptr); /** * @brief This is a helper method to insert replies in the reply map. * @param deviceCommand Identifier of the reply to add. @@ -465,18 +468,21 @@ class DeviceHandlerBase : public DeviceHandlerIF, * by the device repeatedly without request) or not. Default is aperiodic (0). * Please note that periodic replies are disabled by default. You can enable them with * #updatePeriodicReply - * @return - @c RETURN_OK when the command was successfully inserted, - * - @c RETURN_FAILED else. + * @param countdown Instead of using maxDelayCycles to timeout a device reply it is also possible + * to provide a pointer to a Countdown object which will signal the timeout + * when expired + * @return - @c returnvalue::OK when the command was successfully inserted, + * - @c returnvalue::FAILED else. */ ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase *dataSet = nullptr, size_t replyLen = 0, - bool periodic = false); + bool periodic = false, Countdown *countdown = nullptr); /** * @brief A simple command to add a command to the commandList. * @param deviceCommand The command to add - * @return - @c RETURN_OK when the command was successfully inserted, - * - @c RETURN_FAILED else. + * @return - @c returnvalue::OK when the command was successfully inserted, + * - @c returnvalue::FAILED else. */ ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand, bool useAlternativeReply = false, @@ -512,8 +518,8 @@ class DeviceHandlerBase : public DeviceHandlerIF, * @param periodic Indicates if the command is periodic (i.e. it is sent * by the device repeatedly without request) or not. Default is aperiodic (0). * Warning: The setting always overrides the value that was entered in the map. - * @return - @c RETURN_OK when the command was successfully inserted, - * - @c RETURN_FAILED else. + * @return - @c returnvalue::OK when the command was successfully inserted, + * - @c returnvalue::FAILED else. */ ReturnValue_t updateReplyMapEntry(DeviceCommandId_t deviceReply, uint16_t delayCycles, uint16_t maxDelayCycles, bool periodic = false); @@ -596,8 +602,8 @@ class DeviceHandlerBase : public DeviceHandlerIF, * @param mode * @param submode * @return - * - @c RETURN_OK if valid - * - @c RETURN_FAILED if invalid + * - @c returnvalue::OK if valid + * - @c returnvalue::FAILED if invalid */ virtual ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode); /** @@ -616,8 +622,8 @@ class DeviceHandlerBase : public DeviceHandlerIF, * @param[out] switches pointer to an array of switches * @param[out] numberOfSwitches length of returned array * @return - * - @c RETURN_OK if the parameters were set - * - @c RETURN_FAILED if no switches exist + * - @c returnvalue::OK if the parameters were set + * - @c returnvalue::FAILED if no switches exist */ virtual ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches); @@ -783,6 +789,11 @@ class DeviceHandlerBase : public DeviceHandlerIF, LocalPoolDataSetBase *dataSet = nullptr; //! The command that expects this reply. DeviceCommandMap::iterator command; + //! Instead of using delayCycles to specify the maximum time to wait for the device reply, it + //! is also possible specify a countdown + Countdown *countdown = nullptr; + //! will be set to true when reply is enabled + bool active = false; }; using DeviceReplyMap = std::map; @@ -966,7 +977,7 @@ class DeviceHandlerBase : public DeviceHandlerIF, * - A failure code may be returned if something went fundamentally wrong. * * @param deviceCommand - * @return - RETURN_OK if a reply was activated. + * @return - returnvalue::OK if a reply was activated. * - NO_REPLY_EXPECTED if there was no reply found. This is not an * error case as many commands do not expect a reply. */ @@ -993,7 +1004,7 @@ class DeviceHandlerBase : public DeviceHandlerIF, * * @param[out] id the device command id built * @return - * - @c RETURN_OK when a command is to be sent + * - @c returnvalue::OK when a command is to be sent * - not @c NOTHING_TO_SEND when no command is to be sent */ virtual ReturnValue_t buildChildRawCommand(); @@ -1021,7 +1032,7 @@ class DeviceHandlerBase : public DeviceHandlerIF, * by #switches are on * - @c PowerSwitchIF::SWITCH_OFF one of the switches specified by * #switches are off - * - @c PowerSwitchIF::RETURN_FAILED if an error occured + * - @c PowerSwitchIF::returnvalue::FAILED if an error occured */ ReturnValue_t getStateOfSwitches(); @@ -1041,9 +1052,25 @@ class DeviceHandlerBase : public DeviceHandlerIF, bool isAwaitingReply(); - void handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t replyId, bool forceDirectTm = false); - // void handleDeviceTM(uint8_t* data, size_t dataSize, DeviceCommandId_t replyId, - // bool forceDirectTm); + /** + * Wrapper function for @handleDeviceTm which wraps the raw buffer with @SerialBufferAdapter. + * For interpreted data, prefer the other function. + * @param rawData + * @param rawDataLen + * @param replyId + * @param forceDirectTm + */ + void handleDeviceTm(const uint8_t *rawData, size_t rawDataLen, DeviceCommandId_t replyId, + bool forceDirectTm = false); + /** + * Can be used to handle Service 8 data replies. This will also generate the TM wiretapping + * packets accordingly. + * @param dataSet + * @param replyId + * @param forceDirectTm + */ + void handleDeviceTm(const SerializeIF &dataSet, DeviceCommandId_t replyId, + bool forceDirectTm = false); virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode); @@ -1058,11 +1085,12 @@ class DeviceHandlerBase : public DeviceHandlerIF, * @param parameter1 Optional parameter 1 * @param parameter2 Optional parameter 2 */ - void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0); + void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) override; /** * Same as triggerEvent, but for forwarding if object is used as proxy. */ - virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const; + virtual void forwardEvent(Event event, uint32_t parameter1 = 0, + uint32_t parameter2 = 0) const override; /** * Checks if current mode is transitional mode. @@ -1073,7 +1101,7 @@ class DeviceHandlerBase : public DeviceHandlerIF, /** * Checks if current handler state allows reception of external device commands. * Default implementation allows commands only in plain MODE_ON and MODE_NORMAL. - * @return RETURN_OK if commands are accepted, anything else otherwise. + * @return returnvalue::OK if commands are accepted, anything else otherwise. */ virtual ReturnValue_t acceptExternalDeviceCommands(); @@ -1243,6 +1271,17 @@ class DeviceHandlerBase : public DeviceHandlerIF, */ void doGetRead(void); + /** + * @brief Resets replies which use a timeout to detect missed replies. + */ + void resetTimeoutControlledReply(DeviceReplyInfo *info); + + /** + * @brief Resets replies which use a number of maximum delay cycles to detect + * missed replies. + */ + void resetDelayCyclesControlledReply(DeviceReplyInfo *info); + /** * Retrive data from the #IPCStore. * @@ -1250,9 +1289,9 @@ class DeviceHandlerBase : public DeviceHandlerIF, * @param[out] data * @param[out] len * @return - * - @c RETURN_OK @c data is valid - * - @c RETURN_FAILED IPCStore is nullptr - * - the return value from the IPCStore if it was not @c RETURN_OK + * - @c returnvalue::OK @c data is valid + * - @c returnvalue::FAILED IPCStore is nullptr + * - the return value from the IPCStore if it was not @c returnvalue::OK */ ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data, size_t *len); @@ -1282,7 +1321,7 @@ class DeviceHandlerBase : public DeviceHandlerIF, * @param errorPrint */ void printWarningOrError(sif::OutputTypes errorType, const char *functionName, - ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED, + ReturnValue_t errorCode = returnvalue::FAILED, const char *errorPrint = nullptr); }; diff --git a/src/fsfw/devicehandlers/DeviceHandlerFailureIsolation.cpp b/src/fsfw/devicehandlers/DeviceHandlerFailureIsolation.cpp index 48783c20..a3ac9ff7 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerFailureIsolation.cpp +++ b/src/fsfw/devicehandlers/DeviceHandlerFailureIsolation.cpp @@ -23,9 +23,9 @@ DeviceHandlerFailureIsolation::~DeviceHandlerFailureIsolation() {} ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event) { if (isFdirInActionOrAreWeFaulty(event)) { - return RETURN_OK; + return returnvalue::OK; } - ReturnValue_t result = RETURN_FAILED; + ReturnValue_t result = returnvalue::FAILED; switch (event->getEvent()) { case HasModesIF::MODE_TRANSITION_FAILED: case HasModesIF::OBJECT_IN_INVALID_MODE: @@ -48,7 +48,7 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event) // The two above should never be confirmed. case DeviceHandlerIF::DEVICE_MISSED_REPLY: result = sendConfirmationRequest(event); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { break; } // else @@ -72,7 +72,7 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event) case PowerSwitchIF::SWITCH_WENT_OFF: if (powerConfirmation != MessageQueueIF::NO_QUEUE) { result = sendConfirmationRequest(event, powerConfirmation); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { setFdirState(DEVICE_MIGHT_BE_OFF); } } @@ -106,9 +106,9 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event) // break; default: // We don't know the event, someone else should handle it. - return RETURN_FAILED; + return returnvalue::FAILED; } - return RETURN_OK; + return returnvalue::OK; } void DeviceHandlerFailureIsolation::eventConfirmed(EventMessage* event) { @@ -162,7 +162,7 @@ void DeviceHandlerFailureIsolation::clearFaultCounters() { ReturnValue_t DeviceHandlerFailureIsolation::initialize() { ReturnValue_t result = FailureIsolationBase::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "DeviceHandlerFailureIsolation::initialize: Could not" " initialize FailureIsolationBase." @@ -176,7 +176,7 @@ ReturnValue_t DeviceHandlerFailureIsolation::initialize() { powerConfirmation = power->getEventReceptionQueue(); } - return RETURN_OK; + return returnvalue::OK; } void DeviceHandlerFailureIsolation::setFdirState(FDIRState state) { diff --git a/src/fsfw/devicehandlers/DeviceTmReportingWrapper.cpp b/src/fsfw/devicehandlers/DeviceTmReportingWrapper.cpp index 3da431dc..8fc0d368 100644 --- a/src/fsfw/devicehandlers/DeviceTmReportingWrapper.cpp +++ b/src/fsfw/devicehandlers/DeviceTmReportingWrapper.cpp @@ -3,38 +3,30 @@ #include "fsfw/serialize/SerializeAdapter.h" DeviceTmReportingWrapper::DeviceTmReportingWrapper(object_id_t objectId, ActionId_t actionId, - SerializeIF* data) + const SerializeIF& data) : objectId(objectId), actionId(actionId), data(data) {} -DeviceTmReportingWrapper::~DeviceTmReportingWrapper() {} +DeviceTmReportingWrapper::~DeviceTmReportingWrapper() = default; ReturnValue_t DeviceTmReportingWrapper::serialize(uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result = SerializeAdapter::serialize(&objectId, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&actionId, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } - return data->serialize(buffer, size, maxSize, streamEndianness); + return data.serialize(buffer, size, maxSize, streamEndianness); } size_t DeviceTmReportingWrapper::getSerializedSize() const { - return sizeof(objectId) + sizeof(ActionId_t) + data->getSerializedSize(); + return sizeof(objectId) + sizeof(ActionId_t) + data.getSerializedSize(); } ReturnValue_t DeviceTmReportingWrapper::deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { - ReturnValue_t result = SerializeAdapter::deSerialize(&objectId, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - result = SerializeAdapter::deSerialize(&actionId, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - return data->deSerialize(buffer, size, streamEndianness); + return returnvalue::FAILED; } diff --git a/src/fsfw/devicehandlers/DeviceTmReportingWrapper.h b/src/fsfw/devicehandlers/DeviceTmReportingWrapper.h index 71c64453..ae385f4c 100644 --- a/src/fsfw/devicehandlers/DeviceTmReportingWrapper.h +++ b/src/fsfw/devicehandlers/DeviceTmReportingWrapper.h @@ -7,21 +7,22 @@ class DeviceTmReportingWrapper : public SerializeIF { public: - DeviceTmReportingWrapper(object_id_t objectId, ActionId_t actionId, SerializeIF* data); - virtual ~DeviceTmReportingWrapper(); + DeviceTmReportingWrapper(object_id_t objectId, ActionId_t actionId, const SerializeIF& data); + ~DeviceTmReportingWrapper() override; - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const override; + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override; - virtual size_t getSerializedSize() const override; - - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) override; + [[nodiscard]] size_t getSerializedSize() const override; private: object_id_t objectId; ActionId_t actionId; - SerializeIF* data; + const SerializeIF& data; + + // Deserialization forbidden + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; }; #endif /* FSFW_DEVICEHANDLERS_DEVICETMREPORTINGWRAPPER_H_ */ diff --git a/src/fsfw/devicehandlers/HealthDevice.cpp b/src/fsfw/devicehandlers/HealthDevice.cpp index a626fa6c..4c09964a 100644 --- a/src/fsfw/devicehandlers/HealthDevice.cpp +++ b/src/fsfw/devicehandlers/HealthDevice.cpp @@ -16,7 +16,7 @@ HealthDevice::~HealthDevice() { QueueFactory::instance()->deleteMessageQueue(com ReturnValue_t HealthDevice::performOperation(uint8_t opCode) { CommandMessage command; ReturnValue_t result = commandQueue->receiveMessage(&command); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { result = healthHelper.handleHealthCommand(&command); } return result; @@ -24,7 +24,7 @@ ReturnValue_t HealthDevice::performOperation(uint8_t opCode) { ReturnValue_t HealthDevice::initialize() { ReturnValue_t result = SystemObject::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (parentQueue != 0) { @@ -50,7 +50,7 @@ bool HealthDevice::hasHealthChanged() { ReturnValue_t HealthDevice::setHealth(HealthState health) { healthHelper.setHealth(health); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } HasHealthIF::HealthState HealthDevice::getHealth() { return healthHelper.getHealth(); } diff --git a/src/fsfw/events/CMakeLists.txt b/src/fsfw/events/CMakeLists.txt index 28eec772..704cca85 100644 --- a/src/fsfw/events/CMakeLists.txt +++ b/src/fsfw/events/CMakeLists.txt @@ -1,6 +1,3 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - EventManager.cpp - EventMessage.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE EventManager.cpp EventMessage.cpp) add_subdirectory(eventmatching) diff --git a/src/fsfw/events/Event.h b/src/fsfw/events/Event.h index ecab0493..e48736bf 100644 --- a/src/fsfw/events/Event.h +++ b/src/fsfw/events/Event.h @@ -4,8 +4,6 @@ #include #include "fwSubsystemIdRanges.h" -// could be moved to more suitable location -#include using EventId_t = uint16_t; using EventSeverity_t = uint8_t; diff --git a/src/fsfw/events/EventManager.cpp b/src/fsfw/events/EventManager.cpp index aaa7d6c5..f2a099ed 100644 --- a/src/fsfw/events/EventManager.cpp +++ b/src/fsfw/events/EventManager.cpp @@ -15,14 +15,16 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = { {fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS, sizeof(EventIdRangeMatcher)}, {fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS, sizeof(ReporterRangeMatcher)}}; -EventManager::EventManager(object_id_t setObjectId) +EventManager::EventManager(object_id_t setObjectId, uint32_t eventQueueDepth) : SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) { mutex = MutexFactory::instance()->createMutex(); - eventReportQueue = QueueFactory::instance()->createMessageQueue(MAX_EVENTS_PER_CYCLE, - EventMessage::EVENT_MESSAGE_SIZE); + auto mqArgs = MqArgs(setObjectId, static_cast(this)); + eventReportQueue = QueueFactory::instance()->createMessageQueue( + eventQueueDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs); } EventManager::~EventManager() { + listenerList.clear(); QueueFactory::instance()->deleteMessageQueue(eventReportQueue); MutexFactory::instance()->deleteMutex(mutex); } @@ -30,25 +32,36 @@ EventManager::~EventManager() { MessageQueueId_t EventManager::getEventReportQueue() { return eventReportQueue->getId(); } ReturnValue_t EventManager::performOperation(uint8_t opCode) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - while (result == HasReturnvaluesIF::RETURN_OK) { + ReturnValue_t result = returnvalue::OK; + while (result == returnvalue::OK) { EventMessage message; result = eventReportQueue->receiveMessage(&message); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { #if FSFW_OBJ_EVENT_TRANSLATION == 1 printEvent(&message); #endif notifyListeners(&message); } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } 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 != returnvalue::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(); @@ -59,9 +72,14 @@ ReturnValue_t EventManager::registerListener(MessageQueueId_t listener, auto result = listenerList.insert(std::pair( listener, EventMatchTree(&factoryBackend, forwardAllButSelected))); if (!result.second) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + + return returnvalue::OK; +} + +ReturnValue_t EventManager::unregisterListener(MessageQueueId_t listener) { + return listenerList.erase(listener) == 1 ? returnvalue::OK : returnvalue::FAILED; } ReturnValue_t EventManager::subscribeToEvent(MessageQueueId_t listener, EventId_t event) { @@ -88,6 +106,11 @@ ReturnValue_t EventManager::subscribeToEventRange(MessageQueueId_t listener, Eve return result; } +ReturnValue_t EventManager::unsubscribeFromAllEvents(MessageQueueId_t listener, + object_id_t object) { + return unsubscribeFromEventRange(listener, 0, 0, true, object); +} + ReturnValue_t EventManager::unsubscribeFromEventRange(MessageQueueId_t listener, EventId_t idFrom, EventId_t idTo, bool idInverted, object_id_t reporterFrom, @@ -189,4 +212,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 */ diff --git a/src/fsfw/events/EventManager.h b/src/fsfw/events/EventManager.h index f2d642ff..90f97f70 100644 --- a/src/fsfw/events/EventManager.h +++ b/src/fsfw/events/EventManager.h @@ -21,9 +21,7 @@ extern const char* translateEvents(Event event); class EventManager : public EventManagerIF, public ExecutableObjectIF, public SystemObject { public: - static const uint16_t MAX_EVENTS_PER_CYCLE = 80; - - EventManager(object_id_t setObjectId); + EventManager(object_id_t setObjectId, uint32_t eventQueueDepth); virtual ~EventManager(); void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs); @@ -31,17 +29,20 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy MessageQueueId_t getEventReportQueue(); ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false); + ReturnValue_t unregisterListener(MessageQueueId_t listener) override; ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event); ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object); ReturnValue_t subscribeToEventRange(MessageQueueId_t listener, EventId_t idFrom = 0, EventId_t idTo = 0, bool idInverted = false, object_id_t reporterFrom = 0, object_id_t reporterTo = 0, bool reporterInverted = false); + ReturnValue_t unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object); ReturnValue_t unsubscribeFromEventRange(MessageQueueId_t listener, EventId_t idFrom = 0, EventId_t idTo = 0, bool idInverted = false, 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; diff --git a/src/fsfw/events/EventManagerIF.h b/src/fsfw/events/EventManagerIF.h index 98051ba0..12014090 100644 --- a/src/fsfw/events/EventManagerIF.h +++ b/src/fsfw/events/EventManagerIF.h @@ -18,8 +18,10 @@ class EventManagerIF { virtual ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false) = 0; + virtual ReturnValue_t unregisterListener(MessageQueueId_t listener) = 0; virtual ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event) = 0; virtual ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object) = 0; + virtual ReturnValue_t unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object) = 0; virtual ReturnValue_t subscribeToEventRange(MessageQueueId_t listener, EventId_t idFrom = 0, EventId_t idTo = 0, bool idInverted = false, object_id_t reporterFrom = 0, diff --git a/src/fsfw/events/EventReportingProxyIF.h b/src/fsfw/events/EventReportingProxyIF.h index c6034c9f..51f8ed1d 100644 --- a/src/fsfw/events/EventReportingProxyIF.h +++ b/src/fsfw/events/EventReportingProxyIF.h @@ -5,7 +5,7 @@ class EventReportingProxyIF { public: - virtual ~EventReportingProxyIF() {} + virtual ~EventReportingProxyIF() = default; virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const = 0; diff --git a/src/fsfw/events/eventmatching/CMakeLists.txt b/src/fsfw/events/eventmatching/CMakeLists.txt index 81ff9ed8..a9f9c7b3 100644 --- a/src/fsfw/events/eventmatching/CMakeLists.txt +++ b/src/fsfw/events/eventmatching/CMakeLists.txt @@ -1,7 +1,3 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - EventIdRangeMatcher.cpp - EventMatchTree.cpp - ReporterRangeMatcher.cpp - SeverityRangeMatcher.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} PRIVATE EventIdRangeMatcher.cpp EventMatchTree.cpp + ReporterRangeMatcher.cpp SeverityRangeMatcher.cpp) diff --git a/src/fsfw/events/eventmatching/EventMatchTree.cpp b/src/fsfw/events/eventmatching/EventMatchTree.cpp index b564e305..cd3da6a2 100644 --- a/src/fsfw/events/eventmatching/EventMatchTree.cpp +++ b/src/fsfw/events/eventmatching/EventMatchTree.cpp @@ -31,12 +31,12 @@ ReturnValue_t EventMatchTree::addMatch(EventId_t idFrom, EventId_t idTo, bool id iterator lastTest; ReturnValue_t result = findOrInsertRangeMatcher( begin(), idFrom, idTo, idInverted, &lastTest); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (reporterFrom == 0) { // No need to add another AND branch - return RETURN_OK; + return returnvalue::OK; } if (reporterTo == 0) { reporterTo = reporterFrom; @@ -95,7 +95,7 @@ inline ReturnValue_t EventMatchTree::findOrInsertRangeMatcher(iterator start, VA if ((matcher->rangeMatcher.lowerBound == idFrom) && (matcher->rangeMatcher.upperBound == idTo) && (matcher->rangeMatcher.inverted == inverted)) { - return RETURN_OK; + return returnvalue::OK; } else { iter = iter.right(); } @@ -115,9 +115,9 @@ inline ReturnValue_t EventMatchTree::findOrInsertRangeMatcher(iterator start, VA *lastTest = insert(attachToBranch, *lastTest, newNode); if (*lastTest == end()) { // This actaully never fails, so creating a dedicated returncode seems an overshoot. - return RETURN_FAILED; + return returnvalue::FAILED; } - return RETURN_OK; + return returnvalue::OK; } template diff --git a/src/fsfw/events/eventmatching/EventMatchTree.h b/src/fsfw/events/eventmatching/EventMatchTree.h index 010e0623..0d06f0c2 100644 --- a/src/fsfw/events/eventmatching/EventMatchTree.h +++ b/src/fsfw/events/eventmatching/EventMatchTree.h @@ -4,10 +4,10 @@ #include "../../container/PlacementFactory.h" #include "../../events/EventMessage.h" #include "../../globalfunctions/matching/MatchTree.h" -#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../returnvalues/returnvalue.h" class StorageManagerIF; -class EventMatchTree : public MatchTree, public HasReturnvaluesIF { +class EventMatchTree : public MatchTree { public: EventMatchTree(StorageManagerIF* storageBackend, bool invertedMatch); virtual ~EventMatchTree(); diff --git a/src/fsfw/events/fwSubsystemIdRanges.h b/src/fsfw/events/fwSubsystemIdRanges.h index 21123600..e395c2f9 100644 --- a/src/fsfw/events/fwSubsystemIdRanges.h +++ b/src/fsfw/events/fwSubsystemIdRanges.h @@ -10,7 +10,7 @@ enum : uint8_t { CDH = 28, TCS_1 = 59, PCDU_1 = 42, - PCDU_2 = 43, + POWER_SWITCH_IF = 43, HEATER = 50, T_SENSORS = 52, FDIR = 70, @@ -19,6 +19,7 @@ enum : uint8_t { HK = 73, SYSTEM_MANAGER = 74, SYSTEM_MANAGER_1 = 75, + TMTC_DISTRIBUTION = 76, SYSTEM_1 = 79, PUS_SERVICE_1 = 80, PUS_SERVICE_2 = 82, @@ -27,10 +28,12 @@ enum : uint8_t { PUS_SERVICE_6 = 86, PUS_SERVICE_8 = 88, PUS_SERVICE_9 = 89, + PUS_SERVICE_11 = 91, PUS_SERVICE_17 = 97, PUS_SERVICE_23 = 103, MGM_LIS3MDL = 106, MGM_RM3100 = 107, + CFDP = 108, FW_SUBSYSTEM_ID_RANGE }; diff --git a/src/fsfw/fdir/CMakeLists.txt b/src/fsfw/fdir/CMakeLists.txt index f5ffbba8..d41ee2eb 100644 --- a/src/fsfw/fdir/CMakeLists.txt +++ b/src/fsfw/fdir/CMakeLists.txt @@ -1,6 +1,3 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - EventCorrelation.cpp - FailureIsolationBase.cpp - FaultCounter.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} PRIVATE EventCorrelation.cpp FailureIsolationBase.cpp + FaultCounter.cpp) diff --git a/src/fsfw/fdir/ConfirmsFailuresIF.h b/src/fsfw/fdir/ConfirmsFailuresIF.h index e4d26907..4424747e 100644 --- a/src/fsfw/fdir/ConfirmsFailuresIF.h +++ b/src/fsfw/fdir/ConfirmsFailuresIF.h @@ -2,7 +2,7 @@ #define FRAMEWORK_FDIR_CONFIRMSFAILURESIF_H_ #include "../ipc/MessageQueueSenderIF.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" class ConfirmsFailuresIF { public: diff --git a/src/fsfw/fdir/FailureIsolationBase.cpp b/src/fsfw/fdir/FailureIsolationBase.cpp index fedef869..0d3b0214 100644 --- a/src/fsfw/fdir/FailureIsolationBase.cpp +++ b/src/fsfw/fdir/FailureIsolationBase.cpp @@ -14,6 +14,16 @@ FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent } FailureIsolationBase::~FailureIsolationBase() { + EventManagerIF* manager = ObjectManager::instance()->get(objects::EVENT_MANAGER); + if (manager == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "FailureIsolationBase::~FailureIsolationBase: Event Manager has not" + " been initialized!" + << std::endl; +#endif + return; + } + manager->unregisterListener(eventQueue->getId()); QueueFactory::instance()->deleteMessageQueue(eventQueue); } @@ -25,15 +35,15 @@ ReturnValue_t FailureIsolationBase::initialize() { " been initialized!" << std::endl; #endif - return RETURN_FAILED; + return returnvalue::FAILED; } ReturnValue_t result = manager->registerListener(eventQueue->getId()); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (ownerId != objects::NO_OBJECT) { result = manager->subscribeToAllEventsFrom(eventQueue->getId(), ownerId); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } owner = ObjectManager::instance()->get(ownerId); @@ -58,16 +68,16 @@ ReturnValue_t FailureIsolationBase::initialize() { sif::error << "Make sure it implements ConfirmsFailuresIF." << std::endl; #endif return ObjectManagerIF::CHILD_INIT_FAILED; - return RETURN_FAILED; + return returnvalue::FAILED; } eventQueue->setDefaultDestination(parentIF->getEventReceptionQueue()); } - return RETURN_OK; + return returnvalue::OK; } void FailureIsolationBase::checkForFailures() { EventMessage event; - for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == RETURN_OK; + for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK; result = eventQueue->receiveMessage(&event)) { if (event.getSender() == eventQueue->getId()) { // We already got this event, because we sent it. @@ -114,7 +124,7 @@ ReturnValue_t FailureIsolationBase::sendConfirmationRequest(EventMessage* event, } else if (faultTreeParent != objects::NO_OBJECT) { return eventQueue->sendToDefault(event); } - return RETURN_FAILED; + return returnvalue::FAILED; } void FailureIsolationBase::eventConfirmed(EventMessage* event) {} diff --git a/src/fsfw/fdir/FailureIsolationBase.h b/src/fsfw/fdir/FailureIsolationBase.h index 85d18add..543ad6cc 100644 --- a/src/fsfw/fdir/FailureIsolationBase.h +++ b/src/fsfw/fdir/FailureIsolationBase.h @@ -5,13 +5,11 @@ #include "../health/HealthMessage.h" #include "../ipc/MessageQueueIF.h" #include "../parameters/HasParametersIF.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "ConfirmsFailuresIF.h" #include "FaultCounter.h" -class FailureIsolationBase : public HasReturnvaluesIF, - public ConfirmsFailuresIF, - public HasParametersIF { +class FailureIsolationBase : public ConfirmsFailuresIF, public HasParametersIF { public: static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1; static const Event FDIR_CHANGED_STATE = diff --git a/src/fsfw/fdir/FaultCounter.cpp b/src/fsfw/fdir/FaultCounter.cpp index e87cf613..eea08817 100644 --- a/src/fsfw/fdir/FaultCounter.cpp +++ b/src/fsfw/fdir/FaultCounter.cpp @@ -60,20 +60,20 @@ ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint8_t uniqueId, return INVALID_DOMAIN_ID; } - switch (uniqueId) { - case 0: + switch (static_cast(uniqueId)) { + case ParameterIds::FAILURE_THRESHOLD: parameterWrapper->set(failureThreshold); break; - case 1: + case ParameterIds::FAULT_COUNT: parameterWrapper->set(faultCount); break; - case 2: + case ParameterIds::TIMEOUT: parameterWrapper->set(timer.timeout); break; default: return INVALID_IDENTIFIER_ID; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void FaultCounter::setParameterDomain(uint8_t domain) { parameterDomain = domain; } diff --git a/src/fsfw/fdir/FaultCounter.h b/src/fsfw/fdir/FaultCounter.h index 3b59885c..cca780d6 100644 --- a/src/fsfw/fdir/FaultCounter.h +++ b/src/fsfw/fdir/FaultCounter.h @@ -6,6 +6,8 @@ class FaultCounter : public HasParametersIF { public: + enum class ParameterIds { FAILURE_THRESHOLD, FAULT_COUNT, TIMEOUT }; + FaultCounter(); FaultCounter(uint32_t failureThreshold, uint32_t decrementAfterMs, uint8_t setParameterDomain = 0); @@ -25,7 +27,8 @@ class FaultCounter : public HasParametersIF { virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper *parameterWrapper, - const ParameterWrapper *newValues, uint16_t startAtIndex); + const ParameterWrapper *newValues = nullptr, + uint16_t startAtIndex = 0); void setParameterDomain(uint8_t domain); diff --git a/src/fsfw/filesystem.h b/src/fsfw/filesystem.h new file mode 100644 index 00000000..c4a6ebc6 --- /dev/null +++ b/src/fsfw/filesystem.h @@ -0,0 +1,7 @@ +#ifndef FSFW_FILESYSTEM_H +#define FSFW_FILESYSTEM_H + +#include "filesystem/FileSystemArgsIF.h" +#include "filesystem/HasFileSystemIF.h" + +#endif // FSFW_FILESYSTEM_H diff --git a/src/fsfw/filesystem/CMakeLists.txt b/src/fsfw/filesystem/CMakeLists.txt new file mode 100644 index 00000000..a0618d97 --- /dev/null +++ b/src/fsfw/filesystem/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE GenericFileSystemMessage.cpp) diff --git a/src/fsfw/memory/FileSystemArgsIF.h b/src/fsfw/filesystem/FileSystemArgsIF.h similarity index 89% rename from src/fsfw/memory/FileSystemArgsIF.h rename to src/fsfw/filesystem/FileSystemArgsIF.h index f1617f62..656764fa 100644 --- a/src/fsfw/memory/FileSystemArgsIF.h +++ b/src/fsfw/filesystem/FileSystemArgsIF.h @@ -7,7 +7,7 @@ */ class FileSystemArgsIF { public: - virtual ~FileSystemArgsIF(){}; + virtual ~FileSystemArgsIF() = default; }; #endif /* FSFW_SRC_FSFW_MEMORY_FILESYSTEMARGS_H_ */ diff --git a/src/fsfw/memory/GenericFileSystemMessage.cpp b/src/fsfw/filesystem/GenericFileSystemMessage.cpp similarity index 97% rename from src/fsfw/memory/GenericFileSystemMessage.cpp rename to src/fsfw/filesystem/GenericFileSystemMessage.cpp index 805c7dcc..496a973f 100644 --- a/src/fsfw/memory/GenericFileSystemMessage.cpp +++ b/src/fsfw/filesystem/GenericFileSystemMessage.cpp @@ -1,4 +1,4 @@ -#include "fsfw/memory/GenericFileSystemMessage.h" +#include "GenericFileSystemMessage.h" #include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/storagemanager/StorageManagerIF.h" @@ -157,10 +157,10 @@ ReturnValue_t GenericFileSystemMessage::clear(CommandMessage *message) { store_address_t storeId = GenericFileSystemMessage::getStoreId(message); auto ipcStore = ObjectManager::instance()->get(objects::IPC_STORE); if (ipcStore == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } return ipcStore->deleteData(storeId); } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/src/fsfw/memory/GenericFileSystemMessage.h b/src/fsfw/filesystem/GenericFileSystemMessage.h similarity index 100% rename from src/fsfw/memory/GenericFileSystemMessage.h rename to src/fsfw/filesystem/GenericFileSystemMessage.h diff --git a/src/fsfw/filesystem/HasFileSystemIF.h b/src/fsfw/filesystem/HasFileSystemIF.h new file mode 100644 index 00000000..6f7112ad --- /dev/null +++ b/src/fsfw/filesystem/HasFileSystemIF.h @@ -0,0 +1,175 @@ +#ifndef FSFW_MEMORY_HASFILESYSTEMIF_H_ +#define FSFW_MEMORY_HASFILESYSTEMIF_H_ + +#include + +#include "FileSystemArgsIF.h" +#include "fsfw/ipc/MessageQueueIF.h" +#include "fsfw/ipc/messageQueueDefinitions.h" +#include "fsfw/returnvalues/FwClassIds.h" +#include "fsfw/returnvalues/returnvalue.h" + +struct FilesystemParams { + explicit FilesystemParams(const char* path) : path(path) {} + + const char* path; + FileSystemArgsIF* args = nullptr; +}; + +struct FileOpParams { + FileOpParams(const char* path, size_t size) : fsParams(path), size(size) {} + + [[nodiscard]] const char* path() const { return fsParams.path; } + + [[nodiscard]] FileSystemArgsIF* args() const { return fsParams.args; } + + FilesystemParams fsParams; + size_t size; + size_t offset = 0; +}; + +/** + * @brief Generic interface for objects which expose a file system to enable + * message based file handling. + * @author J. Meier, R. Mueller + */ +class HasFileSystemIF { + public: + static constexpr uint8_t INTERFACE_ID = CLASS_ID::FILE_SYSTEM; + + //! [EXPORT] : P1: Can be file system specific error code + static constexpr ReturnValue_t GENERIC_FILE_ERROR = MAKE_RETURN_CODE(0); + static constexpr ReturnValue_t GENERIC_DIR_ERROR = MAKE_RETURN_CODE(1); + static constexpr ReturnValue_t GENERIC_RENAME_ERROR = MAKE_RETURN_CODE(3); + + //! [EXPORT] : File system is currently busy + static constexpr ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(4); + //! [EXPORT] : Invalid parameters like file name or repository path + static constexpr ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(5); + + static constexpr ReturnValue_t FILE_DOES_NOT_EXIST = MAKE_RETURN_CODE(10); + static constexpr ReturnValue_t FILE_ALREADY_EXISTS = MAKE_RETURN_CODE(11); + static constexpr ReturnValue_t NOT_A_FILE = MAKE_RETURN_CODE(12); + static constexpr ReturnValue_t FILE_LOCKED = MAKE_RETURN_CODE(13); + static constexpr ReturnValue_t PERMISSION_DENIED = MAKE_RETURN_CODE(14); + + static constexpr ReturnValue_t DIRECTORY_DOES_NOT_EXIST = MAKE_RETURN_CODE(21); + static constexpr ReturnValue_t DIRECTORY_ALREADY_EXISTS = MAKE_RETURN_CODE(22); + static constexpr ReturnValue_t NOT_A_DIRECTORY = MAKE_RETURN_CODE(23); + static constexpr ReturnValue_t DIRECTORY_NOT_EMPTY = MAKE_RETURN_CODE(24); + + //! [EXPORT] : P1: Sequence number missing + static constexpr ReturnValue_t SEQUENCE_PACKET_MISSING_WRITE = MAKE_RETURN_CODE(30); + //! [EXPORT] : P1: Sequence number missing + static constexpr ReturnValue_t SEQUENCE_PACKET_MISSING_READ = MAKE_RETURN_CODE(31); + + virtual ~HasFileSystemIF() = default; + + /** + * Function to get the MessageQueueId_t of the implementing object + * @return MessageQueueId_t of the object + */ + [[nodiscard]] virtual MessageQueueId_t getCommandQueue() const { + return MessageQueueIF::NO_QUEUE; + } + + virtual bool fileExists(FilesystemParams params) = 0; + + /** + * Truncate a file, deleting its contents and setting its size to 0 accordingly. + * @param params + * @return + */ + virtual ReturnValue_t truncateFile(FilesystemParams params) = 0; + + /** + * @brief Generic function to write to a file. + * + * @details + * Implementations should not truncate the file. This is equivalent to opening a file with "r+" + * on Unix systems or using ios::out | ios::in with the C++ API. + * @param fileOpInfo General information: File name, size to write, offset, additional arguments + * @param data The data to write to the file + */ + virtual ReturnValue_t writeToFile(FileOpParams params, const uint8_t* data) = 0; + + /** + * @brief Generic function to read from a file. This variant takes a pointer to a buffer and + * performs pointer arithmetic by incrementing the pointer by the read size + * @param fileOpInfo General information: File name, size to write, offset, additional arguments + * @param buffer [in/out] Data will be read into the provided buffer, and the pointer will be + * incremented by the read length + * @param readSize [out] Will be incremented by the read length + * @param maxSize Maximum size of the provided buffer + * @param args + * @return + */ + virtual ReturnValue_t readFromFile(FileOpParams fileOpInfo, uint8_t** buffer, size_t& readSize, + size_t maxSize) = 0; + /** + * Variant of the @readFromFile which does not perform pointer arithmetic. + * @param fileOpInfo General information: File name, size to write, offset, additional arguments + * @param buf + * @param maxSize + * @return + */ + virtual ReturnValue_t readFromFile(FileOpParams fileOpInfo, uint8_t* buf, size_t maxSize) { + size_t dummy = 0; + return readFromFile(fileOpInfo, &buf, dummy, maxSize); + } + + /** + * @brief Generic function to create a new file. + * @param repositoryPath + * @param filename + * @param data + * @param size + * @param args Any other arguments which an implementation might require + * @return + */ + virtual ReturnValue_t createFile(FilesystemParams params) { + return createFile(params, nullptr, 0); + } + virtual ReturnValue_t createFile(FilesystemParams params, const uint8_t* data, size_t size) = 0; + + /** + * @brief Generic function to delete a file. + * @param repositoryPath + * @param filename + * @param args Any other arguments which an implementation might require + * @return + */ + virtual ReturnValue_t removeFile(const char* path, FileSystemArgsIF* args) = 0; + virtual ReturnValue_t removeFile(const char* path) { return removeFile(path, nullptr); } + + /** + * @brief Generic function to create a directory + * @param repositoryPath + * @param Equivalent to the -p flag in Unix systems. If some required parent directories + * do not exist, create them as well + * @param args Any other arguments which an implementation might require + * @return + */ + virtual ReturnValue_t createDirectory(FilesystemParams params, bool createParentDirs) = 0; + virtual ReturnValue_t createDirectory(FilesystemParams params) { + return createDirectory(params, false); + } + + /** + * @brief Generic function to remove a directory + * @param repositoryPath + * @param args Any other arguments which an implementation might require + */ + virtual ReturnValue_t removeDirectory(FilesystemParams params, bool deleteRecurively) = 0; + virtual ReturnValue_t removeDirectory(FilesystemParams params) { + return removeDirectory(params, false); + } + + virtual ReturnValue_t rename(const char* oldPath, const char* newPath) { + return rename(oldPath, newPath, nullptr); + } + virtual ReturnValue_t rename(const char* oldPath, const char* newPath, + FileSystemArgsIF* args) = 0; +}; + +#endif /* FSFW_MEMORY_HASFILESYSTEMIF_H_ */ diff --git a/src/fsfw/globalfunctions/AsciiConverter.cpp b/src/fsfw/globalfunctions/AsciiConverter.cpp index 6d49c777..b99814cb 100644 --- a/src/fsfw/globalfunctions/AsciiConverter.cpp +++ b/src/fsfw/globalfunctions/AsciiConverter.cpp @@ -44,7 +44,7 @@ ReturnValue_t AsciiConverter::scanAsciiHexByte(const uint8_t** dataPtr, uint8_t* *value = *value >> 4; } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t AsciiConverter::scanAsciiDecimalNumber_(uint8_t const** dataPtr, uint8_t len, @@ -99,7 +99,7 @@ ReturnValue_t AsciiConverter::scanAsciiDecimalNumber_(uint8_t const** dataPtr, u *dataPtr = ptr; - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t AsciiConverter::printFloat(uint8_t* buffer, uint32_t bufferLength, float value, @@ -124,7 +124,7 @@ ReturnValue_t AsciiConverter::printFloat(uint8_t* buffer, uint32_t bufferLength, ReturnValue_t result = printInteger(buffer + streamposition, bufferLength - streamposition - decimalPlaces - 1, value, &integerSize); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } streamposition += integerSize; @@ -161,7 +161,7 @@ ReturnValue_t AsciiConverter::printInteger(uint8_t* buffer, uint32_t bufferLengt } if (!leadingZeros && (value == 0)) { buffer[(*printedSize)++] = '0'; - return RETURN_OK; + return returnvalue::OK; } while (maximumNumber >= 1) { uint8_t number = value / maximumNumber; @@ -174,7 +174,7 @@ ReturnValue_t AsciiConverter::printInteger(uint8_t* buffer, uint32_t bufferLengt maximumNumber /= 10; } } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t AsciiConverter::printSignedInteger(uint8_t* buffer, uint32_t bufferLength, diff --git a/src/fsfw/globalfunctions/AsciiConverter.h b/src/fsfw/globalfunctions/AsciiConverter.h index db382b61..e6cd60a7 100644 --- a/src/fsfw/globalfunctions/AsciiConverter.h +++ b/src/fsfw/globalfunctions/AsciiConverter.h @@ -1,9 +1,9 @@ #ifndef ASCIICONVERTER_H_ #define ASCIICONVERTER_H_ -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" -class AsciiConverter : public HasReturnvaluesIF { +class AsciiConverter { public: static const uint8_t INTERFACE_ID = CLASS_ID::ASCII_CONVERTER; static const ReturnValue_t TOO_LONG_FOR_TARGET_TYPE = MAKE_RETURN_CODE(1); diff --git a/src/fsfw/globalfunctions/CMakeLists.txt b/src/fsfw/globalfunctions/CMakeLists.txt index 5ccd3c4c..cf8a25d5 100644 --- a/src/fsfw/globalfunctions/CMakeLists.txt +++ b/src/fsfw/globalfunctions/CMakeLists.txt @@ -1,13 +1,13 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - arrayprinter.cpp - AsciiConverter.cpp - CRC.cpp - DleEncoder.cpp - PeriodicOperationDivider.cpp - timevalOperations.cpp - Type.cpp - bitutility.cpp -) +target_sources( + ${LIB_FSFW_NAME} + PRIVATE arrayprinter.cpp + AsciiConverter.cpp + CRC.cpp + DleEncoder.cpp + DleParser.cpp + PeriodicOperationDivider.cpp + timevalOperations.cpp + Type.cpp + bitutility.cpp) add_subdirectory(math) diff --git a/src/fsfw/globalfunctions/DleEncoder.cpp b/src/fsfw/globalfunctions/DleEncoder.cpp index 23caf02a..c93b37c3 100644 --- a/src/fsfw/globalfunctions/DleEncoder.cpp +++ b/src/fsfw/globalfunctions/DleEncoder.cpp @@ -73,7 +73,7 @@ ReturnValue_t DleEncoder::encodeStreamEscaped(const uint8_t *sourceStream, size_ ++encodedIndex; } *encodedLen = encodedIndex; - return RETURN_OK; + return returnvalue::OK; } else { return STREAM_TOO_SHORT; } @@ -119,7 +119,7 @@ ReturnValue_t DleEncoder::encodeStreamNonEscaped(const uint8_t *sourceStream, si destStream[encodedIndex++] = ETX_CHAR; } *encodedLen = encodedIndex; - return RETURN_OK; + return returnvalue::OK; } else { return STREAM_TOO_SHORT; } @@ -191,7 +191,7 @@ ReturnValue_t DleEncoder::decodeStreamEscaped(const uint8_t *sourceStream, size_ case (ETX_CHAR): { *readLen = ++encodedIndex; *decodedLen = decodedIndex; - return RETURN_OK; + return returnvalue::OK; } default: { destStream[decodedIndex] = sourceStream[encodedIndex]; @@ -255,7 +255,7 @@ ReturnValue_t DleEncoder::decodeStreamNonEscaped(const uint8_t *sourceStream, // End of stream reached *readLen = encodedIndex + 2; *decodedLen = decodedIndex; - return RETURN_OK; + return returnvalue::OK; } else { *readLen = encodedIndex; return DECODING_ERROR; diff --git a/src/fsfw/globalfunctions/DleEncoder.h b/src/fsfw/globalfunctions/DleEncoder.h index 009c8656..b7242ebe 100644 --- a/src/fsfw/globalfunctions/DleEncoder.h +++ b/src/fsfw/globalfunctions/DleEncoder.h @@ -3,7 +3,7 @@ #include -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" /** * @brief This DLE Encoder (Data Link Encoder) can be used to encode and @@ -30,7 +30,7 @@ * are escaped with DLE. If the receiver detects a DLE char, it needs to read the next char * to determine whether a start (STX) or end (ETX) of a frame has been detected. */ -class DleEncoder : public HasReturnvaluesIF { +class DleEncoder { public: /** * Create an encoder instance with the given configuration. @@ -72,7 +72,7 @@ class DleEncoder : public HasReturnvaluesIF { * @param addStxEtx Adding STX start marker and ETX end marker can be omitted, * if they are added manually * @return - * - RETURN_OK for successful encoding operation + * - returnvalue::OK for successful encoding operation * - STREAM_TOO_SHORT if the destination stream is too short */ ReturnValue_t encode(const uint8_t *sourceStream, size_t sourceLen, uint8_t *destStream, @@ -87,7 +87,7 @@ class DleEncoder : public HasReturnvaluesIF { * @param maxDestStreamlen * @param decodedLen * @return - * - RETURN_OK for successful decode operation + * - returnvalue::OK for successful decode operation * - DECODE_ERROR if the source stream is invalid * - STREAM_TOO_SHORT if the destination stream is too short */ diff --git a/src/fsfw/globalfunctions/DleParser.cpp b/src/fsfw/globalfunctions/DleParser.cpp new file mode 100644 index 00000000..cc695bab --- /dev/null +++ b/src/fsfw/globalfunctions/DleParser.cpp @@ -0,0 +1,173 @@ +#include "DleParser.h" + +#include + +#include +#include +#include + +DleParser::DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf, + BufPair decodedBuf) + : decodeRingBuf(decodeRingBuf), + decoder(decoder), + encodedBuf(encodedBuf), + decodedBuf(decodedBuf) {} + +ReturnValue_t DleParser::passData(const uint8_t* data, size_t len) { + if (data == nullptr or len == 0) { + return returnvalue::FAILED; + } + return decodeRingBuf.writeData(data, len); +} + +ReturnValue_t DleParser::parseRingBuf(size_t& readSize) { + ctx.setType(DleParser::ContextType::NONE); + size_t availableData = decodeRingBuf.getAvailableReadData(); + if (availableData == 0) { + return NO_PACKET_FOUND; + } + if (availableData > encodedBuf.second) { + ErrorInfo info; + info.len = decodeRingBuf.getAvailableReadData(); + setErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info); + return returnvalue::FAILED; + } + ReturnValue_t result = decodeRingBuf.readData(encodedBuf.first, availableData); + if (result != returnvalue::OK) { + ErrorInfo info; + info.res = result; + setErrorContext(ErrorTypes::RING_BUF_ERROR, info); + return result; + } + bool stxFound = false; + size_t stxIdx = 0; + for (size_t vectorIdx = 0; vectorIdx < availableData; vectorIdx++) { + // handle STX char + if (encodedBuf.first[vectorIdx] == DleEncoder::STX_CHAR) { + if (not stxFound) { + stxFound = true; + stxIdx = vectorIdx; + } else { + // might be lost packet, so we should advance the read pointer + // without skipping the STX + readSize = vectorIdx; + ErrorInfo info; + setErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info); + return POSSIBLE_PACKET_LOSS; + } + } + // handle ETX char + if (encodedBuf.first[vectorIdx] == DleEncoder::ETX_CHAR) { + if (stxFound) { + // This is propably a packet, so we decode it. + size_t decodedLen = 0; + size_t dummy = 0; + + ReturnValue_t result = + decoder.decode(&encodedBuf.first[stxIdx], availableData - stxIdx, &dummy, + decodedBuf.first, decodedBuf.second, &decodedLen); + if (result == returnvalue::OK) { + ctx.setType(ContextType::PACKET_FOUND); + ctx.decodedPacket.first = decodedBuf.first; + ctx.decodedPacket.second = decodedLen; + readSize = ++vectorIdx; + return returnvalue::OK; + } else { + // invalid packet, skip. + readSize = ++vectorIdx; + ErrorInfo info; + info.res = result; + setErrorContext(ErrorTypes::DECODE_ERROR, info); + return POSSIBLE_PACKET_LOSS; + } + } else { + // might be lost packet, so we should advance the read pointer + readSize = ++vectorIdx; + ErrorInfo info; + info.len = 0; + setErrorContext(ErrorTypes::CONSECUTIVE_ETX_CHARS, info); + return POSSIBLE_PACKET_LOSS; + } + } + } + return NO_PACKET_FOUND; +} + +void DleParser::defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "DleParserBase::handleFoundPacket: Detected DLE packet with " << len << " bytes" + << std::endl; +#else + sif::printInfo("DleParserBase::handleFoundPacket: Detected DLE packet with %d bytes\n", len); +#endif +#endif +} + +void DleParser::defaultErrorHandler() { + if (ctx.getType() != DleParser::ContextType::ERROR) { + errorPrinter("No error"); + return; + } + switch (ctx.error.first) { + case (ErrorTypes::NONE): { + errorPrinter("No error"); + break; + } + case (ErrorTypes::DECODE_ERROR): { + errorPrinter("Decode Error"); + break; + } + case (ErrorTypes::RING_BUF_ERROR): { + errorPrinter("Ring Buffer Error"); + break; + } + case (ErrorTypes::ENCODED_BUF_TOO_SMALL): + case (ErrorTypes::DECODING_BUF_TOO_SMALL): { + char opt[64]; + snprintf(opt, sizeof(opt), ": Too small for packet with length %zu", + ctx.decodedPacket.second); + if (ctx.error.first == ErrorTypes::ENCODED_BUF_TOO_SMALL) { + errorPrinter("Encoded buf too small", opt); + } else { + errorPrinter("Decoding buf too small", opt); + } + break; + } + case (ErrorTypes::CONSECUTIVE_STX_CHARS): { + errorPrinter("Consecutive STX chars detected"); + break; + } + case (ErrorTypes::CONSECUTIVE_ETX_CHARS): { + errorPrinter("Consecutive ETX chars detected"); + break; + } + } +} + +void DleParser::errorPrinter(const char* str, const char* opt) { + if (opt == nullptr) { + opt = ""; + } +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "DleParserBase::handleParseError: " << str << opt << std::endl; +#else + sif::printInfo("DleParserBase::handleParseError: %s%s\n", str, opt); +#endif +#endif +} + +void DleParser::setErrorContext(ErrorTypes err, ErrorInfo info) { + ctx.setType(ContextType::ERROR); + ctx.error.first = err; + ctx.error.second = info; +} + +ReturnValue_t DleParser::confirmBytesRead(size_t bytesRead) { + return decodeRingBuf.deleteData(bytesRead); +} + +const DleParser::Context& DleParser::getContext() { return ctx; } + +void DleParser::reset() { decodeRingBuf.clear(); } diff --git a/src/fsfw/globalfunctions/DleParser.h b/src/fsfw/globalfunctions/DleParser.h new file mode 100644 index 00000000..9802017a --- /dev/null +++ b/src/fsfw/globalfunctions/DleParser.h @@ -0,0 +1,127 @@ +#pragma once + +#include +#include +#include + +#include +#include + +/** + * @brief This base helper class can be used to extract DLE encoded packets from a data stream + * @details + * The core API of the parser takes received packets which can contains DLE packets. The parser + * can deal with DLE packets split across multiple packets. It does so by using a dedicated + * decoding ring buffer. The user can process received packets and detect errors by + * overriding two provided virtual methods. This also allows detecting multiple DLE packets + * inside one passed packet. + */ +class DleParser { + public: + static constexpr ReturnValue_t NO_PACKET_FOUND = returnvalue::makeCode(1, 1); + static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS = returnvalue::makeCode(1, 2); + using BufPair = std::pair; + + enum class ContextType { NONE, PACKET_FOUND, ERROR }; + + enum class ErrorTypes { + NONE, + ENCODED_BUF_TOO_SMALL, + DECODING_BUF_TOO_SMALL, + DECODE_ERROR, + RING_BUF_ERROR, + CONSECUTIVE_STX_CHARS, + CONSECUTIVE_ETX_CHARS + }; + + union ErrorInfo { + size_t len; + ReturnValue_t res; + }; + + using ErrorPair = std::pair; + + struct Context { + public: + Context() { setType(ContextType::PACKET_FOUND); } + + void setType(ContextType type) { + this->type = type; + if (type == ContextType::PACKET_FOUND) { + error.first = ErrorTypes::NONE; + error.second.len = 0; + } else { + decodedPacket.first = nullptr; + decodedPacket.second = 0; + } + } + + ContextType getType() const { return type; } + + BufPair decodedPacket = {}; + ErrorPair error; + + private: + ContextType type; + }; + + /** + * Base class constructor + * @param decodeRingBuf Ring buffer used to store multiple packets to allow detecting DLE packets + * split across multiple packets + * @param decoder Decoder instance + * @param encodedBuf Buffer used to store encoded packets. It has to be large enough to hold + * the largest expected encoded DLE packet size + * @param decodedBuf Buffer used to store decoded packets. It has to be large enough to hold the + * largest expected decoded DLE packet size + * @param handler Function which will be called on a found packet + * @param args Arbitrary user argument + */ + DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf, + BufPair decodedBuf); + + /** + * This function allows to pass new data into the parser. It then scans for DLE packets + * automatically and inserts (part of) the packet into a ring buffer if necessary. + * @param data + * @param len + * @return + */ + ReturnValue_t passData(const uint8_t* data, size_t len); + + ReturnValue_t parseRingBuf(size_t& bytesRead); + + ReturnValue_t confirmBytesRead(size_t bytesRead); + + const Context& getContext(); + /** + * Example found packet handler + * function call + * @param packet Decoded packet + * @param len Length of detected packet + */ + void defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args); + /** + * Will be called if an error occured in the #passData call + * @param err + * @param ctx Context information depending on the error type + * - For buffer length errors, will be set to the detected packet length which is too large + * - For decode or ring buffer errors, will be set to the result returned from the failed call + */ + void defaultErrorHandler(); + + static void errorPrinter(const char* str, const char* opt = nullptr); + + void setErrorContext(ErrorTypes err, ErrorInfo ctx); + /** + * Resets the parser by resetting the internal states and clearing the decoding ring buffer + */ + void reset(); + + private: + SimpleRingBuffer& decodeRingBuf; + DleEncoder& decoder; + BufPair encodedBuf; + BufPair decodedBuf; + Context ctx; +}; diff --git a/src/fsfw/globalfunctions/Type.cpp b/src/fsfw/globalfunctions/Type.cpp index 71193673..42c6817e 100644 --- a/src/fsfw/globalfunctions/Type.cpp +++ b/src/fsfw/globalfunctions/Type.cpp @@ -52,12 +52,12 @@ ReturnValue_t Type::serialize(uint8_t** buffer, size_t* size, size_t maxSize, uint8_t ptc; uint8_t pfc; ReturnValue_t result = getPtcPfc(&ptc, &pfc); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&ptc, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -75,18 +75,18 @@ ReturnValue_t Type::deSerialize(const uint8_t** buffer, size_t* size, Endianness uint8_t ptc; uint8_t pfc; ReturnValue_t result = SerializeAdapter::deSerialize(&ptc, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::deSerialize(&pfc, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } actualType = getActualType(ptc, pfc); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Type::getPtcPfc(uint8_t* ptc, uint8_t* pfc) const { @@ -124,9 +124,9 @@ ReturnValue_t Type::getPtcPfc(uint8_t* ptc, uint8_t* pfc) const { *pfc = 2; break; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } Type::ActualType_t Type::getActualType(uint8_t ptc, uint8_t pfc) { diff --git a/src/fsfw/globalfunctions/Type.h b/src/fsfw/globalfunctions/Type.h index 385d7219..d716c223 100644 --- a/src/fsfw/globalfunctions/Type.h +++ b/src/fsfw/globalfunctions/Type.h @@ -3,7 +3,7 @@ #include -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/serialize/SerializeIF.h" /** @@ -44,13 +44,13 @@ class Type : public SerializeIF { static ActualType_t getActualType(uint8_t ptc, uint8_t pfc); - virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const override; + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override; - virtual size_t getSerializedSize() const override; + size_t getSerializedSize() const override; - virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, - Endianness streamEndianness) override; + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override; private: ActualType_t actualType; diff --git a/src/fsfw/globalfunctions/matching/MatchTree.h b/src/fsfw/globalfunctions/matching/MatchTree.h index f7775d45..69f660d3 100644 --- a/src/fsfw/globalfunctions/matching/MatchTree.h +++ b/src/fsfw/globalfunctions/matching/MatchTree.h @@ -24,8 +24,8 @@ class MatchTree : public SerializeableMatcherIF, public BinaryTree>(root.element), maxDepth(maxDepth) {} MatchTree() : BinaryTree>(), maxDepth(-1) {} - virtual ~MatchTree() {} - virtual bool match(T number) { return matchesTree(number); } + virtual ~MatchTree() { clear(); } + virtual bool match(T number) override { return matchesTree(number); } bool matchesTree(T number) { iterator iter = this->begin(); if (iter == this->end()) { @@ -40,34 +40,34 @@ class MatchTree : public SerializeableMatcherIF, public BinaryTreecountRight(iter); ReturnValue_t result = SerializeAdapter::serialize(&count, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (iter == this->end()) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } result = iter->serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (maxDepth > 0) { MatchTree temp(iter.left(), maxDepth - 1); result = temp.serialize(buffer, size, maxSize, streamEndianness); } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } iter = iter.right(); while (iter != this->end()) { result = iter->serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (maxDepth > 0) { MatchTree temp(iter.left(), maxDepth - 1); result = temp.serialize(buffer, size, maxSize, streamEndianness); } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } iter = iter.right(); @@ -106,7 +106,7 @@ class MatchTree : public SerializeableMatcherIF, public BinaryTree, public BinaryTreeerase(position); - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; if (children.first != this->end()) { result = removeElementAndAllChildren(children.first); } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (children.second != this->end()) { result = removeElementAndAllChildren(children.second); } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } // Delete element itself. @@ -143,13 +143,13 @@ class MatchTree : public SerializeableMatcherIF, public BinaryTreeend()) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } // Delete everything from the AND branch. - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; if (position.left() != this->end()) { result = removeElementAndAllChildren(position.left()); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } } @@ -176,9 +176,51 @@ class MatchTree : public SerializeableMatcherIF, public BinaryTree>::rootNode; + + if (localRoot == nullptr) { + return; + } + + Node* node = localRoot->left; + + while (true) { + if (node->left != nullptr) { + node = node->left; + continue; + } + if (node->right != nullptr) { + node = node->right; + continue; + } + if (node->parent == nullptr) { + // this is the root node with no children + if (node->value != nullptr) { + cleanUpElement(iterator(node)); + } + return; + } + // leaf + { + Node* parent = node->parent; + if (parent->left == node) { + parent->left = nullptr; + } else { + parent->right = nullptr; + } + cleanUpElement(iterator(node)); + node = parent; + } + } + } + + virtual ReturnValue_t cleanUpElement(iterator position) { return returnvalue::OK; } bool matchSubtree(iterator iter, T number) { + if (iter == nullptr) { + return false; + } bool isMatch = iter->match(number); if (isMatch) { if (iter.left() == this->end()) { diff --git a/src/fsfw/globalfunctions/matching/RangeMatcher.h b/src/fsfw/globalfunctions/matching/RangeMatcher.h index 4e1f3922..f48c705c 100644 --- a/src/fsfw/globalfunctions/matching/RangeMatcher.h +++ b/src/fsfw/globalfunctions/matching/RangeMatcher.h @@ -15,7 +15,7 @@ class RangeMatcher : public SerializeableMatcherIF { RangeMatcher(T lowerBound, T upperBound, bool inverted = false) : inverted(inverted), lowerBound(lowerBound), upperBound(upperBound) {} - bool match(T input) { + bool match(T input) override { if (inverted) { return !doMatch(input); } else { @@ -27,11 +27,11 @@ class RangeMatcher : public SerializeableMatcherIF { SerializeIF::Endianness streamEndianness) const override { ReturnValue_t result = SerializeAdapter::serialize(&lowerBound, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&upperBound, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return SerializeAdapter::serialize(&inverted, buffer, size, maxSize, streamEndianness); @@ -45,11 +45,11 @@ class RangeMatcher : public SerializeableMatcherIF { SerializeIF::Endianness streamEndianness) override { ReturnValue_t result = SerializeAdapter::deSerialize(&lowerBound, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::deSerialize(&upperBound, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return SerializeAdapter::deSerialize(&inverted, buffer, size, streamEndianness); diff --git a/src/fsfw/globalfunctions/math/CMakeLists.txt b/src/fsfw/globalfunctions/math/CMakeLists.txt index a9c4ded7..1eeb69b5 100644 --- a/src/fsfw/globalfunctions/math/CMakeLists.txt +++ b/src/fsfw/globalfunctions/math/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - QuaternionOperations.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE QuaternionOperations.cpp) diff --git a/src/fsfw/globalfunctions/timevalOperations.cpp b/src/fsfw/globalfunctions/timevalOperations.cpp index e2b35512..79c07eaf 100644 --- a/src/fsfw/globalfunctions/timevalOperations.cpp +++ b/src/fsfw/globalfunctions/timevalOperations.cpp @@ -1,8 +1,8 @@ #include "fsfw/globalfunctions/timevalOperations.h" timeval& operator+=(timeval& lhs, const timeval& rhs) { - int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; - sum += rhs.tv_sec * 1000000. + rhs.tv_usec; + int64_t sum = static_cast(lhs.tv_sec) * 1000000. + lhs.tv_usec; + sum += static_cast(rhs.tv_sec) * 1000000. + rhs.tv_usec; lhs.tv_sec = sum / 1000000; lhs.tv_usec = sum - lhs.tv_sec * 1000000; return lhs; diff --git a/src/fsfw/health/CMakeLists.txt b/src/fsfw/health/CMakeLists.txt index d5f3ccd3..37e4ce48 100644 --- a/src/fsfw/health/CMakeLists.txt +++ b/src/fsfw/health/CMakeLists.txt @@ -1,6 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - HealthHelper.cpp - HealthMessage.cpp - HealthTable.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE HealthHelper.cpp HealthMessage.cpp + HealthTable.cpp) diff --git a/src/fsfw/health/HasHealthIF.h b/src/fsfw/health/HasHealthIF.h index 41abeef3..16666bbc 100644 --- a/src/fsfw/health/HasHealthIF.h +++ b/src/fsfw/health/HasHealthIF.h @@ -3,7 +3,7 @@ #include "../events/Event.h" #include "../ipc/MessageQueueSenderIF.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" class HasHealthIF { public: @@ -16,26 +16,24 @@ class HasHealthIF { }; static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF; - static const ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1); - static const ReturnValue_t INVALID_HEALTH_STATE = MAKE_RETURN_CODE(2); + static constexpr ReturnValue_t OBJECT_NOT_HEALTHY = returnvalue::makeCode(INTERFACE_ID, 1); + static constexpr ReturnValue_t INVALID_HEALTH_STATE = returnvalue::makeCode(INTERFACE_ID, 2); + static constexpr ReturnValue_t IS_EXTERNALLY_CONTROLLED = returnvalue::makeCode(INTERFACE_ID, 3); static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER_1; + //! P1: New Health, P2: Old Health 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; diff --git a/src/fsfw/health/HealthHelper.cpp b/src/fsfw/health/HealthHelper.cpp index 4bef128c..f6077ea1 100644 --- a/src/fsfw/health/HealthHelper.cpp +++ b/src/fsfw/health/HealthHelper.cpp @@ -5,19 +5,23 @@ HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId) : objectId(objectId), owner(owner) {} -HealthHelper::~HealthHelper() {} +HealthHelper::~HealthHelper() { + if (healthTable != nullptr) { + healthTable->removeObject(objectId); + } +} ReturnValue_t HealthHelper::handleHealthCommand(CommandMessage* message) { switch (message->getCommand()) { case HealthMessage::HEALTH_SET: handleSetHealthCommand(message); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; case HealthMessage::HEALTH_ANNOUNCE: { eventSender->forwardEvent(HasHealthIF::HEALTH_INFO, getHealth(), getHealth()); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -53,10 +57,10 @@ ReturnValue_t HealthHelper::initialize() { } ReturnValue_t result = healthTable->registerObject(objectId, HasHealthIF::HEALTHY); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void HealthHelper::setHealth(HasHealthIF::HealthState health) { @@ -76,7 +80,7 @@ void HealthHelper::informParent(HasHealthIF::HealthState health, CommandMessage information; HealthMessage::setHealthMessage(&information, HealthMessage::HEALTH_INFO, health, oldHealth); if (MessageQueueSenderIF::sendMessage(parentQueue, &information, owner->getCommandQueue()) != - HasReturnvaluesIF::RETURN_OK) { + returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::debug << "HealthHelper::informParent: sending health reply failed." << std::endl; #endif @@ -89,13 +93,13 @@ void HealthHelper::handleSetHealthCommand(CommandMessage* command) { return; } CommandMessage reply; - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { HealthMessage::setHealthMessage(&reply, HealthMessage::REPLY_HEALTH_SET); } else { reply.setReplyRejected(result, command->getCommand()); } if (MessageQueueSenderIF::sendMessage(command->getSender(), &reply, owner->getCommandQueue()) != - HasReturnvaluesIF::RETURN_OK) { + returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::debug << "HealthHelper::handleHealthCommand: sending health " "reply failed." diff --git a/src/fsfw/health/HealthHelper.h b/src/fsfw/health/HealthHelper.h index 9b3b0e2b..6b550f90 100644 --- a/src/fsfw/health/HealthHelper.h +++ b/src/fsfw/health/HealthHelper.h @@ -5,7 +5,7 @@ #include "../events/EventReportingProxyIF.h" #include "../ipc/MessageQueueIF.h" #include "../objectmanager/ObjectManagerIF.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "HasHealthIF.h" #include "HealthMessage.h" #include "HealthTableIF.h" @@ -55,8 +55,8 @@ class HealthHelper { * * @param message * @return - * -@c RETURN_OK if the message was handled - * -@c RETURN_FAILED if the message could not be handled + * -@c returnvalue::OK if the message was handled + * -@c returnvalue::FAILED if the message could not be handled * (ie it was not a @c HEALTH_SET or @c HEALTH_READ message) */ ReturnValue_t handleHealthCommand(CommandMessage* message); @@ -88,9 +88,9 @@ class HealthHelper { * @param parentQueue The queue ID of the parent object. * Set to 0 if no parent present * @return - * -@c RETURN_OK if the Health Table was found and the object + * -@c returnvalue::OK if the Health Table was found and the object * could be registered - * -@c RETURN_FAILED else + * -@c returnvalue::FAILED else */ ReturnValue_t initialize(MessageQueueId_t parentQueue); diff --git a/src/fsfw/health/HealthTable.cpp b/src/fsfw/health/HealthTable.cpp index ab4881f4..3fcf7f77 100644 --- a/src/fsfw/health/HealthTable.cpp +++ b/src/fsfw/health/HealthTable.cpp @@ -6,8 +6,6 @@ HealthTable::HealthTable(object_id_t objectid) : SystemObject(objectid) { mutex = MutexFactory::instance()->createMutex(); - ; - mapIterator = healthMap.begin(); } @@ -21,10 +19,19 @@ HealthTable::~HealthTable() { MutexFactory::instance()->deleteMutex(mutex); } ReturnValue_t HealthTable::registerObject(object_id_t object, HasHealthIF::HealthState initilialState) { if (healthMap.count(object) != 0) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } healthMap.emplace(object, initilialState); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; +} + +ReturnValue_t HealthTable::removeObject(object_id_t object) { + mapIterator = healthMap.find(object); + if (mapIterator == healthMap.end()) { + return returnvalue::FAILED; + } + healthMap.erase(mapIterator); + return returnvalue::OK; } void HealthTable::setHealth(object_id_t object, HasHealthIF::HealthState newState) { @@ -67,7 +74,7 @@ void HealthTable::printAll(uint8_t* pointer, size_t maxSize) { uint16_t count = healthMap.size(); ReturnValue_t result = SerializeAdapter::serialize(&count, &pointer, &size, maxSize, SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "HealthTable::printAll: Serialization of health table failed" << std::endl; @@ -80,26 +87,26 @@ void HealthTable::printAll(uint8_t* pointer, size_t maxSize) { for (const auto& health : healthMap) { result = SerializeAdapter::serialize(&health.first, &pointer, &size, maxSize, SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return; } uint8_t healthValue = health.second; result = SerializeAdapter::serialize(&healthValue, &pointer, &size, maxSize, SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return; } } } ReturnValue_t HealthTable::iterate(HealthEntry* value, bool reset) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; MutexGuard(mutex, timeoutType, mutexTimeoutMs); if (reset) { mapIterator = healthMap.begin(); } if (mapIterator == healthMap.end()) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } *value = *mapIterator; mapIterator++; diff --git a/src/fsfw/health/HealthTable.h b/src/fsfw/health/HealthTable.h index 4718abc3..7b42dfba 100644 --- a/src/fsfw/health/HealthTable.h +++ b/src/fsfw/health/HealthTable.h @@ -8,15 +8,18 @@ #include "HealthTableIF.h" class HealthTable : public HealthTableIF, public SystemObject { + friend class CServiceHealthCommanding; + public: - HealthTable(object_id_t objectid); - virtual ~HealthTable(); + explicit HealthTable(object_id_t objectid); + ~HealthTable() override; void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs); /** HealthTableIF overrides */ virtual ReturnValue_t registerObject( object_id_t object, HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY) override; + ReturnValue_t removeObject(object_id_t object) override; virtual size_t getPrintSize() override; virtual void printAll(uint8_t* pointer, size_t maxSize) override; diff --git a/src/fsfw/health/HealthTableIF.h b/src/fsfw/health/HealthTableIF.h index 50266ac2..0b993691 100644 --- a/src/fsfw/health/HealthTableIF.h +++ b/src/fsfw/health/HealthTableIF.h @@ -4,7 +4,7 @@ #include #include "../objectmanager/ObjectManagerIF.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "ManagesHealthIF.h" class HealthTableIF : public ManagesHealthIF { @@ -14,6 +14,8 @@ class HealthTableIF : public ManagesHealthIF { virtual ReturnValue_t registerObject( object_id_t object, HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY) = 0; + virtual ReturnValue_t removeObject(object_id_t objectId) = 0; + virtual size_t getPrintSize() = 0; virtual void printAll(uint8_t *pointer, size_t maxSize) = 0; diff --git a/src/fsfw/housekeeping/AcceptsHkPacketsIF.h b/src/fsfw/housekeeping/AcceptsHkPacketsIF.h index 07882829..7648e7ed 100644 --- a/src/fsfw/housekeeping/AcceptsHkPacketsIF.h +++ b/src/fsfw/housekeeping/AcceptsHkPacketsIF.h @@ -1,12 +1,12 @@ #ifndef FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_ #define FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_ -#include "../ipc/MessageQueueMessageIF.h" +#include "fsfw/ipc/MessageQueueMessageIF.h" class AcceptsHkPacketsIF { public: - virtual ~AcceptsHkPacketsIF(){}; - virtual MessageQueueId_t getHkQueue() const = 0; + virtual ~AcceptsHkPacketsIF() = default; + [[nodiscard]] virtual MessageQueueId_t getHkQueue() const = 0; }; #endif /* FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_ */ diff --git a/src/fsfw/housekeeping/CMakeLists.txt b/src/fsfw/housekeeping/CMakeLists.txt index fecad2e3..236d3204 100644 --- a/src/fsfw/housekeeping/CMakeLists.txt +++ b/src/fsfw/housekeeping/CMakeLists.txt @@ -1,5 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - HousekeepingMessage.cpp - PeriodicHousekeepingHelper.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE HousekeepingMessage.cpp + PeriodicHousekeepingHelper.cpp) diff --git a/src/fsfw/housekeeping/HousekeepingSetPacket.h b/src/fsfw/housekeeping/HousekeepingSetPacket.h index 96eaaed9..fa039da8 100644 --- a/src/fsfw/housekeeping/HousekeepingSetPacket.h +++ b/src/fsfw/housekeeping/HousekeepingSetPacket.h @@ -22,7 +22,7 @@ class HousekeepingSetPacket : public SerialLinkedListAdapter { Endianness streamEndianness) const override { ReturnValue_t result = SerialLinkedListAdapter::serialize(buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return dataSet->serializeLocalPoolIds(buffer, size, maxSize, streamEndianness); @@ -36,7 +36,7 @@ class HousekeepingSetPacket : public SerialLinkedListAdapter { ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) override { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } private: diff --git a/src/fsfw/housekeeping/HousekeepingSnapshot.h b/src/fsfw/housekeeping/HousekeepingSnapshot.h index c3eabe80..9807795d 100644 --- a/src/fsfw/housekeeping/HousekeepingSnapshot.h +++ b/src/fsfw/housekeeping/HousekeepingSnapshot.h @@ -54,8 +54,8 @@ class HousekeepingSnapshot : public SerializeIF { HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize, LocalPoolObjectBase* dataSetPtr) : timeStamp(timeStamp), timeStampSize(timeStampSize), updateData(dataSetPtr){}; - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const { + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const { if (timeStamp != nullptr) { /* Endianness will always be MACHINE, so we can simply use memcpy here. */ @@ -64,21 +64,21 @@ class HousekeepingSnapshot : public SerializeIF { *buffer += timeStampSize; } if (updateData == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } return updateData->serialize(buffer, size, maxSize, streamEndianness); } - virtual size_t getSerializedSize() const { + size_t getSerializedSize() const { if (updateData == nullptr) { return 0; } return timeStampSize + updateData->getSerializedSize(); } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - SerializeIF::Endianness streamEndianness) override { + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override { if (*size < timeStampSize) { return SerializeIF::STREAM_TOO_SHORT; } @@ -92,7 +92,7 @@ class HousekeepingSnapshot : public SerializeIF { } if (updateData == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (*size < updateData->getSerializedSize()) { return SerializeIF::STREAM_TOO_SHORT; diff --git a/src/fsfw/internalerror/CMakeLists.txt b/src/fsfw/internalerror/CMakeLists.txt index 2b383914..87d3c3f7 100644 --- a/src/fsfw/internalerror/CMakeLists.txt +++ b/src/fsfw/internalerror/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - InternalErrorReporter.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE InternalErrorReporter.cpp) diff --git a/src/fsfw/internalerror/InternalErrorReporter.cpp b/src/fsfw/internalerror/InternalErrorReporter.cpp index fa16ec3f..fb2dc8a6 100644 --- a/src/fsfw/internalerror/InternalErrorReporter.cpp +++ b/src/fsfw/internalerror/InternalErrorReporter.cpp @@ -7,14 +7,17 @@ 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) { + commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth); mutex = MutexFactory::instance()->createMutex(); } -InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); } +InternalErrorReporter::~InternalErrorReporter() { + MutexFactory::instance()->deleteMutex(mutex); + QueueFactory::instance()->deleteMessageQueue(commandQueue); +} void InternalErrorReporter::setDiagnosticPrintout(bool enable) { this->diagnosticPrintout = enable; @@ -52,7 +55,7 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { { PoolReadGuard readGuard(&internalErrorDataset); - if (readGuard.getReadResult() == HasReturnvaluesIF::RETURN_OK) { + if (readGuard.getReadResult() == returnvalue::OK) { internalErrorDataset.queueHits.value += newQueueHits; internalErrorDataset.storeHits.value += newStoreHits; internalErrorDataset.tmHits.value += newTmHits; @@ -64,7 +67,7 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { } poolManager.performHkOperation(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void InternalErrorReporter::queueMessageNotSent() { incrementQueueHits(); } @@ -126,13 +129,14 @@ MessageQueueId_t InternalErrorReporter::getCommandQueue() const { ReturnValue_t InternalErrorReporter::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(errorPoolIds::TM_HITS, new PoolEntry()); - localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, new PoolEntry()); - localDataPoolMap.emplace(errorPoolIds::STORE_HITS, new PoolEntry()); - poolManager.subscribeForPeriodicPacket(internalErrorSid, false, getPeriodicOperationFrequency(), - true); + localDataPoolMap.emplace(errorPoolIds::TM_HITS, &tmHitsEntry); + localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, &queueHitsEntry); + localDataPoolMap.emplace(errorPoolIds::STORE_HITS, &storeHitsEntry); + poolManager.subscribeForDiagPeriodicPacket(subdp::DiagnosticsHkPeriodicParams( + internalErrorSid, false, + static_cast(getPeriodicOperationFrequency()) / static_cast(1000.0))); internalErrorDataset.setValidity(true, true); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } dur_millis_t InternalErrorReporter::getPeriodicOperationFrequency() const { @@ -147,7 +151,7 @@ void InternalErrorReporter::setTaskIF(PeriodicTaskIF *task) { this->executingTas ReturnValue_t InternalErrorReporter::initialize() { ReturnValue_t result = poolManager.initialize(commandQueue); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return SystemObject::initialize(); diff --git a/src/fsfw/internalerror/InternalErrorReporter.h b/src/fsfw/internalerror/InternalErrorReporter.h index 549be4bd..ca82d1a4 100644 --- a/src/fsfw/internalerror/InternalErrorReporter.h +++ b/src/fsfw/internalerror/InternalErrorReporter.h @@ -72,6 +72,9 @@ class InternalErrorReporter : public SystemObject, uint32_t queueHits = 0; uint32_t tmHits = 0; uint32_t storeHits = 0; + PoolEntry tmHitsEntry = PoolEntry(); + PoolEntry storeHitsEntry = PoolEntry(); + PoolEntry queueHitsEntry = PoolEntry(); uint32_t getAndResetQueueHits(); void incrementQueueHits(); diff --git a/src/fsfw/internalerror/InternalErrorReporterIF.h b/src/fsfw/internalerror/InternalErrorReporterIF.h index 61bb52e7..aa917d21 100644 --- a/src/fsfw/internalerror/InternalErrorReporterIF.h +++ b/src/fsfw/internalerror/InternalErrorReporterIF.h @@ -12,7 +12,7 @@ */ class InternalErrorReporterIF { public: - virtual ~InternalErrorReporterIF() {} + virtual ~InternalErrorReporterIF() = default; /** * @brief Function to be called if a message queue could not be sent. * @details OSAL Implementations should call this function to indicate that diff --git a/src/fsfw/ipc/CMakeLists.txt b/src/fsfw/ipc/CMakeLists.txt index 3bfe510d..92b91f35 100644 --- a/src/fsfw/ipc/CMakeLists.txt +++ b/src/fsfw/ipc/CMakeLists.txt @@ -1,6 +1,3 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - CommandMessage.cpp - CommandMessageCleaner.cpp - MessageQueueMessage.cpp - MessageQueueBase.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} PRIVATE CommandMessage.cpp CommandMessageCleaner.cpp + MessageQueueMessage.cpp MessageQueueBase.cpp) diff --git a/src/fsfw/ipc/CommandMessageCleaner.cpp b/src/fsfw/ipc/CommandMessageCleaner.cpp index 328441e6..0a43774b 100644 --- a/src/fsfw/ipc/CommandMessageCleaner.cpp +++ b/src/fsfw/ipc/CommandMessageCleaner.cpp @@ -1,10 +1,9 @@ #include "fsfw/ipc/CommandMessageCleaner.h" -#include "fsfw/FSFW.h" #include "fsfw/devicehandlers/DeviceHandlerMessage.h" +#include "fsfw/filesystem/GenericFileSystemMessage.h" #include "fsfw/health/HealthMessage.h" #include "fsfw/housekeeping/HousekeepingMessage.h" -#include "fsfw/memory/GenericFileSystemMessage.h" #include "fsfw/memory/MemoryMessage.h" #include "fsfw/modes/ModeMessage.h" #include "fsfw/monitoring/MonitoringMessage.h" diff --git a/src/fsfw/ipc/CommandMessageIF.h b/src/fsfw/ipc/CommandMessageIF.h index aea08203..dc8f7109 100644 --- a/src/fsfw/ipc/CommandMessageIF.h +++ b/src/fsfw/ipc/CommandMessageIF.h @@ -1,7 +1,7 @@ #ifndef FSFW_IPC_COMMANDMESSAGEIF_H_ #define FSFW_IPC_COMMANDMESSAGEIF_H_ -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "FwMessageTypes.h" #include "MessageQueueMessageIF.h" diff --git a/src/fsfw/ipc/MessageQueueBase.cpp b/src/fsfw/ipc/MessageQueueBase.cpp index 1b0934ff..56041bee 100644 --- a/src/fsfw/ipc/MessageQueueBase.cpp +++ b/src/fsfw/ipc/MessageQueueBase.cpp @@ -1,14 +1,14 @@ #include "MessageQueueBase.h" -MessageQueueBase::MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, - MqArgs* args): id(id) { +MessageQueueBase::MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* args) + : id(id) { this->defaultDest = defaultDest; - if(args != nullptr) { + if (args != nullptr) { this->args = *args; } } -MessageQueueBase::~MessageQueueBase() {} +MessageQueueBase::~MessageQueueBase() = default; ReturnValue_t MessageQueueBase::sendToDefault(MessageQueueMessageIF* message) { return sendToDefaultFrom(message, this->getId(), false); @@ -23,35 +23,25 @@ ReturnValue_t MessageQueueBase::reply(MessageQueueMessageIF* message) { } ReturnValue_t MessageQueueBase::receiveMessage(MessageQueueMessageIF* message, - MessageQueueId_t* receivedFrom) { + MessageQueueId_t* receivedFrom) { ReturnValue_t status = this->receiveMessage(message); *receivedFrom = this->last; return status; } -MessageQueueId_t MessageQueueBase::getLastPartner() const { - return last; -} +MessageQueueId_t MessageQueueBase::getLastPartner() const { return last; } -MessageQueueId_t MessageQueueBase::getId() const { - return id; -} +MessageQueueId_t MessageQueueBase::getId() const { return id; } -MqArgs& MessageQueueBase::getMqArgs() { - return args; -} +MqArgs& MessageQueueBase::getMqArgs() { return args; } void MessageQueueBase::setDefaultDestination(MessageQueueId_t defaultDestination) { this->defaultDest = defaultDestination; } -MessageQueueId_t MessageQueueBase::getDefaultDestination() const { - return defaultDest; -} +MessageQueueId_t MessageQueueBase::getDefaultDestination() const { return defaultDest; } -bool MessageQueueBase::isDefaultDestinationSet() const { - return (defaultDest != NO_QUEUE); -} +bool MessageQueueBase::isDefaultDestinationSet() const { return (defaultDest != NO_QUEUE); } ReturnValue_t MessageQueueBase::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message, bool ignoreFault) { diff --git a/src/fsfw/ipc/MessageQueueBase.h b/src/fsfw/ipc/MessageQueueBase.h index 8313f69a..c4de8eeb 100644 --- a/src/fsfw/ipc/MessageQueueBase.h +++ b/src/fsfw/ipc/MessageQueueBase.h @@ -1,41 +1,40 @@ #ifndef FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_ #define FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_ -#include #include +#include -class MessageQueueBase: public MessageQueueIF { -public: +class MessageQueueBase : public MessageQueueIF { + public: MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* mqArgs); - virtual ~MessageQueueBase(); + ~MessageQueueBase() override; // Default implementations for MessageQueueIF where possible - virtual MessageQueueId_t getLastPartner() const override; - virtual MessageQueueId_t getId() const override; - virtual MqArgs& getMqArgs() override; - virtual void setDefaultDestination(MessageQueueId_t defaultDestination) override; - virtual MessageQueueId_t getDefaultDestination() const override; - virtual bool isDefaultDestinationSet() const override; - virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message, - bool ignoreFault) override; - virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override; - virtual ReturnValue_t reply(MessageQueueMessageIF* message) override; - virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message, - MessageQueueId_t* receivedFrom) override; - virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, - MessageQueueId_t sentFrom, bool ignoreFault = false) override; + [[nodiscard]] MessageQueueId_t getLastPartner() const override; + [[nodiscard]] MessageQueueId_t getId() const override; + MqArgs& getMqArgs() override; + void setDefaultDestination(MessageQueueId_t defaultDestination) override; + [[nodiscard]] MessageQueueId_t getDefaultDestination() const override; + [[nodiscard]] bool isDefaultDestinationSet() const override; + ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message, + bool ignoreFault) override; + ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override; + ReturnValue_t reply(MessageQueueMessageIF* message) override; + ReturnValue_t receiveMessage(MessageQueueMessageIF* message, + MessageQueueId_t* receivedFrom) override; + ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault = false) override; // OSAL specific, forward the abstract function - virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0; - virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, - MessageQueueId_t sentFrom, bool ignoreFault = false) = 0; -protected: + ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override = 0; + ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, + MessageQueueId_t sentFrom, bool ignoreFault = false) override = 0; + + protected: MessageQueueId_t id = MessageQueueIF::NO_QUEUE; MessageQueueId_t last = MessageQueueIF::NO_QUEUE; MessageQueueId_t defaultDest = MessageQueueIF::NO_QUEUE; MqArgs args = {}; }; - - #endif /* FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_ */ diff --git a/src/fsfw/ipc/MessageQueueIF.h b/src/fsfw/ipc/MessageQueueIF.h index d7b6889b..fcd7c329 100644 --- a/src/fsfw/ipc/MessageQueueIF.h +++ b/src/fsfw/ipc/MessageQueueIF.h @@ -2,9 +2,10 @@ #define FSFW_IPC_MESSAGEQUEUEIF_H_ #include + #include -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "MessageQueueMessageIF.h" #include "messageQueueDefinitions.h" @@ -29,7 +30,7 @@ class MessageQueueIF { //! [EXPORT] : [COMMENT] Returned if the target destination is invalid. static constexpr ReturnValue_t DESTINATION_INVALID = MAKE_RETURN_CODE(4); - virtual ~MessageQueueIF() {} + virtual ~MessageQueueIF() = default; /** * @brief This operation sends a message to the last communication partner. * @details @@ -39,13 +40,14 @@ class MessageQueueIF { * @param message * A pointer to a previously created message, which is sent. * @return - * -@c RETURN_OK if ok + * -@c returnvalue::OK if ok * -@c NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found. */ virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0; /** - * @brief This function reads available messages from the message queue and returns the sender. + * @brief This function reads available messages from the message queue and returns the + * sender. * @details * It works identically to the other receiveMessage call, but in addition * returns the sender's queue id. @@ -67,24 +69,24 @@ class MessageQueueIF { * function returns immediately. * @param message * A pointer to a message in which the received data is stored. - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c MessageQueueIF::EMPTY if queue is empty */ virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0; /** * Deletes all pending messages in the queue. * @param count The number of flushed messages. - * @return RETURN_OK on success. + * @return returnvalue::OK on success. */ virtual ReturnValue_t flush(uint32_t* count) = 0; /** * @brief This method returns the message queue ID of the last communication partner. */ - virtual MessageQueueId_t getLastPartner() const = 0; + [[nodiscard]] virtual MessageQueueId_t getLastPartner() const = 0; /** * @brief This method returns the message queue ID of this class's message queue. */ - virtual MessageQueueId_t getId() const = 0; + [[nodiscard]] virtual MessageQueueId_t getId() const = 0; /** * @brief With the sendMessage call, a queue message is sent to a receiving queue. @@ -102,7 +104,7 @@ class MessageQueueIF { * @param ignoreFault * If set to true, the internal software fault counter is not incremented * if queue is full (if implemented). - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c MessageQueueIF::FULL if queue is full */ virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, @@ -134,7 +136,7 @@ class MessageQueueIF { * @param sentFrom * The sentFrom information can be set to inject the sender's queue id * into the message. This variable is set to zero by default. - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c MessageQueueIF::FULL if queue is full */ virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom, @@ -146,7 +148,7 @@ class MessageQueueIF { * call of the Implementation class and adds its queue id as * "sentFrom" information. * @param message A pointer to a previously created message, which is sent. - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c MessageQueueIF::FULL if queue is full */ virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message) = 0; @@ -157,9 +159,9 @@ class MessageQueueIF { /** * @brief This method is a simple getter for the default destination. */ - virtual MessageQueueId_t getDefaultDestination() const = 0; + [[nodiscard]] virtual MessageQueueId_t getDefaultDestination() const = 0; - virtual bool isDefaultDestinationSet() const = 0; + [[nodiscard]] virtual bool isDefaultDestinationSet() const = 0; virtual MqArgs& getMqArgs() = 0; }; diff --git a/src/fsfw/ipc/MessageQueueMessage.cpp b/src/fsfw/ipc/MessageQueueMessage.cpp index 6899915a..b0ce090f 100644 --- a/src/fsfw/ipc/MessageQueueMessage.cpp +++ b/src/fsfw/ipc/MessageQueueMessage.cpp @@ -10,10 +10,10 @@ MessageQueueMessage::MessageQueueMessage() : messageSize(getMinimumMessageSize() } MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size) - : messageSize(this->HEADER_SIZE + size) { - if (size <= this->MAX_DATA_SIZE) { - memcpy(this->getData(), data, size); - this->messageSize = this->HEADER_SIZE + size; + : messageSize(MessageQueueMessage::HEADER_SIZE + size) { + if (size <= MessageQueueMessage::MAX_DATA_SIZE) { + std::memcpy(MessageQueueMessage::getData(), data, size); + this->messageSize = MessageQueueMessage::HEADER_SIZE + size; } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "MessageQueueMessage: Passed size larger than maximum" @@ -21,21 +21,23 @@ MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size) << std::endl; #endif memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); - this->messageSize = this->HEADER_SIZE; + this->messageSize = MessageQueueMessage::HEADER_SIZE; } } -MessageQueueMessage::~MessageQueueMessage() {} +MessageQueueMessage::~MessageQueueMessage() = default; const uint8_t* MessageQueueMessage::getBuffer() const { return this->internalBuffer; } uint8_t* MessageQueueMessage::getBuffer() { return this->internalBuffer; } const uint8_t* MessageQueueMessage::getData() const { - return this->internalBuffer + this->HEADER_SIZE; + return this->internalBuffer + MessageQueueMessage::HEADER_SIZE; } -uint8_t* MessageQueueMessage::getData() { return this->internalBuffer + this->HEADER_SIZE; } +uint8_t* MessageQueueMessage::getData() { + return this->internalBuffer + MessageQueueMessage::HEADER_SIZE; +} MessageQueueId_t MessageQueueMessage::getSender() const { MessageQueueId_t temp_id; @@ -58,14 +60,22 @@ void MessageQueueMessage::print(bool printWholeMessage) { } } -void MessageQueueMessage::clear() { memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE); } +void MessageQueueMessage::clear() { + memset(this->getBuffer(), 0, MessageQueueMessage::MAX_MESSAGE_SIZE); +} size_t MessageQueueMessage::getMessageSize() const { return this->messageSize; } -void MessageQueueMessage::setMessageSize(size_t messageSize) { this->messageSize = messageSize; } +void MessageQueueMessage::setMessageSize(size_t messageSize_) { this->messageSize = messageSize_; } -size_t MessageQueueMessage::getMinimumMessageSize() const { return this->MIN_MESSAGE_SIZE; } +size_t MessageQueueMessage::getMinimumMessageSize() const { + return MessageQueueMessage::MIN_MESSAGE_SIZE; +} -size_t MessageQueueMessage::getMaximumMessageSize() const { return this->MAX_MESSAGE_SIZE; } +size_t MessageQueueMessage::getMaximumMessageSize() const { + return MessageQueueMessage::MAX_MESSAGE_SIZE; +} -size_t MessageQueueMessage::getMaximumDataSize() const { return this->MAX_DATA_SIZE; } +size_t MessageQueueMessage::getMaximumDataSize() const { + return MessageQueueMessage::MAX_DATA_SIZE; +} diff --git a/src/fsfw/ipc/MessageQueueMessage.h b/src/fsfw/ipc/MessageQueueMessage.h index 30e50ffe..a3d596f1 100644 --- a/src/fsfw/ipc/MessageQueueMessage.h +++ b/src/fsfw/ipc/MessageQueueMessage.h @@ -25,6 +25,30 @@ */ class MessageQueueMessage : public MessageQueueMessageIF { public: + /** + * @brief This constant defines the maximum size of the data content, + * excluding the header. + * @details + * It may be changed if necessary, but in general should be kept + * as small as possible. + */ + static const size_t MAX_DATA_SIZE = 24; + /** + * @brief This constant defines the maximum total size in bytes + * of a sent message. + * @details + * It is the sum of the maximum data and the header size. Be aware that + * this constant is used to define the buffer sizes for every message + * queue in the system. So, a change here may have significant impact on + * the required resources. + */ + static constexpr size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE; + /** + * @brief Defines the minimum size of a message where only the + * header is included + */ + static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE; + /** * @brief The class is initialized empty with this constructor. * @details @@ -50,59 +74,12 @@ class MessageQueueMessage : public MessageQueueMessageIF { * @brief As no memory is allocated in this class, * the destructor is empty. */ - virtual ~MessageQueueMessage(); + ~MessageQueueMessage() override; - /** - * @brief The size information of each message is stored in - * this attribute. - * @details - * It is public to simplify usage and to allow for passing the size - * address as a pointer. Care must be taken when inheriting from this class, - * as every child class is responsible for managing the size information by - * itself. When using the class to receive a message, the size information - * is updated automatically. - * - * Please note that the minimum size is limited by the size of the header - * while the maximum size is limited by the maximum allowed message size. - */ - size_t messageSize; - /** - * @brief This constant defines the maximum size of the data content, - * excluding the header. - * @details - * It may be changed if necessary, but in general should be kept - * as small as possible. - */ - static const size_t MAX_DATA_SIZE = 24; - - /** - * @brief This constant defines the maximum total size in bytes - * of a sent message. - * @details - * It is the sum of the maximum data and the header size. Be aware that - * this constant is used to define the buffer sizes for every message - * queue in the system. So, a change here may have significant impact on - * the required resources. - */ - static constexpr size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE; - /** - * @brief Defines the minimum size of a message where only the - * header is included - */ - static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE; - - private: - /** - * @brief This is the internal buffer that contains the - * actual message data. - */ - uint8_t internalBuffer[MAX_MESSAGE_SIZE]; - - public: /** * @brief This method is used to get the complete data of the message. */ - const uint8_t* getBuffer() const override; + [[nodiscard]] const uint8_t* getBuffer() const override; /** * @brief This method is used to get the complete data of the message. */ @@ -112,7 +89,7 @@ class MessageQueueMessage : public MessageQueueMessageIF { * @details * It shall be used by child classes to add data at the right position. */ - const uint8_t* getData() const override; + [[nodiscard]] const uint8_t* getData() const override; /** * @brief This method is used to fetch the data content of the message. * @details @@ -123,7 +100,7 @@ class MessageQueueMessage : public MessageQueueMessageIF { * @brief This method is used to extract the sender's message * queue id information from a received message. */ - MessageQueueId_t getSender() const override; + [[nodiscard]] MessageQueueId_t getSender() const override; /** * @brief With this method, the whole content * and the message size is set to zero. @@ -138,16 +115,40 @@ class MessageQueueMessage : public MessageQueueMessageIF { */ void setSender(MessageQueueId_t setId) override; - virtual size_t getMessageSize() const override; - virtual void setMessageSize(size_t messageSize) override; - virtual size_t getMinimumMessageSize() const override; - virtual size_t getMaximumMessageSize() const override; - virtual size_t getMaximumDataSize() const override; + [[nodiscard]] size_t getMessageSize() const override; + void setMessageSize(size_t messageSize) override; + [[nodiscard]] size_t getMinimumMessageSize() const override; + [[nodiscard]] size_t getMaximumMessageSize() const override; + [[nodiscard]] size_t getMaximumDataSize() const override; /** * @brief This is a debug method that prints the content. */ void print(bool printWholeMessage); + + /** + * TODO: This really should not be public. If it should be possible to pass size address as a + * pointer, add a getter function returning a const reference to the size + * @brief The size information of each message is stored in + * this attribute. + * @details + * It is public to simplify usage and to allow for passing the size + * address as a pointer. Care must be taken when inheriting from this class, + * as every child class is responsible for managing the size information by + * itself. When using the class to receive a message, the size information + * is updated automatically. + * + * Please note that the minimum size is limited by the size of the header + * while the maximum size is limited by the maximum allowed message size. + */ + size_t messageSize; + + private: + /** + * @brief This is the internal buffer that contains the + * actual message data. + */ + uint8_t internalBuffer[MAX_MESSAGE_SIZE] = {}; }; #endif /* FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ */ diff --git a/src/fsfw/ipc/MessageQueueMessageIF.h b/src/fsfw/ipc/MessageQueueMessageIF.h index dae28926..300a90ab 100644 --- a/src/fsfw/ipc/MessageQueueMessageIF.h +++ b/src/fsfw/ipc/MessageQueueMessageIF.h @@ -14,7 +14,7 @@ class MessageQueueMessageIF { */ static const size_t HEADER_SIZE = sizeof(MessageQueueId_t); - virtual ~MessageQueueMessageIF(){}; + virtual ~MessageQueueMessageIF() = default; /** * @brief With this method, the whole content and the message @@ -29,7 +29,7 @@ class MessageQueueMessageIF { * @brief Get read-only pointer to the complete data of the message. * @return */ - virtual const uint8_t* getBuffer() const = 0; + [[nodiscard]] virtual const uint8_t* getBuffer() const = 0; /** * @brief This method is used to get the complete data of the message. @@ -48,14 +48,14 @@ class MessageQueueMessageIF { * @brief This method is used to extract the sender's message queue id * information from a received message. */ - virtual MessageQueueId_t getSender() const = 0; + [[nodiscard]] virtual MessageQueueId_t getSender() const = 0; /** * @brief This method is used to fetch the data content of the message. * @details * It shall be used by child classes to add data at the right position. */ - virtual const uint8_t* getData() const = 0; + [[nodiscard]] virtual const uint8_t* getData() const = 0; /** * @brief This method is used to fetch the data content of the message. * @details @@ -67,12 +67,28 @@ class MessageQueueMessageIF { * Get constant message size of current message implementation. * @return */ - virtual size_t getMessageSize() const = 0; + [[nodiscard]] virtual size_t getMessageSize() const = 0; + /** + * Sets the current message size of a given message + * @param messageSize + */ virtual void setMessageSize(size_t messageSize) = 0; - virtual size_t getMinimumMessageSize() const = 0; - virtual size_t getMaximumMessageSize() const = 0; - virtual size_t getMaximumDataSize() const = 0; + /** + * Returns the smallest possible message size, including any headers + * @return + */ + [[nodiscard]] virtual size_t getMinimumMessageSize() const = 0; + /** + * Returns the largest possible message size, including any headers + * @return + */ + [[nodiscard]] virtual size_t getMaximumMessageSize() const = 0; + /** + * Returns the largest possible data size without any headers + * @return + */ + [[nodiscard]] virtual size_t getMaximumDataSize() const = 0; }; #endif /* FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ */ diff --git a/src/fsfw/ipc/MessageQueueSenderIF.h b/src/fsfw/ipc/MessageQueueSenderIF.h index a98862f6..83c7223a 100644 --- a/src/fsfw/ipc/MessageQueueSenderIF.h +++ b/src/fsfw/ipc/MessageQueueSenderIF.h @@ -1,14 +1,14 @@ #ifndef FSFW_IPC_MESSAGEQUEUESENDERIF_H_ #define FSFW_IPC_MESSAGEQUEUESENDERIF_H_ -#include "../objectmanager/ObjectManagerIF.h" #include "MessageQueueIF.h" #include "MessageQueueMessageIF.h" +#include "fsfw/objectmanager/ObjectManagerIF.h" class MessageQueueSenderIF { public: - virtual ~MessageQueueSenderIF() {} - + virtual ~MessageQueueSenderIF() = default; + MessageQueueSenderIF() = delete; /** * Allows sending messages without actually "owning" a message queue. * Not sure whether this is actually a good idea. @@ -16,9 +16,6 @@ class MessageQueueSenderIF { static ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message, MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE, bool ignoreFault = false); - - private: - MessageQueueSenderIF() {} }; #endif /* FSFW_IPC_MESSAGEQUEUESENDERIF_H_ */ diff --git a/src/fsfw/ipc/MutexGuard.h b/src/fsfw/ipc/MutexGuard.h index f7b90663..f6d2f25f 100644 --- a/src/fsfw/ipc/MutexGuard.h +++ b/src/fsfw/ipc/MutexGuard.h @@ -30,7 +30,7 @@ class MutexGuard { timeoutMs); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ - } else if (result != HasReturnvaluesIF::RETURN_OK) { + } else if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "MutexGuard: Lock of Mutex failed with code " << result << std::endl; #else @@ -51,7 +51,7 @@ class MutexGuard { private: MutexIF* internalMutex; - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t result = returnvalue::FAILED; }; #endif /* FRAMEWORK_IPC_MUTEXGUARD_H_ */ diff --git a/src/fsfw/ipc/MutexIF.h b/src/fsfw/ipc/MutexIF.h index 0bdfa1f4..30992f7b 100644 --- a/src/fsfw/ipc/MutexIF.h +++ b/src/fsfw/ipc/MutexIF.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_IPC_MUTEXIF_H_ #define FRAMEWORK_IPC_MUTEXIF_H_ -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" /** * @brief Common interface for OS Mutex objects which provide MUTual EXclusion. diff --git a/src/fsfw/memory/CMakeLists.txt b/src/fsfw/memory/CMakeLists.txt index c713cd42..9d9c90c4 100644 --- a/src/fsfw/memory/CMakeLists.txt +++ b/src/fsfw/memory/CMakeLists.txt @@ -1,5 +1 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - MemoryHelper.cpp - MemoryMessage.cpp - GenericFileSystemMessage.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE MemoryHelper.cpp MemoryMessage.cpp) diff --git a/src/fsfw/memory/HasFileSystemIF.h b/src/fsfw/memory/HasFileSystemIF.h deleted file mode 100644 index 88a7db83..00000000 --- a/src/fsfw/memory/HasFileSystemIF.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef FSFW_MEMORY_HASFILESYSTEMIF_H_ -#define FSFW_MEMORY_HASFILESYSTEMIF_H_ - -#include - -#include "FileSystemArgsIF.h" -#include "fsfw/ipc/messageQueueDefinitions.h" -#include "fsfw/returnvalues/FwClassIds.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" - -/** - * @brief Generic interface for objects which expose a file system to enable - * message based file handling. - * @author J. Meier, R. Mueller - */ -class HasFileSystemIF { - public: - static constexpr uint8_t INTERFACE_ID = CLASS_ID::FILE_SYSTEM; - - //! [EXPORT] : P1: Can be file system specific error code - static constexpr ReturnValue_t GENERIC_FILE_ERROR = MAKE_RETURN_CODE(0); - //! [EXPORT] : File system is currently busy - static constexpr ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1); - //! [EXPORT] : Invalid parameters like file name or repository path - static constexpr ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2); - - static constexpr ReturnValue_t FILE_DOES_NOT_EXIST = MAKE_RETURN_CODE(5); - static constexpr ReturnValue_t FILE_ALREADY_EXISTS = MAKE_RETURN_CODE(6); - static constexpr ReturnValue_t FILE_LOCKED = MAKE_RETURN_CODE(7); - - static constexpr ReturnValue_t DIRECTORY_DOES_NOT_EXIST = MAKE_RETURN_CODE(10); - static constexpr ReturnValue_t DIRECTORY_ALREADY_EXISTS = MAKE_RETURN_CODE(11); - static constexpr ReturnValue_t DIRECTORY_NOT_EMPTY = MAKE_RETURN_CODE(12); - - //! [EXPORT] : P1: Sequence number missing - static constexpr ReturnValue_t SEQUENCE_PACKET_MISSING_WRITE = MAKE_RETURN_CODE(15); - //! [EXPORT] : P1: Sequence number missing - static constexpr ReturnValue_t SEQUENCE_PACKET_MISSING_READ = MAKE_RETURN_CODE(16); - - virtual ~HasFileSystemIF() {} - - /** - * Function to get the MessageQueueId_t of the implementing object - * @return MessageQueueId_t of the object - */ - virtual MessageQueueId_t getCommandQueue() const = 0; - - /** - * @brief Generic function to append to file. - * @param dirname Directory of the file - * @param filename The filename of the file - * @param data The data to write to the file - * @param size The size of the data to write - * @param packetNumber Current packet number. Can be used to verify that - * there are no missing packets. - * @param args Any other arguments which an implementation might require. - * @param bytesWritten Actual bytes written to file - * For large files the write procedure must be split in multiple calls - * to writeToFile - */ - virtual ReturnValue_t appendToFile(const char* repositoryPath, const char* filename, - const uint8_t* data, size_t size, uint16_t packetNumber, - FileSystemArgsIF* args = nullptr) = 0; - - /** - * @brief Generic function to create a new file. - * @param repositoryPath - * @param filename - * @param data - * @param size - * @param args Any other arguments which an implementation might require - * @return - */ - virtual ReturnValue_t createFile(const char* repositoryPath, const char* filename, - const uint8_t* data = nullptr, size_t size = 0, - FileSystemArgsIF* args = nullptr) = 0; - - /** - * @brief Generic function to delete a file. - * @param repositoryPath - * @param filename - * @param args Any other arguments which an implementation might require - * @return - */ - virtual ReturnValue_t removeFile(const char* repositoryPath, const char* filename, - FileSystemArgsIF* args = nullptr) = 0; - - /** - * @brief Generic function to create a directory - * @param repositoryPath - * @param Equivalent to the -p flag in Unix systems. If some required parent directories - * do not exist, create them as well - * @param args Any other arguments which an implementation might require - * @return - */ - virtual ReturnValue_t createDirectory(const char* repositoryPath, const char* dirname, - bool createParentDirs, - FileSystemArgsIF* args = nullptr) = 0; - - /** - * @brief Generic function to remove a directory - * @param repositoryPath - * @param args Any other arguments which an implementation might require - */ - virtual ReturnValue_t removeDirectory(const char* repositoryPath, const char* dirname, - bool deleteRecurively = false, - FileSystemArgsIF* args = nullptr) = 0; - - virtual ReturnValue_t renameFile(const char* repositoryPath, const char* oldFilename, - const char* newFilename, FileSystemArgsIF* args = nullptr) = 0; -}; - -#endif /* FSFW_MEMORY_HASFILESYSTEMIF_H_ */ diff --git a/src/fsfw/memory/HasMemoryIF.h b/src/fsfw/memory/HasMemoryIF.h index 7aa66377..fe5c1fc8 100644 --- a/src/fsfw/memory/HasMemoryIF.h +++ b/src/fsfw/memory/HasMemoryIF.h @@ -1,7 +1,7 @@ #ifndef HASMEMORYIF_H_ #define HASMEMORYIF_H_ -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" class HasMemoryIF { public: @@ -30,15 +30,13 @@ class HasMemoryIF { * Sets the address of the memory, if possible. * startAddress is a proposal for an address, or the base address if multiple addresses are set. */ - virtual ReturnValue_t setAddress(uint32_t* startAddress) { - return HasReturnvaluesIF::RETURN_FAILED; - } + virtual ReturnValue_t setAddress(uint32_t* startAddress) { return returnvalue::FAILED; } static bool memAccessWasSuccessful(ReturnValue_t result) { switch (result) { case DO_IT_MYSELF: case POINTS_TO_MEMORY: case POINTS_TO_VARIABLE: - case HasReturnvaluesIF::RETURN_OK: + case returnvalue::OK: case ACTIVITY_COMPLETED: return true; default: diff --git a/src/fsfw/memory/MemoryHelper.cpp b/src/fsfw/memory/MemoryHelper.cpp index 462a818e..cf4d205d 100644 --- a/src/fsfw/memory/MemoryHelper.cpp +++ b/src/fsfw/memory/MemoryHelper.cpp @@ -24,13 +24,13 @@ ReturnValue_t MemoryHelper::handleMemoryCommand(CommandMessage* message) { switch (lastCommand) { case MemoryMessage::CMD_MEMORY_DUMP: handleMemoryCheckOrDump(message); - return RETURN_OK; + return returnvalue::OK; case MemoryMessage::CMD_MEMORY_LOAD: handleMemoryLoad(message); - return RETURN_OK; + return returnvalue::OK; case MemoryMessage::CMD_MEMORY_CHECK: handleMemoryCheckOrDump(message); - return RETURN_OK; + return returnvalue::OK; default: lastCommand = CommandMessage::CMD_NONE; return UNKNOWN_CMD; @@ -51,7 +51,7 @@ void MemoryHelper::completeLoad(ReturnValue_t errorCode, const uint8_t* dataToCo EndianConverter::convertBigEndian(copyHere, dataToCopy, size); break; case HasMemoryIF::ACTIVITY_COMPLETED: - case RETURN_OK: + case returnvalue::OK: break; default: ipcStore->deleteData(ipcAddress); @@ -75,7 +75,7 @@ void MemoryHelper::completeDump(ReturnValue_t errorCode, const uint8_t* dataToCo case HasMemoryIF::DO_IT_MYSELF: busy = true; return; - case HasReturnvaluesIF::RETURN_OK: + case returnvalue::OK: case HasMemoryIF::POINTS_TO_MEMORY: case HasMemoryIF::POINTS_TO_VARIABLE: //"data" must be valid pointer! @@ -118,7 +118,7 @@ void MemoryHelper::completeDump(ReturnValue_t errorCode, const uint8_t* dataToCo ipcStore->deleteData(ipcAddress); break; } - if (queueToUse->sendMessage(lastSender, &reply) != RETURN_OK) { + if (queueToUse->sendMessage(lastSender, &reply) != returnvalue::OK) { reply.clear(); } } @@ -148,7 +148,7 @@ void MemoryHelper::handleMemoryLoad(CommandMessage* message) { uint8_t* dataPointer = NULL; size_t size = 0; ReturnValue_t returnCode = ipcStore->getData(ipcAddress, &p_data, &size); - if (returnCode == RETURN_OK) { + if (returnCode == returnvalue::OK) { returnCode = workOnThis->handleMemoryLoad(address, p_data, size, &dataPointer); completeLoad(returnCode, p_data, size, dataPointer); } else { @@ -164,7 +164,7 @@ void MemoryHelper::handleMemoryCheckOrDump(CommandMessage* message) { uint32_t size = MemoryMessage::getLength(message); uint8_t* dataPointer = NULL; ReturnValue_t returnCode = ipcStore->getFreeElement(&ipcAddress, size, &reservedSpaceInIPC); - if (returnCode == RETURN_OK) { + if (returnCode == returnvalue::OK) { returnCode = workOnThis->handleMemoryDump(address, size, &dataPointer, reservedSpaceInIPC); completeDump(returnCode, dataPointer, size); } else { @@ -176,7 +176,7 @@ void MemoryHelper::handleMemoryCheckOrDump(CommandMessage* message) { ReturnValue_t MemoryHelper::initialize(MessageQueueIF* queueToUse_) { if (queueToUse_ == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } this->queueToUse = queueToUse_; return initialize(); @@ -185,8 +185,8 @@ ReturnValue_t MemoryHelper::initialize(MessageQueueIF* queueToUse_) { ReturnValue_t MemoryHelper::initialize() { ipcStore = ObjectManager::instance()->get(objects::IPC_STORE); if (ipcStore != nullptr) { - return RETURN_OK; + return returnvalue::OK; } else { - return RETURN_FAILED; + return returnvalue::FAILED; } } diff --git a/src/fsfw/memory/MemoryHelper.h b/src/fsfw/memory/MemoryHelper.h index 7a645b79..095b366f 100644 --- a/src/fsfw/memory/MemoryHelper.h +++ b/src/fsfw/memory/MemoryHelper.h @@ -3,14 +3,14 @@ #include "../ipc/CommandMessage.h" #include "../ipc/MessageQueueIF.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "../storagemanager/StorageManagerIF.h" #include "AcceptsMemoryMessagesIF.h" /** * @brief TODO: documentation. */ -class MemoryHelper : public HasReturnvaluesIF { +class MemoryHelper { public: static const uint8_t INTERFACE_ID = CLASS_ID::MEMORY_HELPER; static const ReturnValue_t UNKNOWN_CMD = MAKE_RETURN_CODE(0xE0); diff --git a/src/fsfw/modes/CMakeLists.txt b/src/fsfw/modes/CMakeLists.txt index 8e5c719b..4eef58e0 100644 --- a/src/fsfw/modes/CMakeLists.txt +++ b/src/fsfw/modes/CMakeLists.txt @@ -1,5 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - ModeHelper.cpp - ModeMessage.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE ModeHelper.cpp ModeMessage.cpp) diff --git a/src/fsfw/modes/HasModesIF.h b/src/fsfw/modes/HasModesIF.h index 0ebe77d8..599975f8 100644 --- a/src/fsfw/modes/HasModesIF.h +++ b/src/fsfw/modes/HasModesIF.h @@ -4,7 +4,7 @@ #include #include "../events/Event.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "ModeHelper.h" #include "ModeMessage.h" @@ -53,7 +53,7 @@ class HasModesIF { protected: virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } virtual void startTransition(Mode_t mode, Submode_t submode) {} diff --git a/src/fsfw/modes/ModeHelper.cpp b/src/fsfw/modes/ModeHelper.cpp index 2ea392ab..8c83012f 100644 --- a/src/fsfw/modes/ModeHelper.cpp +++ b/src/fsfw/modes/ModeHelper.cpp @@ -25,7 +25,7 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* command) { submode = ModeMessage::getSubmode(command); uint32_t timeout; ReturnValue_t result = owner->checkModeCommand(mode, submode, &timeout); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { ModeMessage::setCantReachMode(&reply, result); MessageQueueSenderIF::sendMessage(command->getSender(), &reply, owner->getCommandQueue()); break; @@ -55,9 +55,9 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* command) { owner->announceMode(true); break; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t ModeHelper::initialize(MessageQueueId_t parentQueueId) { @@ -99,7 +99,7 @@ void ModeHelper::setParentQueue(MessageQueueId_t parentQueueId) { this->parentQueueId = parentQueueId; } -ReturnValue_t ModeHelper::initialize(void) { return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t ModeHelper::initialize(void) { return returnvalue::OK; } bool ModeHelper::isTimedOut() { return countdown.hasTimedOut(); } diff --git a/src/fsfw/modes/ModeHelper.h b/src/fsfw/modes/ModeHelper.h index 4d0479db..a84408a2 100644 --- a/src/fsfw/modes/ModeHelper.h +++ b/src/fsfw/modes/ModeHelper.h @@ -3,7 +3,7 @@ #include "ModeMessage.h" #include "fsfw/ipc/MessageQueueIF.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/timemanager/Countdown.h" class HasModesIF; diff --git a/src/fsfw/modes/ModeMessage.cpp b/src/fsfw/modes/ModeMessage.cpp index ecc52c94..fbfb71aa 100644 --- a/src/fsfw/modes/ModeMessage.cpp +++ b/src/fsfw/modes/ModeMessage.cpp @@ -24,3 +24,19 @@ void ModeMessage::setCantReachMode(CommandMessage* message, ReturnValue_t reason message->setParameter(reason); message->setParameter2(0); } + +void ModeMessage::setModeAnnounceMessage(CommandMessage& message, bool recursive) { + Command_t cmd; + if (recursive) { + cmd = CMD_MODE_ANNOUNCE_RECURSIVELY; + } else { + cmd = CMD_MODE_ANNOUNCE; + } + message.setCommand(cmd); +} + +void ModeMessage::setCmdModeMessage(CommandMessage& message, Mode_t mode, Submode_t submode) { + setModeMessage(&message, CMD_MODE_COMMAND, mode, submode); +} + +void ModeMessage::setModeReadMessage(CommandMessage& message) { message.setCommand(CMD_MODE_READ); } diff --git a/src/fsfw/modes/ModeMessage.h b/src/fsfw/modes/ModeMessage.h index 84429e84..c00e6c9e 100644 --- a/src/fsfw/modes/ModeMessage.h +++ b/src/fsfw/modes/ModeMessage.h @@ -45,6 +45,9 @@ class ModeMessage { static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode, Submode_t submode); + static void setCmdModeMessage(CommandMessage& message, Mode_t mode, Submode_t submode); + static void setModeAnnounceMessage(CommandMessage& message, bool recursive); + static void setModeReadMessage(CommandMessage& message); static void setCantReachMode(CommandMessage* message, ReturnValue_t reason); static void clear(CommandMessage* message); }; diff --git a/src/fsfw/monitoring/AbsLimitMonitor.h b/src/fsfw/monitoring/AbsLimitMonitor.h index c6400166..159a3d2a 100644 --- a/src/fsfw/monitoring/AbsLimitMonitor.h +++ b/src/fsfw/monitoring/AbsLimitMonitor.h @@ -29,12 +29,12 @@ class AbsLimitMonitor : public MonitorBase { return MonitoringIF::OUT_OF_RANGE; } } - return HasReturnvaluesIF::RETURN_OK; // We're not out of range. + return returnvalue::OK; // We're not out of range. } - virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, - ParameterWrapper *parameterWrapper, - const ParameterWrapper *newValues, uint16_t startAtIndex) { + ReturnValue_t getParameter(uint8_t domainId, uint8_t parameterId, + ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues, + uint16_t startAtIndex) override { ReturnValue_t result = this->MonitorBase::getParameter( domainId, parameterId, parameterWrapper, newValues, startAtIndex); // We'll reuse the DOMAIN_ID of MonitorReporter, @@ -49,7 +49,7 @@ class AbsLimitMonitor : public MonitorBase { default: return this->INVALID_IDENTIFIER_ID; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } bool isOutOfLimits() { if (this->oldState == MonitoringIF::OUT_OF_RANGE) { diff --git a/src/fsfw/monitoring/CMakeLists.txt b/src/fsfw/monitoring/CMakeLists.txt index d26e807c..48f945b5 100644 --- a/src/fsfw/monitoring/CMakeLists.txt +++ b/src/fsfw/monitoring/CMakeLists.txt @@ -1,5 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - LimitViolationReporter.cpp - MonitoringMessage.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE LimitViolationReporter.cpp + MonitoringMessage.cpp) diff --git a/src/fsfw/monitoring/LimitMonitor.h b/src/fsfw/monitoring/LimitMonitor.h index 229f1dc2..4fe9ee39 100644 --- a/src/fsfw/monitoring/LimitMonitor.h +++ b/src/fsfw/monitoring/LimitMonitor.h @@ -32,7 +32,7 @@ class LimitMonitor : public MonitorBase { *crossedLimit = lowerLimit; return MonitoringIF::BELOW_LOW_LIMIT; } else { - return HasReturnvaluesIF::RETURN_OK; // Within limits. + return returnvalue::OK; // Within limits. } } @@ -55,7 +55,7 @@ class LimitMonitor : public MonitorBase { default: return this->INVALID_IDENTIFIER_ID; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } bool isOutOfLimits() { if (this->oldState == MonitoringIF::ABOVE_HIGH_LIMIT or diff --git a/src/fsfw/monitoring/LimitViolationReporter.cpp b/src/fsfw/monitoring/LimitViolationReporter.cpp index 43ecf4d3..ec6fa2e6 100644 --- a/src/fsfw/monitoring/LimitViolationReporter.cpp +++ b/src/fsfw/monitoring/LimitViolationReporter.cpp @@ -7,7 +7,7 @@ ReturnValue_t LimitViolationReporter::sendLimitViolationReport(const SerializeIF* data) { ReturnValue_t result = checkClassLoaded(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } store_address_t storeId; @@ -17,12 +17,12 @@ ReturnValue_t LimitViolationReporter::sendLimitViolationReport(const SerializeIF return MonitoringIF::INVALID_SIZE; } result = ipcStore->getFreeElement(&storeId, maxSize, &dataTarget); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } size_t size = 0; result = data->serialize(&dataTarget, &size, maxSize, SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } CommandMessage report; @@ -42,10 +42,10 @@ ReturnValue_t LimitViolationReporter::checkClassLoaded() { if (ipcStore == nullptr) { ipcStore = ObjectManager::instance()->get(objects::IPC_STORE); if (ipcStore == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } // Lazy initialization. diff --git a/src/fsfw/monitoring/LimitViolationReporter.h b/src/fsfw/monitoring/LimitViolationReporter.h index 06b3ba74..12747725 100644 --- a/src/fsfw/monitoring/LimitViolationReporter.h +++ b/src/fsfw/monitoring/LimitViolationReporter.h @@ -8,7 +8,7 @@ #define LIMITVIOLATIONREPORTER_H_ #include "../ipc/MessageQueueSenderIF.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "../serialize/SerializeIF.h" #include "../storagemanager/StorageManagerIF.h" #include "monitoringConf.h" diff --git a/src/fsfw/monitoring/MonitorBase.h b/src/fsfw/monitoring/MonitorBase.h index b2653d75..dd0792b2 100644 --- a/src/fsfw/monitoring/MonitorBase.h +++ b/src/fsfw/monitoring/MonitorBase.h @@ -36,7 +36,7 @@ class MonitorBase : public MonitorReporter { // 2. If returning from fetch != OK, parameter is invalid. // Report (if oldState is != invalidity). - if (validity != HasReturnvaluesIF::RETURN_OK) { + if (validity != returnvalue::OK) { this->monitorStateIs(validity, sample, 0); } else { // 3. Otherwise, check sample. @@ -56,14 +56,14 @@ class MonitorBase : public MonitorReporter { protected: virtual ReturnValue_t fetchSample(T* sample) { ReturnValue_t result = poolVariable.read(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (not poolVariable.isValid()) { return MonitoringIF::INVALID; } *sample = poolVariable.value; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } LocalPoolVariable poolVariable; diff --git a/src/fsfw/monitoring/MonitorReporter.h b/src/fsfw/monitoring/MonitorReporter.h index bcbaf26d..09c39222 100644 --- a/src/fsfw/monitoring/MonitorReporter.h +++ b/src/fsfw/monitoring/MonitorReporter.h @@ -70,7 +70,7 @@ class MonitorReporter : public HasParametersIF { default: return INVALID_IDENTIFIER_ID; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } virtual ReturnValue_t setToUnchecked() { return setToState(MonitoringIF::UNCHECKED); } virtual ReturnValue_t setToInvalid() { return setToState(MonitoringIF::INVALID); } @@ -135,7 +135,7 @@ class MonitorReporter : public HasParametersIF { case MonitoringIF::UNCHECKED: case MonitoringIF::UNSELECTED: case MonitoringIF::INVALID: - case HasReturnvaluesIF::RETURN_OK: + case returnvalue::OK: break; default: EventManagerIF::triggerEvent(reportingId, MonitoringIF::MONITOR_CHANGED_STATE, state); @@ -159,7 +159,7 @@ class MonitorReporter : public HasParametersIF { LimitViolationReporter::sendLimitViolationReport(&report); oldState = state; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } }; diff --git a/src/fsfw/monitoring/MonitoringMessage.h b/src/fsfw/monitoring/MonitoringMessage.h index 9695120b..4fa1c759 100644 --- a/src/fsfw/monitoring/MonitoringMessage.h +++ b/src/fsfw/monitoring/MonitoringMessage.h @@ -13,6 +13,7 @@ class MonitoringMessage : public CommandMessage { static const Command_t LIMIT_VIOLATION_REPORT = MAKE_COMMAND_ID(10); virtual ~MonitoringMessage(); static void setLimitViolationReport(CommandMessage* message, store_address_t storeId); + using CommandMessage::clear; static void clear(CommandMessage* message); static store_address_t getStoreId(const CommandMessage* message); static void setTypicalMessage(CommandMessage* message, Command_t type, store_address_t storeId); diff --git a/src/fsfw/monitoring/MonitoringMessageContent.h b/src/fsfw/monitoring/MonitoringMessageContent.h index 0ac455eb..7a7b5440 100644 --- a/src/fsfw/monitoring/MonitoringMessageContent.h +++ b/src/fsfw/monitoring/MonitoringMessageContent.h @@ -8,7 +8,7 @@ #include "../serialize/SerialLinkedListAdapter.h" #include "../serialize/SerializeElement.h" #include "../serviceinterface/ServiceInterface.h" -#include "../timemanager/TimeStamperIF.h" +#include "../timemanager/TimeWriterIF.h" #include "HasMonitorsIF.h" #include "MonitoringIF.h" #include "monitoringConf.h" @@ -34,9 +34,9 @@ class MonitoringReportContent : public SerialLinkedListAdapter { SerializeElement limitValue; SerializeElement oldState; SerializeElement newState; - uint8_t rawTimestamp[TimeStamperIF::MISSION_TIMESTAMP_SIZE]; + uint8_t rawTimestamp[TimeWriterIF::MAXIMUM_TIMESTAMP_LEN] = {}; SerializeElement> timestampSerializer; - TimeStamperIF* timeStamper; + TimeWriterIF* timeStamper; MonitoringReportContent() : SerialLinkedListAdapter(¶meterObjectId), monitorId(0), @@ -46,9 +46,8 @@ class MonitoringReportContent : public SerialLinkedListAdapter { limitValue(0), oldState(0), newState(0), - rawTimestamp({0}), timestampSerializer(rawTimestamp, sizeof(rawTimestamp)), - timeStamper(NULL) { + timeStamper(nullptr) { setAllNext(); } MonitoringReportContent(gp_id_t globalPoolId, T value, T limitValue, ReturnValue_t oldState, @@ -62,7 +61,7 @@ class MonitoringReportContent : public SerialLinkedListAdapter { oldState(oldState), newState(newState), timestampSerializer(rawTimestamp, sizeof(rawTimestamp)), - timeStamper(NULL) { + timeStamper(nullptr) { setAllNext(); if (checkAndSetStamper()) { timeStamper->addTimeStamp(rawTimestamp, sizeof(rawTimestamp)); @@ -80,7 +79,7 @@ class MonitoringReportContent : public SerialLinkedListAdapter { } bool checkAndSetStamper() { if (timeStamper == nullptr) { - timeStamper = ObjectManager::instance()->get(timeStamperId); + timeStamper = ObjectManager::instance()->get(timeStamperId); if (timeStamper == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "MonitoringReportContent::checkAndSetStamper: " diff --git a/src/fsfw/monitoring/TriplexMonitor.h b/src/fsfw/monitoring/TriplexMonitor.h index 1d9182aa..e007ea5f 100644 --- a/src/fsfw/monitoring/TriplexMonitor.h +++ b/src/fsfw/monitoring/TriplexMonitor.h @@ -49,7 +49,7 @@ class TriplexMonitor : public HasParametersIF { nAvailable++; } } - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t result = returnvalue::FAILED; switch (nAvailable) { case 3: result = doTriplexMonitoring(); @@ -67,9 +67,9 @@ class TriplexMonitor : public HasParametersIF { ReturnValue_t initialize() { healthTable = ObjectManager::instance()->get(objects::HEALTH_TABLE); if (healthTable == NULL) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper *parameterWrapper, @@ -84,7 +84,7 @@ class TriplexMonitor : public HasParametersIF { default: return INVALID_IDENTIFIER_ID; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } protected: @@ -96,7 +96,7 @@ class TriplexMonitor : public HasParametersIF { HealthTableIF *healthTable; uint8_t domainId; ReturnValue_t doTriplexMonitoring() { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; // Find middle value, by ordering indices uint8_t index[3] = {0, 1, 2}; if (values[index[0]].value > values[index[1]].value) { @@ -118,7 +118,7 @@ class TriplexMonitor : public HasParametersIF { if (values[index[2]] > (values[index[1]] + limit)) { EventManagerIF::triggerEvent(getRefereneceObject(index[2]), eventTripleCheck, HIGHEST_VALUE_OOL, 0); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { result = HIGHEST_VALUE_OOL; } else { result = BOTH_VALUES_OOL; @@ -142,7 +142,7 @@ class TriplexMonitor : public HasParametersIF { return DUPLEX_OOL; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } virtual bool checkObjectHealthState(uint8_t valueIndex) = 0; virtual object_id_t getRefereneceObject(uint8_t valueIndex) = 0; diff --git a/src/fsfw/monitoring/TwoValueLimitMonitor.h b/src/fsfw/monitoring/TwoValueLimitMonitor.h index 79b8c4bb..ad3f5c86 100644 --- a/src/fsfw/monitoring/TwoValueLimitMonitor.h +++ b/src/fsfw/monitoring/TwoValueLimitMonitor.h @@ -18,7 +18,7 @@ class TwoValueLimitMonitor : public LimitMonitor { ReturnValue_t doCheck(T lowSample, T highSample) { T crossedLimit; ReturnValue_t currentState = this->checkSample(lowSample, &crossedLimit); - if (currentState != HasReturnvaluesIF::RETURN_OK) { + if (currentState != returnvalue::OK) { return this->monitorStateIs(currentState, lowSample, crossedLimit); } currentState = this->checkSample(highSample, &crossedLimit); diff --git a/src/fsfw/objectmanager/CMakeLists.txt b/src/fsfw/objectmanager/CMakeLists.txt index 72aaec89..c71f43aa 100644 --- a/src/fsfw/objectmanager/CMakeLists.txt +++ b/src/fsfw/objectmanager/CMakeLists.txt @@ -1,5 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - ObjectManager.cpp - SystemObject.cpp -) \ No newline at end of file +target_sources(${LIB_FSFW_NAME} PRIVATE ObjectManager.cpp SystemObject.cpp) diff --git a/src/fsfw/objectmanager/ObjectManager.cpp b/src/fsfw/objectmanager/ObjectManager.cpp index 2017938a..29c1b2fc 100644 --- a/src/fsfw/objectmanager/ObjectManager.cpp +++ b/src/fsfw/objectmanager/ObjectManager.cpp @@ -21,11 +21,19 @@ void ObjectManager::setObjectFactoryFunction(produce_function_t objFactoryFunc, this->factoryArgs = factoryArgs; } -ObjectManager::ObjectManager() {} +ObjectManager::ObjectManager() = default; + +void ObjectManager::clear() { + if (objManagerInstance != nullptr) { + delete objManagerInstance; + objManagerInstance = nullptr; + } +} ObjectManager::~ObjectManager() { - for (auto const& iter : objectList) { - delete iter.second; + teardown = true; + for (auto iter = objectList.begin(); iter != objectList.end(); iter = objectList.erase(iter)) { + delete iter->second; } } @@ -36,7 +44,7 @@ ReturnValue_t ObjectManager::insert(object_id_t id, SystemObjectIF* object) { // sif::debug << "ObjectManager::insert: Object " << std::hex // << (int)id << std::dec << " inserted." << std::endl; #endif - return this->RETURN_OK; + return returnvalue::OK; } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "ObjectManager::insert: Object ID " << std::hex << static_cast(id) @@ -53,13 +61,19 @@ ReturnValue_t ObjectManager::insert(object_id_t id, SystemObjectIF* object) { } ReturnValue_t ObjectManager::remove(object_id_t id) { - if (this->getSystemObject(id) != NULL) { + // this function is called during destruction of System Objects + // disabeld for teardown to avoid iterator invalidation and + // double free + if (teardown) { + return returnvalue::OK; + } + if (this->getSystemObject(id) != nullptr) { this->objectList.erase(id); #if FSFW_CPP_OSTREAM_ENABLED == 1 // sif::debug << "ObjectManager::removeObject: Object " << std::hex // << (int)id << std::dec << " removed." << std::endl; #endif - return RETURN_OK; + return returnvalue::OK; } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "ObjectManager::removeObject: Requested object " << std::hex << (int)id @@ -90,11 +104,11 @@ void ObjectManager::initialize() { return; } objectFactoryFunction(factoryArgs); - ReturnValue_t result = RETURN_FAILED; + ReturnValue_t result = returnvalue::FAILED; uint32_t errorCount = 0; for (auto const& it : objectList) { result = it.second->initialize(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 object_id_t var = it.first; sif::error << "ObjectManager::initialize: Object 0x" << std::hex << std::setw(8) @@ -116,7 +130,7 @@ void ObjectManager::initialize() { errorCount = 0; for (auto const& it : objectList) { result = it.second->checkObjectConnections(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "ObjectManager::ObjectManager: Object 0x" << std::hex << (int)it.first << " connection check failed with code 0x" << result << std::dec << std::endl; diff --git a/src/fsfw/objectmanager/ObjectManager.h b/src/fsfw/objectmanager/ObjectManager.h index 50e4af00..355f5d0a 100644 --- a/src/fsfw/objectmanager/ObjectManager.h +++ b/src/fsfw/objectmanager/ObjectManager.h @@ -24,12 +24,17 @@ class ObjectManager : public ObjectManagerIF { using produce_function_t = void (*)(void* args); /** - * Returns the single instance of TaskFactory. + * Returns the single instance of ObjectManager. * The implementation of #instance is found in its subclasses. * Thus, we choose link-time variability of the instance. */ static ObjectManager* instance(); + /** + * Deletes the single instance of ObjectManager + */ + static void clear(); + void setObjectFactoryFunction(produce_function_t prodFunc, void* args); template @@ -38,7 +43,7 @@ class ObjectManager : public ObjectManagerIF { /** * @brief In the class's destructor, all objects in the list are deleted. */ - virtual ~ObjectManager(); + ~ObjectManager() override; ReturnValue_t insert(object_id_t id, SystemObjectIF* object) override; ReturnValue_t remove(object_id_t id) override; void initialize() override; @@ -66,6 +71,9 @@ class ObjectManager : public ObjectManagerIF { */ std::map objectList; static ObjectManager* objManagerInstance; + // used when the OM itself is deleted to modify behaviour of remove() + // to avoid iterator invalidation and double free + bool teardown = false; }; // Documentation can be found in the class method declaration above diff --git a/src/fsfw/objectmanager/ObjectManagerIF.h b/src/fsfw/objectmanager/ObjectManagerIF.h index 32a0942f..81ddd95a 100644 --- a/src/fsfw/objectmanager/ObjectManagerIF.h +++ b/src/fsfw/objectmanager/ObjectManagerIF.h @@ -1,7 +1,7 @@ #ifndef FSFW_OBJECTMANAGER_OBJECTMANAGERIF_H_ #define FSFW_OBJECTMANAGER_OBJECTMANAGERIF_H_ -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "../serviceinterface/ServiceInterface.h" #include "SystemObjectIF.h" #include "frameworkObjects.h" @@ -16,7 +16,7 @@ * @author Bastian Baetz * @ingroup system_objects */ -class ObjectManagerIF : public HasReturnvaluesIF { +class ObjectManagerIF { public: static constexpr uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; static constexpr ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE(1); @@ -48,14 +48,14 @@ class ObjectManagerIF : public HasReturnvaluesIF { * @param id The new id to be added to the list. * @param object A pointer to the object to be added. * @return @li INSERTION_FAILED in case the object could not be inserted. - * @li RETURN_OK in case the object was successfully inserted + * @li returnvalue::OK in case the object was successfully inserted */ virtual ReturnValue_t insert(object_id_t id, SystemObjectIF* object) = 0; /** * @brief With this call, an object is removed from the list. * @param id The object id of the object to be removed. * @return @li NOT_FOUND in case the object was not found - * @li RETURN_OK in case the object was successfully removed + * @li returnvalue::OK in case the object was successfully removed */ virtual ReturnValue_t remove(object_id_t id) = 0; virtual void initialize() = 0; diff --git a/src/fsfw/objectmanager/SystemObject.cpp b/src/fsfw/objectmanager/SystemObject.cpp index 7f8acfd8..90839013 100644 --- a/src/fsfw/objectmanager/SystemObject.cpp +++ b/src/fsfw/objectmanager/SystemObject.cpp @@ -22,9 +22,9 @@ void SystemObject::triggerEvent(Event event, uint32_t parameter1, uint32_t param EventManagerIF::triggerEvent(objectId, event, parameter1, parameter2); } -ReturnValue_t SystemObject::initialize() { return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t SystemObject::initialize() { return returnvalue::OK; } -ReturnValue_t SystemObject::checkObjectConnections() { return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t SystemObject::checkObjectConnections() { return returnvalue::OK; } void SystemObject::forwardEvent(Event event, uint32_t parameter1, uint32_t parameter2) const { EventManagerIF::triggerEvent(objectId, event, parameter1, parameter2); diff --git a/src/fsfw/objectmanager/SystemObject.h b/src/fsfw/objectmanager/SystemObject.h index 6d5b8303..c541ac5e 100644 --- a/src/fsfw/objectmanager/SystemObject.h +++ b/src/fsfw/objectmanager/SystemObject.h @@ -48,9 +48,10 @@ class SystemObject : public SystemObjectIF { virtual ~SystemObject(); object_id_t getObjectId() const override; virtual ReturnValue_t initialize() override; - virtual ReturnValue_t checkObjectConnections(); + virtual ReturnValue_t checkObjectConnections() override; - virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const; + virtual void forwardEvent(Event event, uint32_t parameter1 = 0, + uint32_t parameter2 = 0) const override; }; #endif /* FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ */ diff --git a/src/fsfw/objectmanager/SystemObjectIF.h b/src/fsfw/objectmanager/SystemObjectIF.h index 72fe9044..b9243de2 100644 --- a/src/fsfw/objectmanager/SystemObjectIF.h +++ b/src/fsfw/objectmanager/SystemObjectIF.h @@ -4,7 +4,7 @@ #include #include "../events/EventReportingProxyIF.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" /** * @defgroup system_objects Software System Object Management * The classes to create System Objects and classes to manage these are @@ -16,7 +16,7 @@ * This is the typedef for object identifiers. * @ingroup system_objects */ -typedef uint32_t object_id_t; +using object_id_t = uint32_t; /** * This interface allows a class to be included in the object manager @@ -45,8 +45,8 @@ class SystemObjectIF : public EventReportingProxyIF { * which might not have been built yet. * Therefore, a two-step initialization resolves this problem and prevents * circular dependencies of not-fully initialized objects on start up. - * @return - @c RETURN_OK in case the initialization was successful - * - @c RETURN_FAILED otherwise + * @return - @c returnvalue::OK in case the initialization was successful + * - @c returnvalue::FAILED otherwise */ virtual ReturnValue_t initialize() = 0; /** @@ -54,7 +54,7 @@ class SystemObjectIF : public EventReportingProxyIF { * for operation. * Some objects need certain other objects (or a certain number), to be * registered as children. These checks can be done in this method. - * @return - @c RETURN_OK in case the check was successful + * @return - @c returnvalue::OK in case the check was successful * - @c any other code otherwise */ virtual ReturnValue_t checkObjectConnections() = 0; diff --git a/src/fsfw/objectmanager/frameworkObjects.h b/src/fsfw/objectmanager/frameworkObjects.h index cc233c0f..9487147d 100644 --- a/src/fsfw/objectmanager/frameworkObjects.h +++ b/src/fsfw/objectmanager/frameworkObjects.h @@ -14,6 +14,7 @@ enum framework_objects : object_id_t { PUS_SERVICE_5_EVENT_REPORTING = 0x53000005, PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008, PUS_SERVICE_9_TIME_MGMT = 0x53000009, + PUS_SERVICE_11_TC_SCHEDULER = 0x53000011, PUS_SERVICE_17_TEST = 0x53000017, PUS_SERVICE_20_PARAMETERS = 0x53000020, PUS_SERVICE_200_MODE_MGMT = 0x53000200, @@ -32,6 +33,7 @@ enum framework_objects : object_id_t { TC_STORE = 0x534f0100, TM_STORE = 0x534f0200, TIME_STAMPER = 0x53500010, + VERIFICATION_REPORTER = 0x53500020, FSFW_OBJECTS_END = 0x53ffffff, NO_OBJECT = 0xFFFFFFFF diff --git a/src/fsfw/osal/CMakeLists.txt b/src/fsfw/osal/CMakeLists.txt index f3c5cfad..6ccea974 100644 --- a/src/fsfw/osal/CMakeLists.txt +++ b/src/fsfw/osal/CMakeLists.txt @@ -1,35 +1,42 @@ # Check the OS_FSFW variable if(FSFW_OSAL MATCHES "freertos") - add_subdirectory(freertos) + add_subdirectory(freertos) + set(FSFW_OSAL_FREERTOS 1) elseif(FSFW_OSAL MATCHES "rtems") - add_subdirectory(rtems) + add_subdirectory(rtems) + set(FSFW_OSAL_RTEMS 1) elseif(FSFW_OSAL MATCHES "linux") - add_subdirectory(linux) + add_subdirectory(linux) + set(FSFW_OSAL_LINUX 1) elseif(FSFW_OSAL MATCHES "host") - add_subdirectory(host) - if (WIN32) - add_subdirectory(windows) - elseif(UNIX) - # We still need to pull in some Linux specific sources - target_sources(${LIB_FSFW_NAME} PUBLIC - linux/tcpipHelpers.cpp - ) - endif () - + add_subdirectory(host) + if(WIN32) + add_subdirectory(windows) + elseif(UNIX) + # We still need to pull in some Linux specific sources + target_sources(${LIB_FSFW_NAME} PUBLIC linux/tcpipHelpers.cpp) + endif() + set(FSFW_OSAL_HOST 1) else() + message( + WARNING + "${MSG_PREFIX} The FSFW_OSAL variable was not set. Assuming host OS..") - message(WARNING "The OS_FSFW variable was not set. Assuming host OS..") - # Not set. Assumuing this is a host build, try to determine host OS - if (WIN32) - add_subdirectory(host) - add_subdirectory(windows) - elseif (UNIX) - add_subdirectory(linux) - else () - # MacOS or other OSes have not been tested yet / are not supported. - message(FATAL_ERROR "The host OS could not be determined! Aborting.") - endif() + # Not set. Assumuing this is a host build, try to determine host OS + if(WIN32) + add_subdirectory(host) + add_subdirectory(windows) + set(FSFW_OSAL_HOST 1) + elseif(UNIX) + add_subdirectory(linux) + set(FSFW_OSAL_LINUX 1) + else() + # MacOS or other OSes have not been tested yet / are not supported. + message(FATAL_ERROR "The host OS could not be determined! Aborting.") + endif() endif() -add_subdirectory(common) \ No newline at end of file +add_subdirectory(common) + +configure_file(osal.h.in ${CMAKE_BINARY_DIR}/fsfw/osal/osal.h) diff --git a/src/fsfw/osal/InternalErrorCodes.h b/src/fsfw/osal/InternalErrorCodes.h index 5924d4c9..abec460f 100644 --- a/src/fsfw/osal/InternalErrorCodes.h +++ b/src/fsfw/osal/InternalErrorCodes.h @@ -1,7 +1,7 @@ #ifndef INTERNALERRORCODES_H_ #define INTERNALERRORCODES_H_ -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" class InternalErrorCodes { public: diff --git a/src/fsfw/osal/common/CMakeLists.txt b/src/fsfw/osal/common/CMakeLists.txt index b7c8c033..c0814172 100644 --- a/src/fsfw/osal/common/CMakeLists.txt +++ b/src/fsfw/osal/common/CMakeLists.txt @@ -1,17 +1,10 @@ if(DEFINED WIN32 OR DEFINED UNIX) - target_sources(${LIB_FSFW_NAME} PRIVATE - tcpipCommon.cpp - TcpIpBase.cpp - UdpTcPollingTask.cpp - UdpTmTcBridge.cpp - TcpTmTcServer.cpp - TcpTmTcBridge.cpp - ) + target_sources( + ${LIB_FSFW_NAME} + PRIVATE tcpipCommon.cpp TcpIpBase.cpp UdpTcPollingTask.cpp + UdpTmTcBridge.cpp TcpTmTcServer.cpp TcpTmTcBridge.cpp) endif() if(WIN32) - target_link_libraries(${LIB_FSFW_NAME} PRIVATE - wsock32 - ws2_32 - ) -endif() \ No newline at end of file + target_link_libraries(${LIB_FSFW_NAME} PRIVATE wsock32 ws2_32) +endif() diff --git a/src/fsfw/osal/common/TcpIpBase.cpp b/src/fsfw/osal/common/TcpIpBase.cpp index 67e71053..b12921bd 100644 --- a/src/fsfw/osal/common/TcpIpBase.cpp +++ b/src/fsfw/osal/common/TcpIpBase.cpp @@ -1,6 +1,7 @@ #include "fsfw/osal/common/TcpIpBase.h" #include "fsfw/platform.h" +#include "fsfw/serviceinterface.h" #ifdef PLATFORM_UNIX #include @@ -21,10 +22,10 @@ ReturnValue_t TcpIpBase::initialize() { sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: WSAStartup failed with error: " << err << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } #endif - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } TcpIpBase::~TcpIpBase() { @@ -39,6 +40,8 @@ int TcpIpBase::closeSocket(socket_t socket) { return closesocket(socket); #elif defined(PLATFORM_UNIX) return close(socket); +#else + return -1; #endif } @@ -47,5 +50,7 @@ int TcpIpBase::getLastSocketError() { return WSAGetLastError(); #elif defined(PLATFORM_UNIX) return errno; +#else + return 0; #endif } diff --git a/src/fsfw/osal/common/TcpIpBase.h b/src/fsfw/osal/common/TcpIpBase.h index ccbd12ca..6cc71fbf 100644 --- a/src/fsfw/osal/common/TcpIpBase.h +++ b/src/fsfw/osal/common/TcpIpBase.h @@ -2,7 +2,7 @@ #define FSFW_OSAL_COMMON_TCPIPIF_H_ #include "../../platform.h" -#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../returnvalues/returnvalue.h" #ifdef PLATFORM_WIN #include diff --git a/src/fsfw/osal/common/TcpTmTcBridge.cpp b/src/fsfw/osal/common/TcpTmTcBridge.cpp index 4b2bea73..0bf3ab28 100644 --- a/src/fsfw/osal/common/TcpTmTcBridge.cpp +++ b/src/fsfw/osal/common/TcpTmTcBridge.cpp @@ -16,9 +16,9 @@ #endif -TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId, - object_id_t tcStoreId) - : TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) { +TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, + uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId) + : TmTcBridge("TCP TMTC Bridge", objectId, tcDestination, msgQueueDepth, tmStoreId, tcStoreId) { mutex = MutexFactory::instance()->createMutex(); // Connection is always up, TM is requested by connecting to server and receiving packets registerCommConnect(); @@ -26,7 +26,7 @@ TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, ob ReturnValue_t TcpTmTcBridge::initialize() { ReturnValue_t result = TmTcBridge::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "TcpTmTcBridge::initialize: TmTcBridge initialization failed!" << std::endl; #else @@ -35,7 +35,7 @@ ReturnValue_t TcpTmTcBridge::initialize() { return result; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } TcpTmTcBridge::~TcpTmTcBridge() { @@ -48,21 +48,20 @@ ReturnValue_t TcpTmTcBridge::handleTm() { // Simply store the telemetry in the FIFO, the server will use it to access the TM MutexGuard guard(mutex, timeoutType, mutexTimeoutMs); TmTcMessage message; - ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t status = returnvalue::OK; for (ReturnValue_t result = tmTcReceptionQueue->receiveMessage(&message); - result == HasReturnvaluesIF::RETURN_OK; - result = tmTcReceptionQueue->receiveMessage(&message)) { + result == returnvalue::OK; result = tmTcReceptionQueue->receiveMessage(&message)) { status = storeDownlinkData(&message); - if (status != HasReturnvaluesIF::RETURN_OK) { + if (status != returnvalue::OK) { break; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t TcpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) { // Not used. The Server uses the FIFO to access and send the telemetry. - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void TcpTmTcBridge::setMutexProperties(MutexIF::TimeoutType timeoutType, dur_millis_t timeoutMs) { diff --git a/src/fsfw/osal/common/TcpTmTcBridge.h b/src/fsfw/osal/common/TcpTmTcBridge.h index 504592cc..b330ba2a 100644 --- a/src/fsfw/osal/common/TcpTmTcBridge.h +++ b/src/fsfw/osal/common/TcpTmTcBridge.h @@ -38,7 +38,7 @@ class TcpTmTcBridge : public TmTcBridge { * @param tmStoreId TM store object ID. It is recommended to the default object ID * @param tcStoreId TC store object ID. It is recommended to the default object ID */ - TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, + TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, uint32_t msgQueueDepth, object_id_t tmStoreId = objects::TM_STORE, object_id_t tcStoreId = objects::TC_STORE); virtual ~TcpTmTcBridge(); diff --git a/src/fsfw/osal/common/TcpTmTcServer.cpp b/src/fsfw/osal/common/TcpTmTcServer.cpp index 2e6910c5..903d8752 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.cpp +++ b/src/fsfw/osal/common/TcpTmTcServer.cpp @@ -19,17 +19,19 @@ #include #elif defined(PLATFORM_UNIX) #include + +#include #endif const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT; TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge, - size_t receptionBufferSize, size_t ringBufferSize, - std::string customTcpServerPort, ReceptionModes receptionMode) + TcpTmTcServer::TcpConfig cfg, size_t receptionBufferSize, + size_t ringBufferSize, ReceptionModes receptionMode) : SystemObject(objectId), tmtcBridgeId(tmtcTcpBridge), receptionMode(receptionMode), - tcpConfig(customTcpServerPort), + tcpConfig(cfg), receptionBuffer(receptionBufferSize), ringBuffer(ringBufferSize, true) {} @@ -37,7 +39,7 @@ ReturnValue_t TcpTmTcServer::initialize() { using namespace tcpip; ReturnValue_t result = TcpIpBase::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -45,7 +47,7 @@ ReturnValue_t TcpTmTcServer::initialize() { case (ReceptionModes::SPACE_PACKETS): { spacePacketParser = new SpacePacketParser(validPacketIds); if (spacePacketParser == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } #if defined PLATFORM_UNIX tcpConfig.tcpFlags |= MSG_DONTWAIT; @@ -77,7 +79,7 @@ ReturnValue_t TcpTmTcServer::initialize() { retval = getaddrinfo(nullptr, tcpConfig.tcpPort.c_str(), &hints, &addrResult); if (retval != 0) { handleError(Protocol::TCP, ErrorSources::GETADDRINFO_CALL); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } // Open TCP (stream) socket @@ -86,7 +88,16 @@ ReturnValue_t TcpTmTcServer::initialize() { if (listenerTcpSocket == INVALID_SOCKET) { freeaddrinfo(addrResult); handleError(Protocol::TCP, ErrorSources::SOCKET_CALL); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; + } + + if (tcpConfig.reuseAddr) { + unsigned int enable = 1; + setsockopt(listenerTcpSocket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); + } + if (tcpConfig.reusePort) { + unsigned int enable = 1; + setsockopt(listenerTcpSocket, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable)); } // Bind to the address found by getaddrinfo @@ -94,21 +105,21 @@ ReturnValue_t TcpTmTcServer::initialize() { if (retval == SOCKET_ERROR) { freeaddrinfo(addrResult); handleError(Protocol::TCP, ErrorSources::BIND_CALL); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } freeaddrinfo(addrResult); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } TcpTmTcServer::~TcpTmTcServer() { closeSocket(listenerTcpSocket); } -ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) { +[[noreturn]] ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) { using namespace tcpip; // If a connection is accepted, the corresponding socket will be assigned to the new socket socket_t connSocket = 0; - // sockaddr clientSockAddr = {}; - // socklen_t connectorSockAddrLen = 0; + sockaddr clientSockAddr = {}; + socklen_t connectorSockAddrLen = 0; int retval = 0; // Listen for connection requests permanently for lifetime of program @@ -119,8 +130,7 @@ ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) { continue; } - // connSocket = accept(listenerTcpSocket, &clientSockAddr, &connectorSockAddrLen); - connSocket = accept(listenerTcpSocket, nullptr, nullptr); + connSocket = accept(listenerTcpSocket, &clientSockAddr, &connectorSockAddrLen); if (connSocket == INVALID_SOCKET) { handleError(Protocol::TCP, ErrorSources::ACCEPT_CALL, 500); @@ -135,10 +145,10 @@ ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) { if (retval != 0) { handleError(Protocol::TCP, ErrorSources::SHUTDOWN_CALL); } + closeSocket(connSocket); connSocket = 0; } - return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t TcpTmTcServer::initializeAfterTaskCreation() { @@ -150,7 +160,7 @@ ReturnValue_t TcpTmTcServer::initializeAfterTaskCreation() { targetTcDestination = tmtcBridge->getRequestQueue(); tcStore = tmtcBridge->tcStore; tmStore = tmtcBridge->tmStore; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void TcpTmTcServer::handleServerOperation(socket_t& connSocket) { @@ -159,8 +169,8 @@ void TcpTmTcServer::handleServerOperation(socket_t& connSocket) { #endif while (true) { - int retval = recv(connSocket, reinterpret_cast(receptionBuffer.data()), - receptionBuffer.capacity(), tcpConfig.tcpFlags); + ssize_t retval = recv(connSocket, reinterpret_cast(receptionBuffer.data()), + receptionBuffer.size(), tcpConfig.tcpFlags); if (retval == 0) { size_t availableReadData = ringBuffer.getAvailableReadData(); if (availableReadData > lastRingBufferSize) { @@ -213,11 +223,11 @@ ReturnValue_t TcpTmTcServer::handleTcReception(uint8_t* spacePacket, size_t pack } if (spacePacket == nullptr or packetSize == 0) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } store_address_t storeId; ReturnValue_t result = tcStore->addData(&storeId, spacePacket, packetSize); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "TcpTmTcServer::handleServerOperation: Data storage with packet size" @@ -235,7 +245,7 @@ ReturnValue_t TcpTmTcServer::handleTcReception(uint8_t* spacePacket, size_t pack TmTcMessage message(storeId); result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "TcpTmTcServer::handleServerOperation: " @@ -252,17 +262,17 @@ ReturnValue_t TcpTmTcServer::handleTcReception(uint8_t* spacePacket, size_t pack return result; } -std::string TcpTmTcServer::getTcpPort() const { return tcpConfig.tcpPort; } +const std::string& TcpTmTcServer::getTcpPort() const { return tcpConfig.tcpPort; } -void TcpTmTcServer::setSpacePacketParsingOptions(std::vector validPacketIds) { - this->validPacketIds = validPacketIds; +void TcpTmTcServer::setSpacePacketParsingOptions(std::vector validPacketIds_) { + this->validPacketIds = std::move(validPacketIds_); } TcpTmTcServer::TcpConfig& TcpTmTcServer::getTcpConfigStruct() { return tcpConfig; } ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) { // Access to the FIFO is mutex protected because it is filled by the bridge - MutexGuard(tmtcBridge->mutex, tmtcBridge->timeoutType, tmtcBridge->mutexTimeoutMs); + MutexGuard mg(tmtcBridge->mutex, tmtcBridge->timeoutType, tmtcBridge->mutexTimeoutMs); store_address_t storeId; while ((not tmtcBridge->tmFifo->empty()) and (tmtcBridge->packetSentCounter < tmtcBridge->sentPacketsPerCycle)) { @@ -272,7 +282,7 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) // Using the store accessor will take care of deleting TM from the store automatically ConstStorageAccessor storeAccessor(storeId); ReturnValue_t result = tmStore->getData(storeId, storeAccessor); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (wiretappingEnabled) { @@ -283,8 +293,8 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) #endif arrayprinter::print(storeAccessor.data(), storeAccessor.size()); } - int retval = send(connSocket, reinterpret_cast(storeAccessor.data()), - storeAccessor.size(), tcpConfig.tcpTmFlags); + ssize_t retval = send(connSocket, reinterpret_cast(storeAccessor.data()), + storeAccessor.size(), tcpConfig.tcpTmFlags); if (retval == static_cast(storeAccessor.size())) { // Packet sent, clear FIFO entry tmtcBridge->tmFifo->pop(); @@ -296,12 +306,12 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) return CONN_BROKEN; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t TcpTmTcServer::handleTcRingBufferData(size_t availableReadData) { - ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t status = returnvalue::OK; + ReturnValue_t result = returnvalue::OK; size_t readAmount = availableReadData; lastRingBufferSize = availableReadData; if (readAmount >= ringBuffer.getMaxSize()) { @@ -334,28 +344,27 @@ ReturnValue_t TcpTmTcServer::handleTcRingBufferData(size_t availableReadData) { } ringBuffer.readData(receptionBuffer.data(), readAmount, true); const uint8_t* bufPtr = receptionBuffer.data(); - const uint8_t** bufPtrPtr = &bufPtr; - size_t startIdx = 0; - size_t foundSize = 0; - size_t readLen = 0; - while (readLen < readAmount) { - result = - spacePacketParser->parseSpacePackets(bufPtrPtr, readAmount, startIdx, foundSize, readLen); + SpacePacketParser::FoundPacketInfo info; + if (spacePacketParser == nullptr) { + return returnvalue::FAILED; + } + spacePacketParser->reset(); + while (spacePacketParser->getAmountRead() < readAmount) { + result = spacePacketParser->parseSpacePackets(&bufPtr, readAmount, info); switch (result) { case (SpacePacketParser::NO_PACKET_FOUND): case (SpacePacketParser::SPLIT_PACKET): { break; } - case (HasReturnvaluesIF::RETURN_OK): { - result = handleTcReception(receptionBuffer.data() + startIdx, foundSize); - if (result != HasReturnvaluesIF::RETURN_OK) { + case (returnvalue::OK): { + result = handleTcReception(receptionBuffer.data() + info.startIdx, info.sizeFound); + if (result != returnvalue::OK) { status = result; } } } - ringBuffer.deleteData(foundSize); + ringBuffer.deleteData(info.sizeFound); lastRingBufferSize = ringBuffer.getAvailableReadData(); - std::memset(receptionBuffer.data() + startIdx, 0, foundSize); } return status; } diff --git a/src/fsfw/osal/common/TcpTmTcServer.h b/src/fsfw/osal/common/TcpTmTcServer.h index d062a0ce..009a1680 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.h +++ b/src/fsfw/osal/common/TcpTmTcServer.h @@ -17,6 +17,7 @@ #endif #include +#include #include class TcpTmTcBridge; @@ -40,11 +41,11 @@ class SpacePacketParser; */ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableObjectIF { public: - enum class ReceptionModes { SPACE_PACKETS }; - struct TcpConfig { public: - TcpConfig(std::string tcpPort) : tcpPort(tcpPort) {} + TcpConfig(bool reuseAddr, bool reusePort) : reuseAddr(reuseAddr), reusePort(reusePort) {} + TcpConfig(std::string tcpPort, bool reuseAddr, bool reusePort) + : tcpPort(std::move(tcpPort)), reuseAddr(reuseAddr), reusePort(reusePort) {} /** * Passed to the recv call @@ -62,8 +63,23 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb */ int tcpTmFlags = 0; - const std::string tcpPort; + std::string tcpPort = DEFAULT_SERVER_PORT; + + /** + * Sets the SO_REUSEADDR option on the socket. See + * https://man7.org/linux/man-pages/man7/socket.7.html for more details. This option is + * especially useful in a debugging and development environment where an OBSW image might be + * re-flashed oftentimes and where all incoming telecommands are received on a dedicated TCP + * port. + */ + bool reuseAddr = false; + /** + * Sets the SO_REUSEPORT option on the socket. See + * https://man7.org/linux/man-pages/man7/socket.7.html for more details. + */ + bool reusePort = false; }; + enum class ReceptionModes { SPACE_PACKETS }; static const std::string DEFAULT_SERVER_PORT; @@ -79,12 +95,11 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb * size will be the Ethernet MTU size * @param customTcpServerPort The user can specify another port than the default (7301) here. */ - TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge, + TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge, TcpTmTcServer::TcpConfig cfg, size_t receptionBufferSize = RING_BUFFER_SIZE, size_t ringBufferSize = RING_BUFFER_SIZE, - std::string customTcpServerPort = DEFAULT_SERVER_PORT, ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS); - virtual ~TcpTmTcServer(); + ~TcpTmTcServer() override; void enableWiretapping(bool enable); @@ -97,17 +112,17 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb void setSpacePacketParsingOptions(std::vector validPacketIds); ReturnValue_t initialize() override; - ReturnValue_t performOperation(uint8_t opCode) override; + [[noreturn]] ReturnValue_t performOperation(uint8_t opCode) override; ReturnValue_t initializeAfterTaskCreation() override; - std::string getTcpPort() const; + [[nodiscard]] const std::string& getTcpPort() const; protected: StorageManagerIF* tcStore = nullptr; StorageManagerIF* tmStore = nullptr; private: - static constexpr ReturnValue_t CONN_BROKEN = HasReturnvaluesIF::makeReturnCode(1, 0); + static constexpr ReturnValue_t CONN_BROKEN = returnvalue::makeCode(1, 0); //! TMTC bridge is cached. object_id_t tmtcBridgeId = objects::NO_OBJECT; TcpTmTcBridge* tmtcBridge = nullptr; @@ -115,7 +130,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb ReceptionModes receptionMode; TcpConfig tcpConfig; - struct sockaddr tcpAddress; + struct sockaddr tcpAddress = {}; socket_t listenerTcpSocket = 0; MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE; diff --git a/src/fsfw/osal/common/UdpTcPollingTask.cpp b/src/fsfw/osal/common/UdpTcPollingTask.cpp index ab982a3c..4304fdd2 100644 --- a/src/fsfw/osal/common/UdpTcPollingTask.cpp +++ b/src/fsfw/osal/common/UdpTcPollingTask.cpp @@ -16,11 +16,13 @@ //! Debugging preprocessor define. #define FSFW_UDP_RECV_WIRETAPPING_ENABLED 0 +const timeval UdpTcPollingTask::DEFAULT_TIMEOUT = {0, 500000}; + UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBridge, size_t maxRecvSize, double timeoutSeconds) : SystemObject(objectId), tmtcBridgeId(tmtcUdpBridge) { - if (frameSize > 0) { - this->frameSize = frameSize; + if (maxRecvSize > 0) { + this->frameSize = maxRecvSize; } else { this->frameSize = DEFAULT_MAX_RECV_SIZE; } @@ -31,22 +33,20 @@ UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBrid receptionBuffer.resize(this->frameSize); if (timeoutSeconds == -1) { - receptionTimeout = DEFAULT_TIMEOUT; + receptionTimeout = UdpTcPollingTask::DEFAULT_TIMEOUT; } else { receptionTimeout = timevalOperations::toTimeval(timeoutSeconds); } } -UdpTcPollingTask::~UdpTcPollingTask() {} - -ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) { +[[noreturn]] ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) { /* Sender Address is cached here. */ - struct sockaddr senderAddress; + struct sockaddr senderAddress {}; socklen_t senderAddressSize = sizeof(senderAddress); /* Poll for new UDP datagrams in permanent loop. */ while (true) { - int bytesReceived = + ssize_t bytesReceived = recvfrom(this->serverSocket, reinterpret_cast(receptionBuffer.data()), frameSize, receptionFlags, &senderAddress, &senderAddressSize); if (bytesReceived == SOCKET_ERROR) { @@ -66,11 +66,10 @@ ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) { #endif /* FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 */ ReturnValue_t result = handleSuccessfullTcRead(bytesReceived); - if (result != HasReturnvaluesIF::RETURN_FAILED) { + if (result != returnvalue::FAILED) { } tmtcBridge->checkAndSetClientAddress(senderAddress); } - return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t UdpTcPollingTask::handleSuccessfullTcRead(size_t bytesRead) { @@ -81,20 +80,20 @@ ReturnValue_t UdpTcPollingTask::handleSuccessfullTcRead(size_t bytesRead) { #endif ReturnValue_t result = tcStore->addData(&storeId, receptionBuffer.data(), bytesRead); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "UdpTcPollingTask::transferPusToSoftwareBus: Data storage failed." << std::endl; sif::warning << "Packet size: " << bytesRead << std::endl; #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } TmTcMessage message(storeId); result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "UdpTcPollingTask::handleSuccessfullTcRead: " @@ -125,11 +124,11 @@ ReturnValue_t UdpTcPollingTask::initialize() { } ReturnValue_t result = TcpIpBase::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t UdpTcPollingTask::initializeAfterTaskCreation() { @@ -139,7 +138,7 @@ ReturnValue_t UdpTcPollingTask::initializeAfterTaskCreation() { /* The server socket is set up in the bridge intialization. Calling this function here ensures that it is set up regardless of which class was initialized first */ this->serverSocket = tmtcBridge->serverSocket; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void UdpTcPollingTask::setTimeout(double timeoutSeconds) { @@ -155,7 +154,7 @@ void UdpTcPollingTask::setTimeout(double timeoutSeconds) { #endif } #elif defined(PLATFORM_UNIX) - timeval tval; + timeval tval{}; tval = timevalOperations::toTimeval(timeoutSeconds); int result = setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO, &tval, sizeof(receptionTimeout)); if (result == -1) { diff --git a/src/fsfw/osal/common/UdpTcPollingTask.h b/src/fsfw/osal/common/UdpTcPollingTask.h index afcd32a1..894716d7 100644 --- a/src/fsfw/osal/common/UdpTcPollingTask.h +++ b/src/fsfw/osal/common/UdpTcPollingTask.h @@ -21,11 +21,11 @@ class UdpTcPollingTask : public TcpIpBase, public SystemObject, public Executabl public: static constexpr size_t DEFAULT_MAX_RECV_SIZE = 1500; //! 0.5 default milliseconds timeout for now. - static constexpr timeval DEFAULT_TIMEOUT = {0, 500}; + static const timeval DEFAULT_TIMEOUT; UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBridge, size_t maxRecvSize = 0, double timeoutSeconds = -1); - virtual ~UdpTcPollingTask(); + ~UdpTcPollingTask() override = default; /** * Turn on optional timeout for UDP polling. In the default mode, @@ -34,9 +34,9 @@ class UdpTcPollingTask : public TcpIpBase, public SystemObject, public Executabl */ void setTimeout(double timeoutSeconds); - virtual ReturnValue_t performOperation(uint8_t opCode) override; - virtual ReturnValue_t initialize() override; - virtual ReturnValue_t initializeAfterTaskCreation() override; + [[noreturn]] ReturnValue_t performOperation(uint8_t opCode) override; + ReturnValue_t initialize() override; + ReturnValue_t initializeAfterTaskCreation() override; protected: StorageManagerIF* tcStore = nullptr; @@ -51,7 +51,7 @@ class UdpTcPollingTask : public TcpIpBase, public SystemObject, public Executabl std::vector receptionBuffer; size_t frameSize = 0; - timeval receptionTimeout; + timeval receptionTimeout{}; ReturnValue_t handleSuccessfullTcRead(size_t bytesRead); }; diff --git a/src/fsfw/osal/common/UdpTmTcBridge.cpp b/src/fsfw/osal/common/UdpTmTcBridge.cpp index 0efe1c74..d6014ec7 100644 --- a/src/fsfw/osal/common/UdpTmTcBridge.cpp +++ b/src/fsfw/osal/common/UdpTmTcBridge.cpp @@ -20,13 +20,13 @@ const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT; UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, - std::string udpServerPort, object_id_t tmStoreId, - object_id_t tcStoreId) - : TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) { - if (udpServerPort == "") { - this->udpServerPort = DEFAULT_SERVER_PORT; + uint32_t msgQueueDepth, const std::string &udpServerPort_, + object_id_t tmStoreId, object_id_t tcStoreId) + : TmTcBridge("UDP TMTC Bridge", objectId, tcDestination, msgQueueDepth, tmStoreId, tcStoreId) { + if (udpServerPort_.empty()) { + udpServerPort = DEFAULT_SERVER_PORT; } else { - this->udpServerPort = udpServerPort; + udpServerPort = udpServerPort_; } mutex = MutexFactory::instance()->createMutex(); @@ -35,7 +35,7 @@ UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, ReturnValue_t UdpTmTcBridge::initialize() { ReturnValue_t result = TmTcBridge::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "UdpTmTcBridge::initialize: TmTcBridge initialization failed!" << std::endl; #endif @@ -56,7 +56,7 @@ ReturnValue_t UdpTmTcBridge::initialize() { #else sif::printError("UdpTmTcBridge::UdpTmTcBridge: WSAStartup failed with error: %d\n", err); #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } #endif @@ -75,14 +75,14 @@ ReturnValue_t UdpTmTcBridge::initialize() { int retval = getaddrinfo(nullptr, udpServerPort.c_str(), &hints, &addrResult); if (retval != 0) { tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::GETADDRINFO_CALL); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } serverSocket = socket(addrResult->ai_family, addrResult->ai_socktype, addrResult->ai_protocol); if (serverSocket == INVALID_SOCKET) { freeaddrinfo(addrResult); tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SOCKET_CALL); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } #if FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1 @@ -93,10 +93,10 @@ ReturnValue_t UdpTmTcBridge::initialize() { if (retval != 0) { freeaddrinfo(addrResult); tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::BIND_CALL); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } freeaddrinfo(addrResult); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } UdpTmTcBridge::~UdpTmTcBridge() { @@ -117,8 +117,8 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) { tcpip::printAddress(&clientAddress); #endif - int bytesSent = sendto(serverSocket, reinterpret_cast(data), dataLen, flags, - &clientAddress, clientAddressLen); + ssize_t bytesSent = sendto(serverSocket, reinterpret_cast(data), dataLen, flags, + &clientAddress, clientAddressLen); if (bytesSent == SOCKET_ERROR) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "TmTcUdpBridge::sendTm: Send operation failed." << std::endl; @@ -126,12 +126,9 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) { tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL); } #if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1 - sif::debug << "TmTcUdpBridge::sendTm: " << bytesSent - << " bytes were" - " sent." - << std::endl; + sif::debug << "TmTcUdpBridge::sendTm: " << bytesSent << " bytes were sent" << std::endl; #endif - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void UdpTmTcBridge::checkAndSetClientAddress(sockaddr &newAddress) { @@ -150,7 +147,7 @@ void UdpTmTcBridge::checkAndSetClientAddress(sockaddr &newAddress) { clientAddressLen = sizeof(clientAddress); } -void UdpTmTcBridge::setMutexProperties(MutexIF::TimeoutType timeoutType, dur_millis_t timeoutMs) { - this->timeoutType = timeoutType; - this->mutexTimeoutMs = timeoutMs; +void UdpTmTcBridge::setMutexProperties(MutexIF::TimeoutType timeoutType_, dur_millis_t timeoutMs) { + timeoutType = timeoutType_; + mutexTimeoutMs = timeoutMs; } diff --git a/src/fsfw/osal/common/UdpTmTcBridge.h b/src/fsfw/osal/common/UdpTmTcBridge.h index 78843ccd..ce8adb4c 100644 --- a/src/fsfw/osal/common/UdpTmTcBridge.h +++ b/src/fsfw/osal/common/UdpTmTcBridge.h @@ -29,10 +29,10 @@ class UdpTmTcBridge : public TmTcBridge, public TcpIpBase { /* The ports chosen here should not be used by any other process. */ static const std::string DEFAULT_SERVER_PORT; - UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, std::string udpServerPort = "", - object_id_t tmStoreId = objects::TM_STORE, + UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, uint32_t msgQueueDepth, + const std::string& udpServerPort = "", object_id_t tmStoreId = objects::TM_STORE, object_id_t tcStoreId = objects::TC_STORE); - virtual ~UdpTmTcBridge(); + ~UdpTmTcBridge() override; /** * Set properties of internal mutex. @@ -46,12 +46,12 @@ class UdpTmTcBridge : public TmTcBridge, public TcpIpBase { std::string getUdpPort() const; protected: - virtual ReturnValue_t sendTm(const uint8_t* data, size_t dataLen) override; + ReturnValue_t sendTm(const uint8_t* data, size_t dataLen) override; private: std::string udpServerPort; - struct sockaddr clientAddress; + struct sockaddr clientAddress = {}; socklen_t clientAddressLen = 0; //! Access to the client address is mutex protected as it is set by another task. diff --git a/src/fsfw/osal/freertos/BinSemaphUsingTask.cpp b/src/fsfw/osal/freertos/BinSemaphUsingTask.cpp index 7ffd61d3..54226e18 100644 --- a/src/fsfw/osal/freertos/BinSemaphUsingTask.cpp +++ b/src/fsfw/osal/freertos/BinSemaphUsingTask.cpp @@ -42,7 +42,7 @@ ReturnValue_t BinarySemaphoreUsingTask::acquireWithTickTimeout(TimeoutType timeo TickType_t timeoutTicks) { BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks); if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { return SemaphoreIF::SEMAPHORE_TIMEOUT; } @@ -56,10 +56,10 @@ ReturnValue_t BinarySemaphoreUsingTask::release(TaskHandle_t taskHandle) { } BaseType_t returncode = xTaskNotifyGive(taskHandle); if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { // This should never happen. - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -82,7 +82,7 @@ ReturnValue_t BinarySemaphoreUsingTask::releaseFromISR(TaskHandle_t taskHandle, return SemaphoreIF::SEMAPHORE_NOT_OWNED; } vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR(TaskHandle_t taskHandle, diff --git a/src/fsfw/osal/freertos/BinSemaphUsingTask.h b/src/fsfw/osal/freertos/BinSemaphUsingTask.h index 34b0d031..480296ee 100644 --- a/src/fsfw/osal/freertos/BinSemaphUsingTask.h +++ b/src/fsfw/osal/freertos/BinSemaphUsingTask.h @@ -2,7 +2,7 @@ #define FSFW_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ #include "FreeRTOS.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/tasks/SemaphoreIF.h" #include "task.h" @@ -20,7 +20,7 @@ * (for example in the initializeAfterTaskCreation() function) or * by calling refreshTaskHandle() with the correct executing task. */ -class BinarySemaphoreUsingTask : public SemaphoreIF, public HasReturnvaluesIF { +class BinarySemaphoreUsingTask : public SemaphoreIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; @@ -50,8 +50,8 @@ class BinarySemaphoreUsingTask : public SemaphoreIF, public HasReturnvaluesIF { /** * Same as acquire() with timeout in FreeRTOS ticks. * @param timeoutTicks - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure + * @return - @c returnvalue::OK on success + * - @c returnvalue::FAILED on failure */ ReturnValue_t acquireWithTickTimeout(TimeoutType timeoutType = TimeoutType::BLOCKING, TickType_t timeoutTicks = portMAX_DELAY); @@ -65,8 +65,8 @@ class BinarySemaphoreUsingTask : public SemaphoreIF, public HasReturnvaluesIF { /** * Wrapper function to give back semaphore from handle * @param semaphore - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure + * @return - @c returnvalue::OK on success + * - @c returnvalue::FAILED on failure */ static ReturnValue_t release(TaskHandle_t taskToNotify); @@ -76,8 +76,8 @@ class BinarySemaphoreUsingTask : public SemaphoreIF, public HasReturnvaluesIF { * @param higherPriorityTaskWoken This will be set to pdPASS if a task with * a higher priority was unblocked. A context switch should be requested * from an ISR if this is the case (see TaskManagement functions) - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure + * @return - @c returnvalue::OK on success + * - @c returnvalue::FAILED on failure */ static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, BaseType_t* higherPriorityTaskWoken); diff --git a/src/fsfw/osal/freertos/BinarySemaphore.cpp b/src/fsfw/osal/freertos/BinarySemaphore.cpp index 6e53380c..0ab621bc 100644 --- a/src/fsfw/osal/freertos/BinarySemaphore.cpp +++ b/src/fsfw/osal/freertos/BinarySemaphore.cpp @@ -59,7 +59,7 @@ ReturnValue_t BinarySemaphore::acquireWithTickTimeout(TimeoutType timeoutType, BaseType_t returncode = xSemaphoreTake(handle, timeoutTicks); if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { return SemaphoreIF::SEMAPHORE_TIMEOUT; } @@ -73,7 +73,7 @@ ReturnValue_t BinarySemaphore::release(SemaphoreHandle_t semaphore) { } BaseType_t returncode = xSemaphoreGive(semaphore); if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { return SemaphoreIF::SEMAPHORE_NOT_OWNED; } @@ -91,7 +91,7 @@ ReturnValue_t BinarySemaphore::releaseFromISR(SemaphoreHandle_t semaphore, } BaseType_t returncode = xSemaphoreGiveFromISR(semaphore, higherPriorityTaskWoken); if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { return SemaphoreIF::SEMAPHORE_NOT_OWNED; } diff --git a/src/fsfw/osal/freertos/BinarySemaphore.h b/src/fsfw/osal/freertos/BinarySemaphore.h index e2ca3c9d..bd1148ec 100644 --- a/src/fsfw/osal/freertos/BinarySemaphore.h +++ b/src/fsfw/osal/freertos/BinarySemaphore.h @@ -2,7 +2,7 @@ #define FSFW_OSAL_FREERTOS_BINARYSEMPAHORE_H_ #include "FreeRTOS.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/tasks/SemaphoreIF.h" #include "semphr.h" @@ -22,7 +22,7 @@ * @author R. Mueller * @ingroup osal */ -class BinarySemaphore : public SemaphoreIF, public HasReturnvaluesIF { +class BinarySemaphore : public SemaphoreIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; @@ -47,7 +47,7 @@ class BinarySemaphore : public SemaphoreIF, public HasReturnvaluesIF { * for a maximum of #timeoutMs or until the semaphore is given back, * for example by an ISR or another task. * @param timeoutMs - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout */ ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, @@ -56,7 +56,7 @@ class BinarySemaphore : public SemaphoreIF, public HasReturnvaluesIF { /** * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. * @param timeoutTicks - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout */ ReturnValue_t acquireWithTickTimeout(TimeoutType timeoutType = TimeoutType::BLOCKING, @@ -64,7 +64,7 @@ class BinarySemaphore : public SemaphoreIF, public HasReturnvaluesIF { /** * Release the binary semaphore. - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is * already available. */ @@ -79,7 +79,7 @@ class BinarySemaphore : public SemaphoreIF, public HasReturnvaluesIF { /** * Wrapper function to give back semaphore from handle * @param semaphore - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is * already available. */ @@ -91,7 +91,7 @@ class BinarySemaphore : public SemaphoreIF, public HasReturnvaluesIF { * @param higherPriorityTaskWoken This will be set to pdPASS if a task with * a higher priority was unblocked. A context switch from an ISR should * then be requested (see TaskManagement functions) - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is * already available. */ diff --git a/src/fsfw/osal/freertos/CMakeLists.txt b/src/fsfw/osal/freertos/CMakeLists.txt index 40bdcd0f..cb6ac55a 100644 --- a/src/fsfw/osal/freertos/CMakeLists.txt +++ b/src/fsfw/osal/freertos/CMakeLists.txt @@ -1,32 +1,30 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - Clock.cpp - FixedTimeslotTask.cpp - BinarySemaphore.cpp - BinSemaphUsingTask.cpp - CountingSemaphore.cpp - CountingSemaphUsingTask.cpp - MessageQueue.cpp - Mutex.cpp - MutexFactory.cpp - PeriodicTask.cpp - QueueFactory.cpp - SemaphoreFactory.cpp - TaskFactory.cpp - Timekeeper.cpp - TaskManagement.cpp - QueueMapManager.cpp -) +target_sources( + ${LIB_FSFW_NAME} + PRIVATE Clock.cpp + FixedTimeslotTask.cpp + BinarySemaphore.cpp + BinSemaphUsingTask.cpp + CountingSemaphore.cpp + CountingSemaphUsingTask.cpp + MessageQueue.cpp + Mutex.cpp + MutexFactory.cpp + PeriodicTask.cpp + QueueFactory.cpp + SemaphoreFactory.cpp + TaskFactory.cpp + Timekeeper.cpp + TaskManagement.cpp + QueueMapManager.cpp) -# FreeRTOS is required to link the FSFW now. It is recommended to compile -# FreeRTOS as a static library and set LIB_OS_NAME to the target name of the +# FreeRTOS is required to link the FSFW now. It is recommended to compile +# FreeRTOS as a static library and set LIB_OS_NAME to the target name of the # library. if(NOT LIB_OS_NAME) - message(STATUS - "LIB_OS_NAME is empty. Make sure to include the FreeRTOS header path properly." - ) + message( + STATUS + "LIB_OS_NAME is empty. Make sure to include the FreeRTOS header path properly." + ) else() - target_link_libraries(${LIB_FSFW_NAME} PRIVATE - ${LIB_OS_NAME} - ) + target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${LIB_OS_NAME}) endif() diff --git a/src/fsfw/osal/freertos/Clock.cpp b/src/fsfw/osal/freertos/Clock.cpp index cabf7d81..dc00ac7e 100644 --- a/src/fsfw/osal/freertos/Clock.cpp +++ b/src/fsfw/osal/freertos/Clock.cpp @@ -17,7 +17,7 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { timeval time_timeval; ReturnValue_t result = convertTimeOfDayToTimeval(time, &time_timeval); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -31,7 +31,7 @@ ReturnValue_t Clock::setClock(const timeval* time) { Timekeeper::instance()->setOffset(offset); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::getClock_timeval(timeval* time) { @@ -41,13 +41,13 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) { *time = offset + uptime; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::getUptime(timeval* uptime) { *uptime = getUptime(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } timeval Clock::getUptime() { @@ -58,7 +58,7 @@ timeval Clock::getUptime() { ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { timeval uptime = getUptime(); *uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } // uint32_t Clock::getUptimeSeconds() { @@ -69,17 +69,17 @@ ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { ReturnValue_t Clock::getClock_usecs(uint64_t* time) { timeval time_timeval; ReturnValue_t result = getClock_timeval(&time_timeval); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } *time = time_timeval.tv_sec * 1000000 + time_timeval.tv_usec; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { timeval time_timeval; ReturnValue_t result = getClock_timeval(&time_timeval); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } struct tm time_tm; @@ -96,7 +96,7 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { time->usecond = time_timeval.tv_usec; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) { @@ -115,10 +115,10 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to->tv_sec = seconds; to->tv_usec = from->usecond; // Fails in 2038.. - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { *JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/src/fsfw/osal/freertos/CountingSemaphUsingTask.cpp b/src/fsfw/osal/freertos/CountingSemaphUsingTask.cpp index 0e4d967d..f58e1be9 100644 --- a/src/fsfw/osal/freertos/CountingSemaphUsingTask.cpp +++ b/src/fsfw/osal/freertos/CountingSemaphUsingTask.cpp @@ -65,7 +65,7 @@ ReturnValue_t CountingSemaphoreUsingTask::acquireWithTickTimeout(TimeoutType tim // Decrement notfication value without resetting it. BaseType_t oldCount = ulTaskNotifyTake(pdFALSE, timeoutTicks); if (getSemaphoreCounter() == oldCount - 1) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { return SemaphoreIF::SEMAPHORE_TIMEOUT; } @@ -81,10 +81,10 @@ ReturnValue_t CountingSemaphoreUsingTask::release() { ReturnValue_t CountingSemaphoreUsingTask::release(TaskHandle_t taskToNotify) { BaseType_t returncode = xTaskNotifyGive(taskToNotify); if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { // This should never happen. - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -99,7 +99,7 @@ TaskHandle_t CountingSemaphoreUsingTask::getTaskHandle() { return handle; } ReturnValue_t CountingSemaphoreUsingTask::releaseFromISR(TaskHandle_t taskToNotify, BaseType_t* higherPriorityTaskWoken) { vTaskNotifyGiveFromISR(taskToNotify, higherPriorityTaskWoken); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } uint8_t CountingSemaphoreUsingTask::getSemaphoreCounterFromISR( diff --git a/src/fsfw/osal/freertos/CountingSemaphUsingTask.h b/src/fsfw/osal/freertos/CountingSemaphUsingTask.h index 86b27267..4426f29b 100644 --- a/src/fsfw/osal/freertos/CountingSemaphUsingTask.h +++ b/src/fsfw/osal/freertos/CountingSemaphUsingTask.h @@ -30,7 +30,7 @@ class CountingSemaphoreUsingTask : public SemaphoreIF { * for a maximum of #timeoutMs or until one is given back, * for example by an ISR or another task. * @param timeoutMs - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout */ ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, @@ -39,7 +39,7 @@ class CountingSemaphoreUsingTask : public SemaphoreIF { /** * Release a semaphore, increasing the number of available counting * semaphores up to the #maxCount value. - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are * already available. */ @@ -59,7 +59,7 @@ class CountingSemaphoreUsingTask : public SemaphoreIF { /** * Acquire with a timeout value in ticks * @param timeoutTicks - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout */ ReturnValue_t acquireWithTickTimeout(TimeoutType timeoutType = TimeoutType::BLOCKING, @@ -74,7 +74,7 @@ class CountingSemaphoreUsingTask : public SemaphoreIF { /** * Release semaphore of task by supplying task handle * @param taskToNotify - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are * already available. */ @@ -85,7 +85,7 @@ class CountingSemaphoreUsingTask : public SemaphoreIF { * @param higherPriorityTaskWoken This will be set to pdPASS if a task with * a higher priority was unblocked. A context switch should be requested * from an ISR if this is the case (see TaskManagement functions) - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are * already available. */ diff --git a/src/fsfw/osal/freertos/FixedTimeslotTask.cpp b/src/fsfw/osal/freertos/FixedTimeslotTask.cpp index e0e3779e..a0a4ecee 100644 --- a/src/fsfw/osal/freertos/FixedTimeslotTask.cpp +++ b/src/fsfw/osal/freertos/FixedTimeslotTask.cpp @@ -1,27 +1,23 @@ #include "fsfw/osal/freertos/FixedTimeslotTask.h" -#include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/serviceinterface/ServiceInterface.h" +#include "fsfw/serviceinterface.h" -uint32_t FixedTimeslotTask::deadlineMissedCount = 0; const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE; FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod overallPeriod, - void (*setDeadlineMissedFunc)()) - : started(false), handle(nullptr), pst(overallPeriod * 1000) { + TaskStackSize setStack, TaskPeriod period, + TaskDeadlineMissedFunction dlmFunc_) + : FixedTimeslotTaskBase(period, dlmFunc_), started(false), handle(nullptr) { configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); - // All additional attributes are applied to the object. - this->deadlineMissedFunc = setDeadlineMissedFunc; } -FixedTimeslotTask::~FixedTimeslotTask() {} +FixedTimeslotTask::~FixedTimeslotTask() = default; void FixedTimeslotTask::taskEntryPoint(void* argument) { // The argument is re-interpreted as FixedTimeslotTask. The Task object is // global, so it is found from any place. - FixedTimeslotTask* originalTask(reinterpret_cast(argument)); + auto* originalTask(reinterpret_cast(argument)); /* Task should not start until explicitly requested, * but in FreeRTOS, tasks start as soon as they are created if the scheduler * is running but not if the scheduler is not running. @@ -32,26 +28,18 @@ void FixedTimeslotTask::taskEntryPoint(void* argument) { * can continue */ if (not originalTask->started) { - vTaskSuspend(NULL); + vTaskSuspend(nullptr); } originalTask->taskFunctionality(); #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::debug << "Polling task " << originalTask->handle << " returned from taskFunctionality." << std::endl; +#else + sif::printDebug("Polling task returned from taskFunctionality\n"); #endif } -void FixedTimeslotTask::missedDeadlineCounter() { - FixedTimeslotTask::deadlineMissedCount++; - if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount << " deadlines." - << std::endl; -#endif - } -} - ReturnValue_t FixedTimeslotTask::startTask() { started = true; @@ -60,34 +48,15 @@ ReturnValue_t FixedTimeslotTask::startTask() { vTaskResume(handle); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } -ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep) { - ExecutableObjectIF* handler = ObjectManager::instance()->get(componentId); - if (handler != nullptr) { - pst.addSlot(componentId, slotTimeMs, executionStep, handler, this); - return HasReturnvaluesIF::RETURN_OK; - } - -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "Component " << std::hex << componentId << " not found, not adding it to pst" - << std::endl; -#endif - return HasReturnvaluesIF::RETURN_FAILED; -} - -uint32_t FixedTimeslotTask::getPeriodMs() const { return pst.getLengthMs(); } - -ReturnValue_t FixedTimeslotTask::checkSequence() const { return pst.checkSequence(); } - -void FixedTimeslotTask::taskFunctionality() { +[[noreturn]] void FixedTimeslotTask::taskFunctionality() { // A local iterator for the Polling Sequence Table is created to find the // start time for the first entry. - auto slotListIter = pst.current; + auto slotListIter = pollingSeqTable.current; - pst.intializeSequenceAfterTaskCreation(); + pollingSeqTable.intializeSequenceAfterTaskCreation(); // The start time for the first entry is read. uint32_t intervalMs = slotListIter->pollingTimeMs; @@ -108,10 +77,10 @@ void FixedTimeslotTask::taskFunctionality() { /* Enter the loop that defines the task behavior. */ for (;;) { // The component for this slot is executed and the next one is chosen. - this->pst.executeAndAdvance(); - if (not pst.slotFollowsImmediately()) { + this->pollingSeqTable.executeAndAdvance(); + if (not pollingSeqTable.slotFollowsImmediately()) { // Get the interval till execution of the next slot. - intervalMs = this->pst.getIntervalToPreviousSlotMs(); + intervalMs = this->pollingSeqTable.getIntervalToPreviousSlotMs(); interval = pdMS_TO_TICKS(intervalMs); #if (tskKERNEL_VERSION_MAJOR == 10 && tskKERNEL_VERSION_MINOR >= 4) || tskKERNEL_VERSION_MAJOR > 10 @@ -132,14 +101,14 @@ void FixedTimeslotTask::taskFunctionality() { } void FixedTimeslotTask::handleMissedDeadline() { - if (deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); + if (dlmFunc != nullptr) { + dlmFunc(); } } ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { vTaskDelay(pdMS_TO_TICKS(ms)); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } TaskHandle_t FixedTimeslotTask::getTaskHandle() { return handle; } diff --git a/src/fsfw/osal/freertos/FixedTimeslotTask.h b/src/fsfw/osal/freertos/FixedTimeslotTask.h index 77999d71..53c9a11c 100644 --- a/src/fsfw/osal/freertos/FixedTimeslotTask.h +++ b/src/fsfw/osal/freertos/FixedTimeslotTask.h @@ -4,11 +4,11 @@ #include "FreeRTOS.h" #include "FreeRTOSTaskIF.h" #include "fsfw/tasks/FixedSlotSequence.h" -#include "fsfw/tasks/FixedTimeslotTaskIF.h" -#include "fsfw/tasks/Typedef.h" +#include "fsfw/tasks/FixedTimeslotTaskBase.h" +#include "fsfw/tasks/definitions.h" #include "task.h" -class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF { +class FixedTimeslotTask : public FixedTimeslotTaskBase, public FreeRTOSTaskIF { public: /** * Keep in mind that you need to call before vTaskStartScheduler()! @@ -23,7 +23,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF { * @return Pointer to the newly created task. */ FixedTimeslotTask(TaskName name, TaskPriority setPriority, TaskStackSize setStack, - TaskPeriod overallPeriod, void (*setDeadlineMissedFunc)()); + TaskPeriod overallPeriod, TaskDeadlineMissedFunction dlmFunc); /** * @brief The destructor of the class. @@ -32,26 +32,9 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF { * initialization for the PST and the device handlers. This is done by * calling the PST's destructor. */ - virtual ~FixedTimeslotTask(void); + ~FixedTimeslotTask() override; - ReturnValue_t startTask(void); - /** - * This static function can be used as #deadlineMissedFunc. - * It counts missedDeadlines and prints the number of missed deadlines - * every 10th time. - */ - static void missedDeadlineCounter(); - /** - * A helper variable to count missed deadlines. - */ - static uint32_t deadlineMissedCount; - - ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep) override; - - uint32_t getPeriodMs() const override; - - ReturnValue_t checkSequence() const override; + ReturnValue_t startTask() override; ReturnValue_t sleepFor(uint32_t ms) override; @@ -61,17 +44,6 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF { bool started; TaskHandle_t handle; - FixedSlotSequence pst; - - /** - * @brief This attribute holds a function pointer that is executed when - * a deadline was missed. - * @details - * Another function may be announced to determine the actions to perform - * when a deadline was missed. Currently, only one function for missing - * any deadline is allowed. If not used, it shall be declared NULL. - */ - void (*deadlineMissedFunc)(void); /** * @brief This is the entry point for a new task. * @details @@ -88,7 +60,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF { * It links the functionalities provided by FixedSlotSequence with the * OS's System Calls to keep the timing of the periods. */ - void taskFunctionality(void); + [[noreturn]] void taskFunctionality(); void handleMissedDeadline(); }; diff --git a/src/fsfw/osal/freertos/FreeRTOSTaskIF.h b/src/fsfw/osal/freertos/FreeRTOSTaskIF.h index ad5c9f7f..dbefc6c1 100644 --- a/src/fsfw/osal/freertos/FreeRTOSTaskIF.h +++ b/src/fsfw/osal/freertos/FreeRTOSTaskIF.h @@ -6,11 +6,11 @@ class FreeRTOSTaskIF { public: - virtual ~FreeRTOSTaskIF() {} + virtual ~FreeRTOSTaskIF() = default; virtual TaskHandle_t getTaskHandle() = 0; protected: - bool checkMissedDeadline(const TickType_t xLastWakeTime, const TickType_t interval) { + static bool checkMissedDeadline(const TickType_t xLastWakeTime, const TickType_t interval) { /* Check whether deadline was missed while also taking overflows * into account. Drawing this on paper with a timeline helps to understand * it. */ diff --git a/src/fsfw/osal/freertos/MessageQueue.cpp b/src/fsfw/osal/freertos/MessageQueue.cpp index d1a7f691..e449ef1e 100644 --- a/src/fsfw/osal/freertos/MessageQueue.cpp +++ b/src/fsfw/osal/freertos/MessageQueue.cpp @@ -48,14 +48,14 @@ ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault } return MessageQueueIF::FULL; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { BaseType_t result = xQueueReceive(handle, reinterpret_cast(message->getBuffer()), 0); if (result == pdPASS) { this->last = message->getSender(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { return MessageQueueIF::EMPTY; } @@ -65,7 +65,7 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) { // TODO FreeRTOS does not support flushing partially // Is always successful xQueueReset(handle); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } // static core function to send messages. diff --git a/src/fsfw/osal/freertos/MessageQueue.h b/src/fsfw/osal/freertos/MessageQueue.h index 00dfea68..ee3479aa 100644 --- a/src/fsfw/osal/freertos/MessageQueue.h +++ b/src/fsfw/osal/freertos/MessageQueue.h @@ -2,6 +2,7 @@ #define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_ #include + #include "FreeRTOS.h" #include "TaskManagement.h" #include "fsfw/internalerror/InternalErrorReporterIF.h" diff --git a/src/fsfw/osal/freertos/Mutex.cpp b/src/fsfw/osal/freertos/Mutex.cpp index 1995e1ea..6c264dd6 100644 --- a/src/fsfw/osal/freertos/Mutex.cpp +++ b/src/fsfw/osal/freertos/Mutex.cpp @@ -31,7 +31,7 @@ ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) { BaseType_t returncode = xSemaphoreTake(handle, timeout); if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { return MutexIF::MUTEX_TIMEOUT; } @@ -43,7 +43,7 @@ ReturnValue_t Mutex::unlockMutex() { } BaseType_t returncode = xSemaphoreGive(handle); if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { return MutexIF::CURR_THREAD_DOES_NOT_OWN_MUTEX; } diff --git a/src/fsfw/osal/freertos/PeriodicTask.cpp b/src/fsfw/osal/freertos/PeriodicTask.cpp index d2c46ea8..2b6a94db 100644 --- a/src/fsfw/osal/freertos/PeriodicTask.cpp +++ b/src/fsfw/osal/freertos/PeriodicTask.cpp @@ -5,27 +5,28 @@ #include "fsfw/tasks/ExecutableObjectIF.h" PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack, - TaskPeriod setPeriod, TaskDeadlineMissedFunction deadlineMissedFunc) - : started(false), handle(NULL), period(setPeriod), deadlineMissedFunc(deadlineMissedFunc) { + TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc_) + : PeriodicTaskBase(setPeriod, dlmFunc_), started(false), handle(nullptr) { configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); BaseType_t status = xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); if (status != pdPASS) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "PeriodicTask Insufficient heap memory remaining. " - "Status: " + sif::debug << "PeriodicTask::PeriodicTask Insufficient heap memory remaining. Status: " << status << std::endl; +#else + sif::printDebug("PeriodicTask::PeriodicTask: Insufficient heap memory remaining. Status: %d\n", + status); #endif } } -PeriodicTask::~PeriodicTask(void) { - // Do not delete objects, we were responsible for ptrs only. -} +// Do not delete objects, we were responsible for ptrs only. +PeriodicTask::~PeriodicTask() = default; void PeriodicTask::taskEntryPoint(void* argument) { // The argument is re-interpreted as PeriodicTask. The Task object is // global, so it is found from any place. - PeriodicTask* originalTask(reinterpret_cast(argument)); + auto* originalTask(reinterpret_cast(argument)); /* Task should not start until explicitly requested, * but in FreeRTOS, tasks start as soon as they are created if the scheduler * is running but not if the scheduler is not running. @@ -36,7 +37,7 @@ void PeriodicTask::taskEntryPoint(void* argument) { * can continue */ if (not originalTask->started) { - vTaskSuspend(NULL); + vTaskSuspend(nullptr); } originalTask->taskFunctionality(); @@ -54,21 +55,19 @@ ReturnValue_t PeriodicTask::startTask() { vTaskResume(handle); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { vTaskDelay(pdMS_TO_TICKS(ms)); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } -void PeriodicTask::taskFunctionality() { +[[noreturn]] void PeriodicTask::taskFunctionality() { TickType_t xLastWakeTime; const TickType_t xPeriod = pdMS_TO_TICKS(this->period * 1000.); - for (auto const& object : objectList) { - object->initializeAfterTaskCreation(); - } + initObjsAfterTaskCreation(); /* The xLastWakeTime variable needs to be initialized with the current tick count. Note that this is the only time the variable is written to @@ -77,8 +76,8 @@ void PeriodicTask::taskFunctionality() { xLastWakeTime = xTaskGetTickCount(); /* Enter the loop that defines the task behavior. */ for (;;) { - for (auto const& object : objectList) { - object->performOperation(); + for (auto const& objectPair : objectList) { + objectPair.first->performOperation(objectPair.second); } #if (tskKERNEL_VERSION_MAJOR == 10 && tskKERNEL_VERSION_MINOR >= 4) || tskKERNEL_VERSION_MAJOR > 10 @@ -95,32 +94,10 @@ void PeriodicTask::taskFunctionality() { } } -ReturnValue_t PeriodicTask::addComponent(object_id_t object) { - ExecutableObjectIF* newObject = ObjectManager::instance()->get(object); - return addComponent(newObject); -} - -ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) { - if (object == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PeriodicTask::addComponent: Invalid object. Make sure" - "it implement ExecutableObjectIF" - << std::endl; -#endif - return HasReturnvaluesIF::RETURN_FAILED; - } - objectList.push_back(object); - object->setTaskIF(this); - - return HasReturnvaluesIF::RETURN_OK; -} - -uint32_t PeriodicTask::getPeriodMs() const { return period * 1000; } - TaskHandle_t PeriodicTask::getTaskHandle() { return handle; } void PeriodicTask::handleMissedDeadline() { - if (deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); + if (dlmFunc != nullptr) { + dlmFunc(); } } diff --git a/src/fsfw/osal/freertos/PeriodicTask.h b/src/fsfw/osal/freertos/PeriodicTask.h index fc8e9092..c3fb9d70 100644 --- a/src/fsfw/osal/freertos/PeriodicTask.h +++ b/src/fsfw/osal/freertos/PeriodicTask.h @@ -6,8 +6,8 @@ #include "FreeRTOS.h" #include "FreeRTOSTaskIF.h" #include "fsfw/objectmanager/ObjectManagerIF.h" -#include "fsfw/tasks/PeriodicTaskIF.h" -#include "fsfw/tasks/Typedef.h" +#include "fsfw/tasks/PeriodicTaskBase.h" +#include "fsfw/tasks/definitions.h" #include "task.h" class ExecutableObjectIF; @@ -17,7 +17,7 @@ class ExecutableObjectIF; * periodic activities of multiple objects. * @ingroup task_handling */ -class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF { +class PeriodicTask : public PeriodicTaskBase, public FreeRTOSTaskIF { public: /** * Keep in Mind that you need to call before this vTaskStartScheduler()! @@ -43,7 +43,7 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF { * @brief Currently, the executed object's lifetime is not coupled with * the task object's lifetime, so the destructor is empty. */ - virtual ~PeriodicTask(void); + ~PeriodicTask() override; /** * @brief The method to start the task. @@ -53,27 +53,6 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF { * to the system call. */ ReturnValue_t startTask() override; - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object Id of the object to add. - * @return - * -@c RETURN_OK on success - * -@c RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(object_id_t object) override; - - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object Id of the object to add. - * @return - * -@c RETURN_OK on success - * -@c RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(ExecutableObjectIF* object) override; - - uint32_t getPeriodMs() const override; ReturnValue_t sleepFor(uint32_t ms) override; @@ -83,28 +62,6 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF { bool started; TaskHandle_t handle; - //! Typedef for the List of objects. - typedef std::vector ObjectList; - /** - * @brief This attribute holds a list of objects to be executed. - */ - ObjectList objectList; - /** - * @brief The period of the task. - * @details - * The period determines the frequency of the task's execution. - * It is expressed in clock ticks. - */ - TaskPeriod period; - /** - * @brief The pointer to the deadline-missed function. - * @details - * This pointer stores the function that is executed if the task's deadline - * is missed so each may react individually on a timing failure. - * The pointer may be NULL, then nothing happens on missing the deadline. - * The deadline is equal to the next execution of the periodic task. - */ - void (*deadlineMissedFunc)(void); /** * @brief This is the function executed in the new task's context. * @details @@ -125,7 +82,7 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF { * the next period. * On missing the deadline, the deadlineMissedFunction is executed. */ - void taskFunctionality(void); + [[noreturn]] void taskFunctionality(); void handleMissedDeadline(); }; diff --git a/src/fsfw/osal/freertos/QueueMapManager.cpp b/src/fsfw/osal/freertos/QueueMapManager.cpp index cb3afb1c..172d9dff 100644 --- a/src/fsfw/osal/freertos/QueueMapManager.cpp +++ b/src/fsfw/osal/freertos/QueueMapManager.cpp @@ -34,12 +34,12 @@ ReturnValue_t QueueMapManager::addMessageQueue(QueueHandle_t queue, MessageQueue "QueueMapManager::addMessageQueue This ID is already " "inside the map!\n"); #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (id != nullptr) { *id = currentId; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } QueueHandle_t QueueMapManager::getMessageQueue(MessageQueueId_t messageQueueId) const { diff --git a/src/fsfw/osal/freertos/TaskFactory.cpp b/src/fsfw/osal/freertos/TaskFactory.cpp index 7acd812f..688069cf 100644 --- a/src/fsfw/osal/freertos/TaskFactory.cpp +++ b/src/fsfw/osal/freertos/TaskFactory.cpp @@ -2,7 +2,7 @@ #include "fsfw/osal/freertos/FixedTimeslotTask.h" #include "fsfw/osal/freertos/PeriodicTask.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); @@ -31,16 +31,16 @@ ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { if (task == nullptr) { // delete self vTaskDelete(nullptr); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { // TODO not implemented - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } ReturnValue_t TaskFactory::delayTask(uint32_t delayMs) { vTaskDelay(pdMS_TO_TICKS(delayMs)); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void TaskFactory::printMissedDeadline() { diff --git a/src/fsfw/osal/freertos/TaskManagement.h b/src/fsfw/osal/freertos/TaskManagement.h index 825d8865..6dec15cc 100644 --- a/src/fsfw/osal/freertos/TaskManagement.h +++ b/src/fsfw/osal/freertos/TaskManagement.h @@ -3,7 +3,7 @@ #include -#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../returnvalues/returnvalue.h" #include "FreeRTOS.h" #include "task.h" diff --git a/src/fsfw/osal/host/CMakeLists.txt b/src/fsfw/osal/host/CMakeLists.txt index 2d29ce5d..95ab25c9 100644 --- a/src/fsfw/osal/host/CMakeLists.txt +++ b/src/fsfw/osal/host/CMakeLists.txt @@ -1,24 +1,23 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - Clock.cpp - FixedTimeslotTask.cpp - MessageQueue.cpp - Mutex.cpp - MutexFactory.cpp - PeriodicTask.cpp - QueueFactory.cpp - QueueMapManager.cpp - SemaphoreFactory.cpp - TaskFactory.cpp - taskHelpers.cpp -) +target_sources( + ${LIB_FSFW_NAME} + PRIVATE Clock.cpp + FixedTimeslotTask.cpp + MessageQueue.cpp + Mutex.cpp + MutexFactory.cpp + PeriodicTask.cpp + QueueFactory.cpp + QueueMapManager.cpp + SemaphoreFactory.cpp + TaskFactory.cpp + taskHelpers.cpp) if(UNIX) - find_package(Threads REQUIRED) - - target_link_libraries(${LIB_FSFW_NAME} - PRIVATE - rt - ${CMAKE_THREAD_LIBS_INIT} - ) -endif() \ No newline at end of file + find_package(Threads REQUIRED) + + target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${CMAKE_THREAD_LIBS_INIT}) + if(NOT APPLE) + target_link_libraries(${LIB_FSFW_NAME} PRIVATE rt) + endif() + +endif() diff --git a/src/fsfw/osal/host/Clock.cpp b/src/fsfw/osal/host/Clock.cpp index 19e120b3..dbf6529c 100644 --- a/src/fsfw/osal/host/Clock.cpp +++ b/src/fsfw/osal/host/Clock.cpp @@ -8,6 +8,7 @@ #if defined(PLATFORM_WIN) #include +#define timegm _mkgmtime #elif defined(PLATFORM_UNIX) #include #endif @@ -32,7 +33,7 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { #else sif::printWarning("Clock::setClock: Not implemented for host OSAL\n"); #endif - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::setClock(const timeval* time) { @@ -43,7 +44,7 @@ ReturnValue_t Clock::setClock(const timeval* time) { #else sif::printWarning("Clock::setClock: Not implemented for host OSAL\n"); #endif - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::getClock_timeval(timeval* time) { @@ -54,33 +55,33 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) { time->tv_sec = std::chrono::duration_cast(epoch).count(); auto fraction = now - secondsChrono; time->tv_usec = std::chrono::duration_cast(fraction).count(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; #elif defined(PLATFORM_UNIX) timespec timeUnix; int status = clock_gettime(CLOCK_REALTIME, &timeUnix); if (status != 0) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } time->tv_sec = timeUnix.tv_sec; time->tv_usec = timeUnix.tv_nsec / 1000.0; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; #else #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl; #else sif::printWarning("Clock::getUptime: Not implemented for found OS!\n"); #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; #endif } ReturnValue_t Clock::getClock_usecs(uint64_t* time) { if (time == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } using namespace std::chrono; *time = duration_cast(system_clock::now().time_since_epoch()).count(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } timeval Clock::getUptime() { @@ -108,13 +109,13 @@ timeval Clock::getUptime() { ReturnValue_t Clock::getUptime(timeval* uptime) { *uptime = getUptime(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { timeval uptime = getUptime(); *uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { @@ -126,7 +127,7 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { auto fraction = now - seconds; time_t tt = SystemClock::to_time_t(now); ReturnValue_t result = checkOrCreateClockMutex(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } MutexGuard helper(timeMutex); @@ -142,11 +143,11 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { time->second = timeInfo->tm_sec; auto usecond = std::chrono::duration_cast(fraction); time->usecond = usecond.count(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) { - struct tm time_tm; + struct tm time_tm {}; time_tm.tm_year = from->year - 1900; time_tm.tm_mon = from->month - 1; @@ -162,10 +163,10 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to->tv_sec = seconds; to->tv_usec = from->usecond; // Fails in 2038.. - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { *JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/src/fsfw/osal/host/FixedTimeslotTask.cpp b/src/fsfw/osal/host/FixedTimeslotTask.cpp index 07853938..edb2d52d 100644 --- a/src/fsfw/osal/host/FixedTimeslotTask.cpp +++ b/src/fsfw/osal/host/FixedTimeslotTask.cpp @@ -3,9 +3,7 @@ #include #include -#include "fsfw/ipc/MutexFactory.h" #include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/osal/host/FixedTimeslotTask.h" #include "fsfw/osal/host/Mutex.h" #include "fsfw/osal/host/taskHelpers.h" #include "fsfw/platform.h" @@ -22,12 +20,8 @@ FixedTimeslotTask::FixedTimeslotTask(const char* name, TaskPriority setPriority, TaskStackSize setStack, TaskPeriod setPeriod, - void (*setDeadlineMissedFunc)()) - : started(false), - pollingSeqTable(setPeriod * 1000), - taskName(name), - period(setPeriod), - deadlineMissedFunc(setDeadlineMissedFunc) { + TaskDeadlineMissedFunction dlmFunc_) + : FixedTimeslotTaskBase(setPeriod, dlmFunc_), started(false), taskName(name) { // It is propably possible to set task priorities by using the native // task handles for Windows / Linux mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this); @@ -39,7 +33,7 @@ FixedTimeslotTask::FixedTimeslotTask(const char* name, TaskPriority setPriority, tasks::insertTaskName(mainThread.get_id(), taskName); } -FixedTimeslotTask::~FixedTimeslotTask(void) { +FixedTimeslotTask::~FixedTimeslotTask() { // Do not delete objects, we were responsible for ptrs only. terminateThread = true; if (mainThread.joinable()) { @@ -48,7 +42,7 @@ FixedTimeslotTask::~FixedTimeslotTask(void) { } void FixedTimeslotTask::taskEntryPoint(void* argument) { - FixedTimeslotTask* originalTask(reinterpret_cast(argument)); + auto* originalTask(reinterpret_cast(argument)); if (not originalTask->started) { // we have to suspend/block here until the task is started. @@ -72,16 +66,18 @@ ReturnValue_t FixedTimeslotTask::startTask() { std::lock_guard lock(initMutex); initCondition.notify_one(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { std::this_thread::sleep_for(std::chrono::milliseconds(ms)); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void FixedTimeslotTask::taskFunctionality() { - pollingSeqTable.intializeSequenceAfterTaskCreation(); + ReturnValue_t result = pollingSeqTable.intializeSequenceAfterTaskCreation(); + // Ignore returnvalue for now + static_cast(result); // A local iterator for the Polling Sequence Table is created to // find the start time for the first entry. @@ -106,37 +102,15 @@ void FixedTimeslotTask::taskFunctionality() { // we need to wait before executing the current slot // this gives us the time to wait: interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs()); - delayForInterval(¤tStartTime, interval); - // TODO deadline missed check + if (not delayForInterval(¤tStartTime, interval)) { + if (dlmFunc != nullptr) { + dlmFunc(); + } + } } } } -ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep) { - ExecutableObjectIF* executableObject = - ObjectManager::instance()->get(componentId); - if (executableObject != nullptr) { - pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, executableObject, this); - return HasReturnvaluesIF::RETURN_OK; - } - -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "Component " << std::hex << "0x" << componentId - << "not found, " - "not adding it to PST.." - << std::dec << std::endl; -#else - sif::printError("Component 0x%08x not found, not adding it to PST..\n", - static_cast(componentId)); -#endif - return HasReturnvaluesIF::RETURN_FAILED; -} - -ReturnValue_t FixedTimeslotTask::checkSequence() const { return pollingSeqTable.checkSequence(); } - -uint32_t FixedTimeslotTask::getPeriodMs() const { return period * 1000; } - bool FixedTimeslotTask::delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval) { bool shouldDelay = false; // Get current wakeup time diff --git a/src/fsfw/osal/host/FixedTimeslotTask.h b/src/fsfw/osal/host/FixedTimeslotTask.h index cdbc6f23..95159ab8 100644 --- a/src/fsfw/osal/host/FixedTimeslotTask.h +++ b/src/fsfw/osal/host/FixedTimeslotTask.h @@ -5,11 +5,12 @@ #include #include #include +#include -#include "../../objectmanager/ObjectManagerIF.h" -#include "../../tasks/FixedSlotSequence.h" -#include "../../tasks/FixedTimeslotTaskIF.h" -#include "../../tasks/Typedef.h" +#include "fsfw/objectmanager/ObjectManagerIF.h" +#include "fsfw/tasks/FixedSlotSequence.h" +#include "fsfw/tasks/FixedTimeslotTaskBase.h" +#include "fsfw/tasks/definitions.h" class ExecutableObjectIF; @@ -19,7 +20,7 @@ class ExecutableObjectIF; * @details * @ingroup task_handling */ -class FixedTimeslotTask : public FixedTimeslotTaskIF { +class FixedTimeslotTask : public FixedTimeslotTaskBase { public: /** * @brief Standard constructor of the class. @@ -39,7 +40,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { * @brief Currently, the executed object's lifetime is not coupled with * the task object's lifetime, so the destructor is empty. */ - virtual ~FixedTimeslotTask(void); + ~FixedTimeslotTask() override; /** * @brief The method to start the task. @@ -48,56 +49,22 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { * The address of the task object is passed as an argument * to the system call. */ - ReturnValue_t startTask(void); + ReturnValue_t startTask() override; - /** - * Add timeslot to the polling sequence table. - * @param componentId - * @param slotTimeMs - * @param executionStep - * @return - */ - ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep); - - ReturnValue_t checkSequence() const override; - - uint32_t getPeriodMs() const; - - ReturnValue_t sleepFor(uint32_t ms); + ReturnValue_t sleepFor(uint32_t ms) override; protected: using chron_ms = std::chrono::milliseconds; bool started; - //!< Typedef for the List of objects. - typedef std::vector ObjectList; + std::thread mainThread; std::atomic terminateThread{false}; - //! Polling sequence table which contains the object to execute - //! and information like the timeslots and the passed execution step. - FixedSlotSequence pollingSeqTable; - std::condition_variable initCondition; std::mutex initMutex; std::string taskName; - /** - * @brief The period of the task. - * @details - * The period determines the frequency of the task's execution. - * It is expressed in clock ticks. - */ - TaskPeriod period; - /** - * @brief The pointer to the deadline-missed function. - * @details - * This pointer stores the function that is executed if the task's deadline - * is missed. So, each may react individually on a timing failure. - * The pointer may be NULL, then nothing happens on missing the deadline. - * The deadline is equal to the next execution of the periodic task. - */ - void (*deadlineMissedFunc)(void); /** * @brief This is the function executed in the new task's context. * @details @@ -117,9 +84,9 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { * the checkAndRestartPeriod system call blocks the task until the next * period. On missing the deadline, the deadlineMissedFunction is executed. */ - void taskFunctionality(void); + void taskFunctionality(); - bool delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval); + static bool delayForInterval(chron_ms* previousWakeTimeMs, chron_ms interval); }; #endif /* FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ */ diff --git a/src/fsfw/osal/host/MessageQueue.cpp b/src/fsfw/osal/host/MessageQueue.cpp index d0a12850..a4781cdb 100644 --- a/src/fsfw/osal/host/MessageQueue.cpp +++ b/src/fsfw/osal/host/MessageQueue.cpp @@ -14,7 +14,7 @@ MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* a messageDepth(messageDepth) { queueLock = MutexFactory::instance()->createMutex(); auto result = QueueMapManager::instance()->addMessageQueue(this, &id); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "MessageQueue::MessageQueue: Could not be created" << std::endl; #else @@ -40,14 +40,14 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { messageQueue.pop(); // The last partner is the first uint32_t field in the message this->last = message->getSender(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t MessageQueue::flush(uint32_t* count) { *count = messageQueue.size(); // Clears the queue. messageQueue = std::queue>(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } // static core function to send messages. @@ -56,20 +56,20 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, MessageQueueId_t sentFrom, bool ignoreFault) { if (message == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } message->setSender(sentFrom); if (message->getMessageSize() > message->getMaximumMessageSize()) { // Actually, this should never happen or an error will be emitted // in MessageQueueMessage. // But I will still return a failure here. - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - MessageQueue* targetQueue = + auto* targetQueue = dynamic_cast(QueueMapManager::instance()->getMessageQueue(sendTo)); if (targetQueue == nullptr) { if (not ignoreFault) { - InternalErrorReporterIF* internalErrorReporter = + auto* internalErrorReporter = ObjectManager::instance()->get(objects::INTERNAL_ERROR_REPORTER); if (internalErrorReporter != nullptr) { internalErrorReporter->queueMessageNotSent(); @@ -84,7 +84,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, message->getMaximumMessageSize()); } else { if (not ignoreFault) { - InternalErrorReporterIF* internalErrorReporter = + auto* internalErrorReporter = ObjectManager::instance()->get(objects::INTERNAL_ERROR_REPORTER); if (internalErrorReporter != nullptr) { internalErrorReporter->queueMessageNotSent(); @@ -92,7 +92,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, } return MessageQueueIF::FULL; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t MessageQueue::lockQueue(MutexIF::TimeoutType timeoutType, dur_millis_t lockTimeout) { diff --git a/src/fsfw/osal/host/MessageQueue.h b/src/fsfw/osal/host/MessageQueue.h index bb4f26a1..7d60fb8e 100644 --- a/src/fsfw/osal/host/MessageQueue.h +++ b/src/fsfw/osal/host/MessageQueue.h @@ -1,17 +1,17 @@ #ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ #define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ -#include "fsfw/ipc/MessageQueueBase.h" +#include +#include + #include "fsfw/internalerror/InternalErrorReporterIF.h" +#include "fsfw/ipc/MessageQueueBase.h" #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" -#include -#include - /** * @brief This class manages sending and receiving of * message queue messages. @@ -68,7 +68,7 @@ class MessageQueue : public MessageQueueBase { * @details This is accomplished by using the delete call provided * by the operating system. */ - virtual ~MessageQueue(); + ~MessageQueue() override; // Implement non-generic MessageQueueIF functions not handled by MessageQueueBase virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, @@ -111,8 +111,6 @@ class MessageQueue : public MessageQueueBase { size_t messageDepth = 0; MutexIF* queueLock; - - MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE; }; #endif /* FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ */ diff --git a/src/fsfw/osal/host/Mutex.cpp b/src/fsfw/osal/host/Mutex.cpp index 4b7a9582..2b67c7b5 100644 --- a/src/fsfw/osal/host/Mutex.cpp +++ b/src/fsfw/osal/host/Mutex.cpp @@ -7,15 +7,15 @@ Mutex::Mutex() {} ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) { if (timeoutType == TimeoutType::BLOCKING) { mutex.lock(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else if (timeoutType == TimeoutType::POLLING) { if (mutex.try_lock()) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } } else if (timeoutType == TimeoutType::WAITING) { auto chronoMs = std::chrono::milliseconds(timeoutMs); if (mutex.try_lock_for(chronoMs)) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } } return MutexIF::MUTEX_TIMEOUT; @@ -23,7 +23,7 @@ ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) { ReturnValue_t Mutex::unlockMutex() { mutex.unlock(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } std::timed_mutex* Mutex::getMutexHandle() { return &mutex; } diff --git a/src/fsfw/osal/host/PeriodicTask.cpp b/src/fsfw/osal/host/PeriodicTask.cpp index cdcfafa6..e16aead0 100644 --- a/src/fsfw/osal/host/PeriodicTask.cpp +++ b/src/fsfw/osal/host/PeriodicTask.cpp @@ -3,13 +3,10 @@ #include #include -#include "fsfw/ipc/MutexFactory.h" -#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/osal/host/Mutex.h" #include "fsfw/osal/host/taskHelpers.h" #include "fsfw/platform.h" #include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tasks/ExecutableObjectIF.h" #if defined(PLATFORM_WIN) #include @@ -20,8 +17,8 @@ #endif PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack, - TaskPeriod setPeriod, void (*setDeadlineMissedFunc)()) - : started(false), taskName(name), period(setPeriod), deadlineMissedFunc(setDeadlineMissedFunc) { + TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc_) + : PeriodicTaskBase(setPeriod, dlmFunc_), started(false), taskName(name) { // It is probably possible to set task priorities by using the native // task handles for Windows / Linux mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this); @@ -33,7 +30,7 @@ PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStack tasks::insertTaskName(mainThread.get_id(), taskName); } -PeriodicTask::~PeriodicTask(void) { +PeriodicTask::~PeriodicTask() { // Do not delete objects, we were responsible for ptrs only. terminateThread = true; if (mainThread.joinable()) { @@ -42,7 +39,7 @@ PeriodicTask::~PeriodicTask(void) { } void PeriodicTask::taskEntryPoint(void* argument) { - PeriodicTask* originalTask(reinterpret_cast(argument)); + auto* originalTask(reinterpret_cast(argument)); if (not originalTask->started) { // we have to suspend/block here until the task is started. @@ -66,56 +63,36 @@ ReturnValue_t PeriodicTask::startTask() { std::lock_guard lock(initMutex); initCondition.notify_one(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { std::this_thread::sleep_for(std::chrono::milliseconds(ms)); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void PeriodicTask::taskFunctionality() { - for (const auto& object : objectList) { - object->initializeAfterTaskCreation(); - } + initObjsAfterTaskCreation(); std::chrono::milliseconds periodChrono(static_cast(period * 1000)); auto currentStartTime{std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch())}; - auto nextStartTime{currentStartTime}; - /* Enter the loop that defines the task behavior. */ for (;;) { if (terminateThread.load()) { break; } - for (const auto& object : objectList) { - object->performOperation(); + for (const auto& objectPair : objectList) { + objectPair.first->performOperation(objectPair.second); } if (not delayForInterval(¤tStartTime, periodChrono)) { - if (deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); + if (dlmFunc != nullptr) { + this->dlmFunc(); } } } } -ReturnValue_t PeriodicTask::addComponent(object_id_t object) { - ExecutableObjectIF* newObject = ObjectManager::instance()->get(object); - return addComponent(newObject); -} - -ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) { - if (object == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - object->setTaskIF(this); - objectList.push_back(object); - return HasReturnvaluesIF::RETURN_OK; -} - -uint32_t PeriodicTask::getPeriodMs() const { return period * 1000; } - bool PeriodicTask::delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval) { bool shouldDelay = false; // Get current wakeup time diff --git a/src/fsfw/osal/host/PeriodicTask.h b/src/fsfw/osal/host/PeriodicTask.h index 6c4d5e8b..82ec70c0 100644 --- a/src/fsfw/osal/host/PeriodicTask.h +++ b/src/fsfw/osal/host/PeriodicTask.h @@ -5,10 +5,11 @@ #include #include #include +#include -#include "../../objectmanager/ObjectManagerIF.h" -#include "../../tasks/PeriodicTaskIF.h" -#include "../../tasks/Typedef.h" +#include "fsfw/objectmanager/ObjectManagerIF.h" +#include "fsfw/tasks/PeriodicTaskBase.h" +#include "fsfw/tasks/definitions.h" class ExecutableObjectIF; @@ -19,7 +20,7 @@ class ExecutableObjectIF; * * @ingroup task_handling */ -class PeriodicTask : public PeriodicTaskIF { +class PeriodicTask : public PeriodicTaskBase { public: /** * @brief Standard constructor of the class. @@ -34,12 +35,12 @@ class PeriodicTask : public PeriodicTaskIF { * assigned. */ PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack, - TaskPeriod setPeriod, void (*setDeadlineMissedFunc)()); + TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc); /** * @brief Currently, the executed object's lifetime is not coupled with * the task object's lifetime, so the destructor is empty. */ - virtual ~PeriodicTask(void); + ~PeriodicTask() override; /** * @brief The method to start the task. @@ -48,63 +49,20 @@ class PeriodicTask : public PeriodicTaskIF { * The address of the task object is passed as an argument * to the system call. */ - ReturnValue_t startTask(void); - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object Id of the object to add. - * @return - * -@c RETURN_OK on success - * -@c RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(object_id_t object); + ReturnValue_t startTask() override; - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object pointer to the object to add. - * @return - * -@c RETURN_OK on success - * -@c RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(ExecutableObjectIF* object); - - uint32_t getPeriodMs() const; - - ReturnValue_t sleepFor(uint32_t ms); + ReturnValue_t sleepFor(uint32_t ms) override; protected: using chron_ms = std::chrono::milliseconds; bool started; - //!< Typedef for the List of objects. - typedef std::vector ObjectList; std::thread mainThread; std::atomic terminateThread{false}; - /** - * @brief This attribute holds a list of objects to be executed. - */ - ObjectList objectList; - std::condition_variable initCondition; std::mutex initMutex; std::string taskName; - /** - * @brief The period of the task. - * @details - * The period determines the frequency of the task's execution. - * It is expressed in clock ticks. - */ - TaskPeriod period; - /** - * @brief The pointer to the deadline-missed function. - * @details - * This pointer stores the function that is executed if the task's deadline - * is missed. So, each may react individually on a timing failure. - * The pointer may be NULL, then nothing happens on missing the deadline. - * The deadline is equal to the next execution of the periodic task. - */ - void (*deadlineMissedFunc)(void); + /** * @brief This is the function executed in the new task's context. * @details @@ -124,9 +82,9 @@ class PeriodicTask : public PeriodicTaskIF { * the checkAndRestartPeriod system call blocks the task until the next * period. On missing the deadline, the deadlineMissedFunction is executed. */ - void taskFunctionality(void); + void taskFunctionality(); - bool delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval); + static bool delayForInterval(chron_ms* previousWakeTimeMs, chron_ms interval); }; -#endif /* PERIODICTASK_H_ */ +#endif /* FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ */ diff --git a/src/fsfw/osal/host/QueueFactory.cpp b/src/fsfw/osal/host/QueueFactory.cpp index 732892ca..e2d83fd4 100644 --- a/src/fsfw/osal/host/QueueFactory.cpp +++ b/src/fsfw/osal/host/QueueFactory.cpp @@ -13,7 +13,6 @@ ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message, MessageQueueId_t sentFrom, bool ignoreFault) { return MessageQueue::sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault); - return HasReturnvaluesIF::RETURN_OK; } QueueFactory* QueueFactory::instance() { @@ -23,9 +22,9 @@ QueueFactory* QueueFactory::instance() { return factoryInstance; } -QueueFactory::QueueFactory() {} +QueueFactory::QueueFactory() = default; -QueueFactory::~QueueFactory() {} +QueueFactory::~QueueFactory() = default; MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs* args) { diff --git a/src/fsfw/osal/host/QueueMapManager.cpp b/src/fsfw/osal/host/QueueMapManager.cpp index 72c70baa..d7efb0dd 100644 --- a/src/fsfw/osal/host/QueueMapManager.cpp +++ b/src/fsfw/osal/host/QueueMapManager.cpp @@ -39,12 +39,12 @@ ReturnValue_t QueueMapManager::addMessageQueue(MessageQueueIF* queueToInsert, "QueueMapManager::addMessageQueue This ID is already " "inside the map!\n"); #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (id != nullptr) { *id = currentId; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } MessageQueueIF* QueueMapManager::getMessageQueue(MessageQueueId_t messageQueueId) const { @@ -54,7 +54,7 @@ MessageQueueIF* QueueMapManager::getMessageQueue(MessageQueueId_t messageQueueId } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "QueueMapManager::getQueueHandle: The ID " << messageQueueId - << " does not exists in the map!" << std::endl; + << " does not exist in the map" << std::endl; #else sif::printWarning("QueueMapManager::getQueueHandle: The ID %d does not exist in the map!\n", messageQueueId); diff --git a/src/fsfw/osal/host/TaskFactory.cpp b/src/fsfw/osal/host/TaskFactory.cpp index 6e74fd57..0a27241b 100644 --- a/src/fsfw/osal/host/TaskFactory.cpp +++ b/src/fsfw/osal/host/TaskFactory.cpp @@ -5,7 +5,7 @@ #include "fsfw/osal/host/FixedTimeslotTask.h" #include "fsfw/osal/host/PeriodicTask.h" #include "fsfw/osal/host/taskHelpers.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/tasks/PeriodicTaskIF.h" @@ -14,9 +14,9 @@ TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); // Not used for the host implementation for now because C++ thread abstraction is used const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0; -TaskFactory::TaskFactory() {} +TaskFactory::TaskFactory() = default; -TaskFactory::~TaskFactory() {} +TaskFactory::~TaskFactory() = default; TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; } @@ -37,12 +37,12 @@ FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask( ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { // This might block for some time! delete task; - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } ReturnValue_t TaskFactory::delayTask(uint32_t delayMs) { std::this_thread::sleep_for(std::chrono::milliseconds(delayMs)); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void TaskFactory::printMissedDeadline() { diff --git a/src/fsfw/osal/host/taskHelpers.cpp b/src/fsfw/osal/host/taskHelpers.cpp index aba2948a..e5a931ed 100644 --- a/src/fsfw/osal/host/taskHelpers.cpp +++ b/src/fsfw/osal/host/taskHelpers.cpp @@ -6,13 +6,13 @@ std::mutex nameMapLock; std::map taskNameMap; -ReturnValue_t tasks::insertTaskName(std::thread::id threadId, std::string taskName) { +ReturnValue_t tasks::insertTaskName(std::thread::id threadId, const std::string& taskName) { std::lock_guard lg(nameMapLock); auto returnPair = taskNameMap.emplace(threadId, taskName); if (not returnPair.second) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } std::string tasks::getTaskName(std::thread::id threadId) { diff --git a/src/fsfw/osal/host/taskHelpers.h b/src/fsfw/osal/host/taskHelpers.h index cf553011..35988332 100644 --- a/src/fsfw/osal/host/taskHelpers.h +++ b/src/fsfw/osal/host/taskHelpers.h @@ -1,13 +1,14 @@ #ifndef FSFW_OSAL_HOST_TASKHELPERS_H_ #define FSFW_OSAL_HOST_TASKHELPERS_H_ -#include +#include #include +#include namespace tasks { -ReturnValue_t insertTaskName(std::thread::id threadId, std::string taskName); +ReturnValue_t insertTaskName(std::thread::id threadId, const std::string& taskName); std::string getTaskName(std::thread::id threadId); } // namespace tasks diff --git a/src/fsfw/osal/linux/BinarySemaphore.cpp b/src/fsfw/osal/linux/BinarySemaphore.cpp index 4fb67f15..9b954d6c 100644 --- a/src/fsfw/osal/linux/BinarySemaphore.cpp +++ b/src/fsfw/osal/linux/BinarySemaphore.cpp @@ -43,7 +43,7 @@ ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, uint32_t timeout } } if (result == 0) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } switch (errno) { @@ -62,10 +62,10 @@ ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, uint32_t timeout case (EINTR): { // Call was interrupted by signal handler utility::printUnixErrorGeneric(CLASS_NAME, "acquire", "EINTR"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -73,13 +73,13 @@ ReturnValue_t BinarySemaphore::release() { return BinarySemaphore::release(&this ReturnValue_t BinarySemaphore::release(sem_t* handle) { ReturnValue_t countResult = checkCount(handle, 1); - if (countResult != HasReturnvaluesIF::RETURN_OK) { + if (countResult != returnvalue::OK) { return countResult; } int result = sem_post(handle); if (result == 0) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } switch (errno) { @@ -91,10 +91,10 @@ ReturnValue_t BinarySemaphore::release(sem_t* handle) { case (EOVERFLOW): { // SEM_MAX_VALUE overflow. This should never happen utility::printUnixErrorGeneric(CLASS_NAME, "release", "EOVERFLOW"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -145,9 +145,9 @@ ReturnValue_t BinarySemaphore::checkCount(sem_t* handle, uint8_t maxCount) { // This is a config error use lightweight printf is this is called // from an interrupt printf("BinarySemaphore::release: Value of binary semaphore greater than 1!\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } return SemaphoreIF::SEMAPHORE_NOT_OWNED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/src/fsfw/osal/linux/BinarySemaphore.h b/src/fsfw/osal/linux/BinarySemaphore.h index f75618a6..fe2c0db0 100644 --- a/src/fsfw/osal/linux/BinarySemaphore.h +++ b/src/fsfw/osal/linux/BinarySemaphore.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ #define FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ -#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../returnvalues/returnvalue.h" #include "../../tasks/SemaphoreIF.h" extern "C" { @@ -17,7 +17,7 @@ extern "C" { * @author R. Mueller * @ingroup osal */ -class BinarySemaphore : public SemaphoreIF, public HasReturnvaluesIF { +class BinarySemaphore : public SemaphoreIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; @@ -45,7 +45,7 @@ class BinarySemaphore : public SemaphoreIF, public HasReturnvaluesIF { * for a maximum of #timeoutMs or until the semaphore is given back, * for example by an ISR or another task. * @param timeoutMs - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout */ ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, @@ -53,7 +53,7 @@ class BinarySemaphore : public SemaphoreIF, public HasReturnvaluesIF { /** * Release the binary semaphore. - * @return -@c RETURN_OK on success + * @return -@c returnvalue::OK on success * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is * already available. */ diff --git a/src/fsfw/osal/linux/CMakeLists.txt b/src/fsfw/osal/linux/CMakeLists.txt index 679b2931..72a62b86 100644 --- a/src/fsfw/osal/linux/CMakeLists.txt +++ b/src/fsfw/osal/linux/CMakeLists.txt @@ -1,29 +1,25 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - Clock.cpp - BinarySemaphore.cpp - CountingSemaphore.cpp - FixedTimeslotTask.cpp - InternalErrorCodes.cpp - MessageQueue.cpp - Mutex.cpp - MutexFactory.cpp - PeriodicPosixTask.cpp - PosixThread.cpp - QueueFactory.cpp - SemaphoreFactory.cpp - TaskFactory.cpp - tcpipHelpers.cpp - unixUtility.cpp -) +target_sources( + ${LIB_FSFW_NAME} + PRIVATE Clock.cpp + BinarySemaphore.cpp + CountingSemaphore.cpp + FixedTimeslotTask.cpp + InternalErrorCodes.cpp + MessageQueue.cpp + Mutex.cpp + MutexFactory.cpp + PeriodicPosixTask.cpp + PosixThread.cpp + QueueFactory.cpp + SemaphoreFactory.cpp + TaskFactory.cpp + tcpipHelpers.cpp + unixUtility.cpp) find_package(Threads REQUIRED) -target_link_libraries(${LIB_FSFW_NAME} PRIVATE - ${CMAKE_THREAD_LIBS_INIT} - rt -) - -target_link_libraries(${LIB_FSFW_NAME} INTERFACE - ${CMAKE_THREAD_LIBS_INIT} -) +target_link_libraries(${LIB_FSFW_NAME} PUBLIC ${CMAKE_THREAD_LIBS_INIT}) +if(NOT APPLE) + target_link_libraries(${LIB_FSFW_NAME} PUBLIC rt) +endif() diff --git a/src/fsfw/osal/linux/Clock.cpp b/src/fsfw/osal/linux/Clock.cpp index 534e7e22..7dd960e5 100644 --- a/src/fsfw/osal/linux/Clock.cpp +++ b/src/fsfw/osal/linux/Clock.cpp @@ -2,23 +2,22 @@ #include #include -#include -#include #include +#include #include #include "fsfw/ipc/MutexGuard.h" #include "fsfw/serviceinterface/ServiceInterface.h" -uint32_t Clock::getTicksPerSecond(void) { +uint32_t Clock::getTicksPerSecond() { uint32_t ticks = sysconf(_SC_CLK_TCK); return ticks; } ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { - timespec timeUnix; - timeval timeTimeval; + timespec timeUnix{}; + timeval timeTimeval{}; convertTimeOfDayToTimeval(time, &timeTimeval); timeUnix.tv_sec = timeTimeval.tv_sec; timeUnix.tv_nsec = (__syscall_slong_t)timeTimeval.tv_usec * 1000; @@ -26,49 +25,49 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { int status = clock_settime(CLOCK_REALTIME, &timeUnix); if (status != 0) { // TODO errno - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::setClock(const timeval* time) { - timespec timeUnix; + timespec timeUnix{}; timeUnix.tv_sec = time->tv_sec; timeUnix.tv_nsec = (__syscall_slong_t)time->tv_usec * 1000; int status = clock_settime(CLOCK_REALTIME, &timeUnix); if (status != 0) { // TODO errno - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::getClock_timeval(timeval* time) { - timespec timeUnix; + timespec timeUnix{}; int status = clock_gettime(CLOCK_REALTIME, &timeUnix); if (status != 0) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } time->tv_sec = timeUnix.tv_sec; time->tv_usec = timeUnix.tv_nsec / 1000.0; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::getClock_usecs(uint64_t* time) { - timeval timeVal; + timeval timeVal{}; ReturnValue_t result = getClock_timeval(&timeVal); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } - *time = (uint64_t)timeVal.tv_sec * 1e6 + timeVal.tv_usec; + *time = static_cast(timeVal.tv_sec) * 1e6 + timeVal.tv_usec; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } timeval Clock::getUptime() { - timeval uptime; + timeval uptime{}; auto result = getUptime(&uptime); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "Clock::getUptime: Error getting uptime" << std::endl; #endif @@ -77,14 +76,17 @@ timeval Clock::getUptime() { } ReturnValue_t Clock::getUptime(timeval* uptime) { - // TODO This is not posix compatible and delivers only seconds precision - // Linux specific file read but more precise. double uptimeSeconds; - if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) { + std::ifstream ifile("/proc/uptime"); + if (ifile.bad()) { + return returnvalue::FAILED; + } + if (ifile >> uptimeSeconds) { uptime->tv_sec = uptimeSeconds; uptime->tv_usec = uptimeSeconds * (double)1e6 - (uptime->tv_sec * 1e6); + return returnvalue::OK; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::FAILED; } // Wait for new FSFW Clock function delivering seconds uptime. @@ -93,36 +95,36 @@ ReturnValue_t Clock::getUptime(timeval* uptime) { // struct sysinfo sysInfo; // int result = sysinfo(&sysInfo); // if(result != 0){ -// return HasReturnvaluesIF::RETURN_FAILED; +// return returnvalue::FAILED; // } // return sysInfo.uptime; //} ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { - timeval uptime; + timeval uptime{}; ReturnValue_t result = getUptime(&uptime); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } *uptimeMs = uptime.tv_sec * 1e3 + uptime.tv_usec / 1e3; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { - timespec timeUnix; + timespec timeUnix{}; int status = clock_gettime(CLOCK_REALTIME, &timeUnix); if (status != 0) { // TODO errno - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } ReturnValue_t result = checkOrCreateClockMutex(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } MutexGuard helper(timeMutex); // gmtime writes its output in a global buffer which is not Thread Safe // Therefore we have to use a Mutex here - struct tm* timeInfo; + struct std::tm* timeInfo; timeInfo = gmtime(&timeUnix.tv_sec); time->year = timeInfo->tm_year + 1900; time->month = timeInfo->tm_mon + 1; @@ -132,11 +134,11 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { time->second = timeInfo->tm_sec; time->usecond = timeUnix.tv_nsec / 1000.0; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) { - tm fromTm; + std::tm fromTm{}; // Note: Fails for years before AD fromTm.tm_year = from->year - 1900; fromTm.tm_mon = from->month - 1; @@ -148,10 +150,10 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to->tv_sec = timegm(&fromTm); to->tv_usec = from->usecond; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { *JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/src/fsfw/osal/linux/CountingSemaphore.cpp b/src/fsfw/osal/linux/CountingSemaphore.cpp index 78210996..e2b006d9 100644 --- a/src/fsfw/osal/linux/CountingSemaphore.cpp +++ b/src/fsfw/osal/linux/CountingSemaphore.cpp @@ -35,7 +35,7 @@ CountingSemaphore& CountingSemaphore::operator=(CountingSemaphore&& other) { ReturnValue_t CountingSemaphore::release() { ReturnValue_t result = checkCount(&handle, maxCount); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return CountingSemaphore::release(&this->handle); @@ -44,7 +44,7 @@ ReturnValue_t CountingSemaphore::release() { ReturnValue_t CountingSemaphore::release(sem_t* handle) { int result = sem_post(handle); if (result == 0) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } switch (errno) { @@ -61,7 +61,7 @@ ReturnValue_t CountingSemaphore::release(sem_t* handle) { } default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } diff --git a/src/fsfw/osal/linux/FixedTimeslotTask.cpp b/src/fsfw/osal/linux/FixedTimeslotTask.cpp index 1f4d6e23..34729c22 100644 --- a/src/fsfw/osal/linux/FixedTimeslotTask.cpp +++ b/src/fsfw/osal/linux/FixedTimeslotTask.cpp @@ -1,22 +1,20 @@ #include "fsfw/osal/linux/FixedTimeslotTask.h" -#include +#include -#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/serviceinterface/ServiceInterface.h" -uint32_t FixedTimeslotTask::deadlineMissedCount = 0; const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN; -FixedTimeslotTask::FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_, - uint32_t periodMs_) - : PosixThread(name_, priority_, stackSize_), pst(periodMs_), started(false) {} - -FixedTimeslotTask::~FixedTimeslotTask() {} +FixedTimeslotTask::FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_, + TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_) + : FixedTimeslotTaskBase(periodSeconds_, dlmFunc_), + posixThread(name_, priority_, stackSize_), + started(false) {} void* FixedTimeslotTask::taskEntryPoint(void* arg) { // The argument is re-interpreted as PollingTask. - FixedTimeslotTask* originalTask(reinterpret_cast(arg)); + auto* originalTask(reinterpret_cast(arg)); // The task's functionality is called. originalTask->taskFunctionality(); return nullptr; @@ -24,71 +22,44 @@ void* FixedTimeslotTask::taskEntryPoint(void* arg) { ReturnValue_t FixedTimeslotTask::startTask() { started = true; - createTask(&taskEntryPoint, this); - return HasReturnvaluesIF::RETURN_OK; + posixThread.createTask(&taskEntryPoint, this); + return returnvalue::OK; } ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { return PosixThread::sleep((uint64_t)ms * 1000000); } -uint32_t FixedTimeslotTask::getPeriodMs() const { return pst.getLengthMs(); } - -ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep) { - ExecutableObjectIF* executableObject = - ObjectManager::instance()->get(componentId); - if (executableObject != nullptr) { - pst.addSlot(componentId, slotTimeMs, executionStep, executableObject, this); - return HasReturnvaluesIF::RETURN_OK; - } - -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "Component " << std::hex << componentId << " not found, not adding it to pst" - << std::dec << std::endl; -#endif - return HasReturnvaluesIF::RETURN_FAILED; -} - -ReturnValue_t FixedTimeslotTask::checkSequence() const { return pst.checkSequence(); } - -void FixedTimeslotTask::taskFunctionality() { +[[noreturn]] void FixedTimeslotTask::taskFunctionality() { // Like FreeRTOS pthreads are running as soon as they are created if (!started) { - suspend(); + posixThread.suspend(); } - pst.intializeSequenceAfterTaskCreation(); + // Returnvalue ignored for now + static_cast(pollingSeqTable.intializeSequenceAfterTaskCreation()); // The start time for the first entry is read. - uint64_t lastWakeTime = getCurrentMonotonicTimeMs(); - uint64_t interval = pst.getIntervalToNextSlotMs(); + uint64_t lastWakeTime = PosixThread::getCurrentMonotonicTimeMs(); + uint32_t interval = 0; // The task's "infinite" inner loop is entered. - while (1) { - if (pst.slotFollowsImmediately()) { + while (true) { + if (pollingSeqTable.slotFollowsImmediately()) { // Do nothing } else { // The interval for the next polling slot is selected. - interval = this->pst.getIntervalToPreviousSlotMs(); + interval = pollingSeqTable.getIntervalToPreviousSlotMs(); // The period is checked and restarted with the new interval. // If the deadline was missed, the deadlineMissedFunc is called. if (!PosixThread::delayUntil(&lastWakeTime, interval)) { // No time left on timer -> we missed the deadline - missedDeadlineCounter(); + if (dlmFunc != nullptr) { + dlmFunc(); + } } } // The device handler for this slot is executed and the next one is chosen. - this->pst.executeAndAdvance(); - } -} - -void FixedTimeslotTask::missedDeadlineCounter() { - FixedTimeslotTask::deadlineMissedCount++; - if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount << " deadlines." - << std::endl; -#endif + pollingSeqTable.executeAndAdvance(); } } diff --git a/src/fsfw/osal/linux/FixedTimeslotTask.h b/src/fsfw/osal/linux/FixedTimeslotTask.h index 76b92db3..1f5766a2 100644 --- a/src/fsfw/osal/linux/FixedTimeslotTask.h +++ b/src/fsfw/osal/linux/FixedTimeslotTask.h @@ -3,11 +3,12 @@ #include -#include "../../tasks/FixedSlotSequence.h" -#include "../../tasks/FixedTimeslotTaskIF.h" #include "PosixThread.h" +#include "fsfw/tasks/FixedSlotSequence.h" +#include "fsfw/tasks/FixedTimeslotTaskBase.h" +#include "fsfw/tasks/definitions.h" -class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread { +class FixedTimeslotTask : public FixedTimeslotTaskBase { public: /** * Create a generic periodic task. @@ -21,29 +22,13 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread { * @param period_ * @param deadlineMissedFunc_ */ - FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_, uint32_t periodMs_); - virtual ~FixedTimeslotTask(); + FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_, + TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_); + ~FixedTimeslotTask() override = default; - virtual ReturnValue_t startTask(); + ReturnValue_t startTask() override; - virtual ReturnValue_t sleepFor(uint32_t ms); - - virtual uint32_t getPeriodMs() const; - - virtual ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep); - - virtual ReturnValue_t checkSequence() const; - - /** - * This static function can be used as #deadlineMissedFunc. - * It counts missedDeadlines and prints the number of missed deadlines every 10th time. - */ - static void missedDeadlineCounter(); - - /** - * A helper variable to count missed deadlines. - */ - static uint32_t deadlineMissedCount; + ReturnValue_t sleepFor(uint32_t ms) override; protected: /** @@ -53,9 +38,12 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread { * It links the functionalities provided by FixedSlotSequence with the * OS's System Calls to keep the timing of the periods. */ - virtual void taskFunctionality(); + [[noreturn]] virtual void taskFunctionality(); private: + PosixThread posixThread; + bool started; + /** * @brief This is the entry point in a new thread. * @@ -68,9 +56,6 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread { * arbitrary data. */ static void* taskEntryPoint(void* arg); - FixedSlotSequence pst; - - bool started; }; #endif /* FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */ diff --git a/src/fsfw/osal/linux/InternalErrorCodes.cpp b/src/fsfw/osal/linux/InternalErrorCodes.cpp index 11913906..41472b0c 100644 --- a/src/fsfw/osal/linux/InternalErrorCodes.cpp +++ b/src/fsfw/osal/linux/InternalErrorCodes.cpp @@ -2,7 +2,7 @@ ReturnValue_t InternalErrorCodes::translate(uint8_t code) { // TODO This class can be removed - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } InternalErrorCodes::InternalErrorCodes() {} diff --git a/src/fsfw/osal/linux/MessageQueue.cpp b/src/fsfw/osal/linux/MessageQueue.cpp index 378f4e74..c08e3775 100644 --- a/src/fsfw/osal/linux/MessageQueue.cpp +++ b/src/fsfw/osal/linux/MessageQueue.cpp @@ -21,7 +21,7 @@ MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs* attributes.mq_msgsize = maxMessageSize; attributes.mq_flags = 0; // Flags are ignored on Linux during mq_open // Set the name of the queue. The slash is mandatory! - sprintf(name, "/FSFW_MQ%u\n", queueCounter++); + sprintf(name, "/FSFW_MQ%u", queueCounter++); // Create a nonblocking queue if the name is available (the queue is read // and writable for the owner as well as the group) @@ -54,7 +54,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { "nullptr!" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (message->getMaximumMessageSize() < maxMessageSize) { @@ -62,7 +62,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { sif::error << "MessageQueue::receiveMessage: Message size " << message->getMaximumMessageSize() << " too small to receive data!" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } unsigned int messagePriority = 0; @@ -72,9 +72,9 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { this->last = message->getSender(); // Check size of incoming message. if (message->getMessageSize() < message->getMinimumMessageSize()) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else if (status == 0) { // Success but no message received return MessageQueueIF::EMPTY; @@ -131,9 +131,9 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { } default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -152,9 +152,9 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) { utility::printUnixErrorGeneric(CLASS_NAME, "flush", "EINVAL"); break; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } *count = attrib.mq_curmsgs; attrib.mq_curmsgs = 0; @@ -176,11 +176,11 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) { utility::printUnixErrorGeneric(CLASS_NAME, "flush", "EINVAL"); break; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, @@ -200,7 +200,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, #else sif::printError("MessageQueue::sendMessageFromMessageQueue: Message is nullptr\n"); #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } message->setSender(sentFrom); @@ -257,11 +257,11 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, utility::printUnixErrorGeneric(CLASS_NAME, "sendMessageFromMessageQueue", "EMSGSIZE"); break; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t MessageQueue::handleOpenError(mq_attr* attributes, uint32_t messageDepth) { @@ -290,9 +290,9 @@ ReturnValue_t MessageQueue::handleOpenError(mq_attr* attributes, uint32_t messag */ #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "MessageQueue::MessageQueue: Default MQ size " << defaultMqMaxMsg - << " is too small for requested size " << messageDepth << std::endl; + << " is too small for requested message depth " << messageDepth << std::endl; sif::error << "This error can be fixed by setting the maximum " - "allowed message size higher!" + "allowed message depth higher" << std::endl; #else sif::printError( @@ -320,7 +320,7 @@ ReturnValue_t MessageQueue::handleOpenError(mq_attr* attributes, uint32_t messag if (tempId != -1) { // Successful mq_open this->id = tempId; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } } break; @@ -331,5 +331,5 @@ ReturnValue_t MessageQueue::handleOpenError(mq_attr* attributes, uint32_t messag utility::printUnixErrorGeneric(CLASS_NAME, "MessageQueue", "Unknown"); } } - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } diff --git a/src/fsfw/osal/linux/MessageQueue.h b/src/fsfw/osal/linux/MessageQueue.h index 8614d101..108ec797 100644 --- a/src/fsfw/osal/linux/MessageQueue.h +++ b/src/fsfw/osal/linux/MessageQueue.h @@ -61,8 +61,7 @@ class MessageQueue : public MessageQueueBase { ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override; ReturnValue_t flush(uint32_t* count) override; ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, - MessageQueueId_t sentFrom, - bool ignoreFault = false) override; + MessageQueueId_t sentFrom, bool ignoreFault = false) override; protected: /** diff --git a/src/fsfw/osal/linux/Mutex.cpp b/src/fsfw/osal/linux/Mutex.cpp index 2698fb54..be7a0a85 100644 --- a/src/fsfw/osal/linux/Mutex.cpp +++ b/src/fsfw/osal/linux/Mutex.cpp @@ -82,9 +82,9 @@ ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) { return CURR_THREAD_ALREADY_OWNS_MUTEX; case 0: // Success - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; }; } @@ -103,8 +103,8 @@ ReturnValue_t Mutex::unlockMutex() { return CURR_THREAD_DOES_NOT_OWN_MUTEX; case 0: // Success - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; }; } diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.cpp b/src/fsfw/osal/linux/PeriodicPosixTask.cpp index e1937df4..556a0367 100644 --- a/src/fsfw/osal/linux/PeriodicPosixTask.cpp +++ b/src/fsfw/osal/linux/PeriodicPosixTask.cpp @@ -1,86 +1,54 @@ -#include "fsfw/osal/linux/PeriodicPosixTask.h" +#include "PeriodicPosixTask.h" -#include - -#include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/serviceinterface/ServiceInterface.h" +#include "fsfw/serviceinterface.h" #include "fsfw/tasks/ExecutableObjectIF.h" PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, - uint32_t period_, void(deadlineMissedFunc_)()) - : PosixThread(name_, priority_, stackSize_), - objectList(), - started(false), - periodMs(period_), - deadlineMissedFunc(deadlineMissedFunc_) {} - -PeriodicPosixTask::~PeriodicPosixTask() { - // Not Implemented -} + TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_) + : PeriodicTaskBase(period_, dlmFunc_), + posixThread(name_, priority_, stackSize_), + started(false) {} void* PeriodicPosixTask::taskEntryPoint(void* arg) { // The argument is re-interpreted as PollingTask. - PeriodicPosixTask* originalTask(reinterpret_cast(arg)); + auto* originalTask(reinterpret_cast(arg)); // The task's functionality is called. originalTask->taskFunctionality(); - return NULL; -} - -ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) { - ExecutableObjectIF* newObject = ObjectManager::instance()->get(object); - return addComponent(newObject); -} - -ReturnValue_t PeriodicPosixTask::addComponent(ExecutableObjectIF* object) { - if (object == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PeriodicTask::addComponent: Invalid object. Make sure" - << " it implements ExecutableObjectIF!" << std::endl; -#else - sif::printError( - "PeriodicTask::addComponent: Invalid object. Make sure it " - "implements ExecutableObjectIF!\n"); -#endif - return HasReturnvaluesIF::RETURN_FAILED; - } - objectList.push_back(object); - object->setTaskIF(this); - - return HasReturnvaluesIF::RETURN_OK; + return nullptr; } ReturnValue_t PeriodicPosixTask::sleepFor(uint32_t ms) { - return PosixThread::sleep((uint64_t)ms * 1000000); + return PosixThread::sleep(static_cast(ms) * 1000000); } -ReturnValue_t PeriodicPosixTask::startTask(void) { +ReturnValue_t PeriodicPosixTask::startTask() { + if (isEmpty()) { + return returnvalue::FAILED; + } started = true; - PosixThread::createTask(&taskEntryPoint, this); - return HasReturnvaluesIF::RETURN_OK; + posixThread.createTask(&taskEntryPoint, this); + return returnvalue::OK; } -void PeriodicPosixTask::taskFunctionality(void) { +[[noreturn]] void PeriodicPosixTask::taskFunctionality() { if (not started) { - suspend(); + posixThread.suspend(); } - for (auto const& object : objectList) { - object->initializeAfterTaskCreation(); - } + initObjsAfterTaskCreation(); - uint64_t lastWakeTime = getCurrentMonotonicTimeMs(); + uint64_t lastWakeTime = PosixThread::getCurrentMonotonicTimeMs(); + uint64_t periodMs = getPeriodMs(); // The task's "infinite" inner loop is entered. - while (1) { - for (auto const& object : objectList) { - object->performOperation(); + while (true) { + for (auto const& objOpCodePair : objectList) { + objOpCodePair.first->performOperation(objOpCodePair.second); } if (not PosixThread::delayUntil(&lastWakeTime, periodMs)) { - if (this->deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); + if (dlmFunc != nullptr) { + dlmFunc(); } } } } - -uint32_t PeriodicPosixTask::getPeriodMs() const { return periodMs; } diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.h b/src/fsfw/osal/linux/PeriodicPosixTask.h index 3cd9847a..085c10b9 100644 --- a/src/fsfw/osal/linux/PeriodicPosixTask.h +++ b/src/fsfw/osal/linux/PeriodicPosixTask.h @@ -3,12 +3,13 @@ #include -#include "../../objectmanager/ObjectManagerIF.h" -#include "../../tasks/ExecutableObjectIF.h" -#include "../../tasks/PeriodicTaskIF.h" #include "PosixThread.h" +#include "fsfw/objectmanager/ObjectManagerIF.h" +#include "fsfw/tasks/ExecutableObjectIF.h" +#include "fsfw/tasks/PeriodicTaskBase.h" +#include "fsfw/tasks/PeriodicTaskIF.h" -class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF { +class PeriodicPosixTask : public PeriodicTaskBase { public: /** * Create a generic periodic task. @@ -22,9 +23,9 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF { * @param period_ * @param deadlineMissedFunc_ */ - PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, uint32_t period_, - void (*deadlineMissedFunc_)()); - virtual ~PeriodicPosixTask(); + PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod period_, + TaskDeadlineMissedFunction dlmFunc_); + ~PeriodicPosixTask() override = default; /** * @brief The method to start the task. @@ -34,42 +35,17 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF { * to the system call. */ ReturnValue_t startTask() override; - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object Id of the object to add. - * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(object_id_t object) override; - - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object pointer to the object to add. - * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(ExecutableObjectIF* object) override; - - uint32_t getPeriodMs() const override; ReturnValue_t sleepFor(uint32_t ms) override; private: - typedef std::vector ObjectList; //!< Typedef for the List of objects. - /** - * @brief This attribute holds a list of objects to be executed. - */ - ObjectList objectList; + PosixThread posixThread; /** * @brief Flag to indicate that the task was started and is allowed to run */ bool started; - /** - * @brief Period of the task in milliseconds - */ - uint32_t periodMs; /** * @brief The function containing the actual functionality of the task. * @details The method sets and starts @@ -78,7 +54,7 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF { * will be blocked until the next period. On missing the deadline, the deadlineMissedFunction is * executed. */ - virtual void taskFunctionality(void); + [[noreturn]] virtual void taskFunctionality(); /** * @brief This is the entry point in a new thread. * @@ -86,14 +62,6 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF { * of the child class. Needs a valid pointer to the derived class. */ static void* taskEntryPoint(void* arg); - /** - * @brief The pointer to the deadline-missed function. - * @details This pointer stores the function that is executed if the task's deadline is missed. - * So, each may react individually on a timing failure. The pointer may be - * NULL, then nothing happens on missing the deadline. The deadline is equal to the next execution - * of the periodic task. - */ - void (*deadlineMissedFunc)(); }; #endif /* FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ */ diff --git a/src/fsfw/osal/linux/PosixThread.cpp b/src/fsfw/osal/linux/PosixThread.cpp index 9fc088ae..811d58e2 100644 --- a/src/fsfw/osal/linux/PosixThread.cpp +++ b/src/fsfw/osal/linux/PosixThread.cpp @@ -29,16 +29,16 @@ ReturnValue_t PosixThread::sleep(uint64_t ns) { switch (errno) { case EINTR: // The nanosleep() function was interrupted by a signal. - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case EINVAL: // The rqtp argument specified a nanosecond value less than zero or // greater than or equal to 1000 million. - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void PosixThread::suspend() { diff --git a/src/fsfw/osal/linux/PosixThread.h b/src/fsfw/osal/linux/PosixThread.h index 69c6c5b7..add41bf6 100644 --- a/src/fsfw/osal/linux/PosixThread.h +++ b/src/fsfw/osal/linux/PosixThread.h @@ -7,7 +7,7 @@ #include -#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../returnvalues/returnvalue.h" class PosixThread { public: @@ -35,6 +35,21 @@ class PosixThread { */ void resume(); + /** + * @brief Function that has to be called by derived class because the + * derived class pointer has to be valid as argument. + * @details + * This function creates a pthread with the given parameters. As the + * function requires a pointer to the derived object it has to be called + * after the this pointer of the derived object is valid. + * Sets the taskEntryPoint as function to be called by new a thread. + * @param fnc_ Function which will be executed by the thread. + * @param arg_ + * argument of the taskEntryPoint function, needs to be this pointer + * of derived class + */ + void createTask(void* (*fnc_)(void*), void* arg_); + /** * Delay function similar to FreeRtos delayUntil function * @@ -55,21 +70,6 @@ class PosixThread { protected: pthread_t thread; - /** - * @brief Function that has to be called by derived class because the - * derived class pointer has to be valid as argument. - * @details - * This function creates a pthread with the given parameters. As the - * function requires a pointer to the derived object it has to be called - * after the this pointer of the derived object is valid. - * Sets the taskEntryPoint as function to be called by new a thread. - * @param fnc_ Function which will be executed by the thread. - * @param arg_ - * argument of the taskEntryPoint function, needs to be this pointer - * of derived class - */ - void createTask(void* (*fnc_)(void*), void* arg_); - private: char name[PTHREAD_MAX_NAMELEN]; int priority; diff --git a/src/fsfw/osal/linux/TaskFactory.cpp b/src/fsfw/osal/linux/TaskFactory.cpp index 8503039f..bacc4311 100644 --- a/src/fsfw/osal/linux/TaskFactory.cpp +++ b/src/fsfw/osal/linux/TaskFactory.cpp @@ -2,32 +2,33 @@ #include "fsfw/osal/linux/FixedTimeslotTask.h" #include "fsfw/osal/linux/PeriodicPosixTask.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/serviceinterface/ServiceInterface.h" // TODO: Different variant than the lazy loading in QueueFactory. What's better and why? TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); -TaskFactory::~TaskFactory() {} +TaskFactory::~TaskFactory() = default; TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; } PeriodicTaskIF* TaskFactory::createPeriodicTask( TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_, TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) { - return new PeriodicPosixTask(name_, taskPriority_, stackSize_, periodInSeconds_ * 1000, + return new PeriodicPosixTask(name_, taskPriority_, stackSize_, periodInSeconds_, deadLineMissedFunction_); } FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask( TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_, TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) { - return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_ * 1000); + return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_, + deadLineMissedFunction_); } ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { // TODO not implemented - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } ReturnValue_t TaskFactory::delayTask(uint32_t delayMs) { diff --git a/src/fsfw/osal/osal.h.in b/src/fsfw/osal/osal.h.in new file mode 100644 index 00000000..8e48c31a --- /dev/null +++ b/src/fsfw/osal/osal.h.in @@ -0,0 +1,36 @@ +#pragma once + +namespace osal { + enum osalTarget{ + HOST, + LINUX, + WINDOWS, + FREERTOS, + RTEMS, + }; + +#cmakedefine FSFW_OSAL_HOST +#cmakedefine FSFW_OSAL_LINUX +#cmakedefine FSFW_OSAL_WINDOWS +#cmakedefine FSFW_OSAL_FREERTOS +#cmakedefine FSFW_OSAL_RTEMS + + + constexpr osalTarget getTarget() { +#ifdef FSFW_OSAL_HOST + return HOST; +#endif +#ifdef FSFW_OSAL_LINUX + return LINUX; +#endif +#ifdef FSFW_OSAL_WINDOWS + return WINDOWS; +#endif +#ifdef FSFW_OSAL_FREERTOS + return FREERTOS; +#endif +#ifdef FSFW_OSAL_RTEMS + return RTEMS; +#endif + } +}; \ No newline at end of file diff --git a/src/fsfw/osal/rtems/BinarySemaphore.cpp b/src/fsfw/osal/rtems/BinarySemaphore.cpp index 06b0bf77..3677dd22 100644 --- a/src/fsfw/osal/rtems/BinarySemaphore.cpp +++ b/src/fsfw/osal/rtems/BinarySemaphore.cpp @@ -7,9 +7,9 @@ BinarySemaphore::BinarySemaphore() {} BinarySemaphore::~BinarySemaphore() {} ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, uint32_t timeoutMs) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } -ReturnValue_t BinarySemaphore::release() { return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t BinarySemaphore::release() { return returnvalue::OK; } uint8_t BinarySemaphore::getSemaphoreCounter() const { return 0; } diff --git a/src/fsfw/osal/rtems/CMakeLists.txt b/src/fsfw/osal/rtems/CMakeLists.txt index 734566a3..1b47e1b9 100644 --- a/src/fsfw/osal/rtems/CMakeLists.txt +++ b/src/fsfw/osal/rtems/CMakeLists.txt @@ -1,20 +1,17 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - Clock.cpp - CpuUsage.cpp - InitTask.cpp - InternalErrorCodes.cpp - MessageQueue.cpp - PeriodicTask.cpp - Mutex.cpp - MutexFactory.cpp - FixedTimeslotTask.cpp - QueueFactory.cpp - RtemsBasic.cpp - RTEMSTaskBase.cpp - TaskFactory.cpp - BinarySemaphore.cpp - SemaphoreFactory.cpp -) - - +target_sources( + ${LIB_FSFW_NAME} + PRIVATE Clock.cpp + CpuUsage.cpp + InitTask.cpp + InternalErrorCodes.cpp + MessageQueue.cpp + PeriodicTask.cpp + Mutex.cpp + MutexFactory.cpp + FixedTimeslotTask.cpp + QueueFactory.cpp + RtemsBasic.cpp + RTEMSTaskBase.cpp + TaskFactory.cpp + BinarySemaphore.cpp + SemaphoreFactory.cpp) diff --git a/src/fsfw/osal/rtems/Clock.cpp b/src/fsfw/osal/rtems/Clock.cpp index 831c67d4..cb7bd042 100644 --- a/src/fsfw/osal/rtems/Clock.cpp +++ b/src/fsfw/osal/rtems/Clock.cpp @@ -23,13 +23,13 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { rtems_status_code status = rtems_clock_set(&timeRtems); switch (status) { case RTEMS_SUCCESSFUL: - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; case RTEMS_INVALID_ADDRESS: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_INVALID_CLOCK: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -38,7 +38,7 @@ ReturnValue_t Clock::setClock(const timeval* time) { newTime.tv_sec = time->tv_sec; if (time->tv_usec < 0) { // better returnvalue. - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } newTime.tv_nsec = time->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND; @@ -48,10 +48,10 @@ ReturnValue_t Clock::setClock(const timeval* time) { Status_Control status = _TOD_Set(&newTime, &context); _TOD_Unlock(); if (status == STATUS_SUCCESSFUL) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } // better returnvalue - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } ReturnValue_t Clock::getClock_timeval(timeval* time) { @@ -59,11 +59,11 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) { rtems_status_code status = rtems_clock_get_tod_timeval(time); switch (status) { case RTEMS_SUCCESSFUL: - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; case RTEMS_NOT_DEFINED: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -77,16 +77,16 @@ ReturnValue_t Clock::getUptime(timeval* uptime) { uptime->tv_usec = time.tv_nsec; switch (status) { case RTEMS_SUCCESSFUL: - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { // This counter overflows after 50 days *uptimeMs = rtems_clock_get_ticks_since_boot(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::getClock_usecs(uint64_t* time) { @@ -95,9 +95,9 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) { *time = ((uint64_t)temp_time.tv_sec * 1000000) + temp_time.tv_usec; switch (returnValue) { case RTEMS_SUCCESSFUL: - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -118,16 +118,16 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { time->usecond = static_cast(timeRtems.ticks) / rtems_clock_get_ticks_per_second() * 1e6; time->year = timeRtems.year; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } case RTEMS_NOT_DEFINED: /* System date and time is not set */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_INVALID_ADDRESS: /* time_buffer is NULL */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -143,10 +143,10 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* timeRtems.ticks = from->usecond * getTicksPerSecond() / 1e6; to->tv_sec = _TOD_To_seconds(&timeRtems); to->tv_usec = from->usecond; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { *JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/src/fsfw/osal/rtems/CpuUsage.cpp b/src/fsfw/osal/rtems/CpuUsage.cpp index 2613a698..4ffc2271 100644 --- a/src/fsfw/osal/rtems/CpuUsage.cpp +++ b/src/fsfw/osal/rtems/CpuUsage.cpp @@ -86,7 +86,7 @@ ReturnValue_t CpuUsage::serialize(uint8_t** buffer, size_t* size, size_t maxSize Endianness streamEndianness) const { ReturnValue_t result = SerializeAdapter::serialize(&timeSinceLastReset, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return SerialArrayListAdapter::serialize(&threadData, buffer, size, maxSize, @@ -106,7 +106,7 @@ ReturnValue_t CpuUsage::deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::deSerialize(&timeSinceLastReset, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return SerialArrayListAdapter::deSerialize(&threadData, buffer, size, @@ -116,7 +116,7 @@ ReturnValue_t CpuUsage::deSerialize(const uint8_t** buffer, size_t* size, ReturnValue_t CpuUsage::ThreadData::serialize(uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result = SerializeAdapter::serialize(&id, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (*size + MAX_LENGTH_OF_THREAD_NAME > maxSize) { @@ -126,14 +126,14 @@ ReturnValue_t CpuUsage::ThreadData::serialize(uint8_t** buffer, size_t* size, si *size += MAX_LENGTH_OF_THREAD_NAME; *buffer += MAX_LENGTH_OF_THREAD_NAME; result = SerializeAdapter::serialize(&timeRunning, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&percentUsage, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } uint32_t CpuUsage::ThreadData::getSerializedSize() const { @@ -150,7 +150,7 @@ uint32_t CpuUsage::ThreadData::getSerializedSize() const { ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::deSerialize(&id, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (*size < MAX_LENGTH_OF_THREAD_NAME) { @@ -159,12 +159,12 @@ ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer, size_t* memcpy(name, *buffer, MAX_LENGTH_OF_THREAD_NAME); *buffer -= MAX_LENGTH_OF_THREAD_NAME; result = SerializeAdapter::deSerialize(&timeRunning, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::deSerialize(&percentUsage, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/src/fsfw/osal/rtems/CpuUsage.h b/src/fsfw/osal/rtems/CpuUsage.h index fdba689e..55a55143 100644 --- a/src/fsfw/osal/rtems/CpuUsage.h +++ b/src/fsfw/osal/rtems/CpuUsage.h @@ -19,13 +19,13 @@ class CpuUsage : public SerializeIF { float timeRunning; float percentUsage; - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const override; + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override; - virtual size_t getSerializedSize() const override; + size_t getSerializedSize() const override; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) override; + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; }; CpuUsage(); diff --git a/src/fsfw/osal/rtems/FixedTimeslotTask.cpp b/src/fsfw/osal/rtems/FixedTimeslotTask.cpp index 3347739a..c1cc4460 100644 --- a/src/fsfw/osal/rtems/FixedTimeslotTask.cpp +++ b/src/fsfw/osal/rtems/FixedTimeslotTask.cpp @@ -1,42 +1,32 @@ #include "fsfw/osal/rtems/FixedTimeslotTask.h" -#include #include -#include #include #include #include -#include -#include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/objectmanager/SystemObjectIF.h" #include "fsfw/osal/rtems/RtemsBasic.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tasks/FixedSequenceSlot.h" #if FSFW_CPP_OSTREAM_ENABLED == 1 #include #endif #include -#include - -uint32_t FixedTimeslotTask::deadlineMissedCount = 0; FixedTimeslotTask::FixedTimeslotTask(const char *name, rtems_task_priority setPriority, - size_t setStack, uint32_t setOverallPeriod, - void (*setDeadlineMissedFunc)(void)) - : RTEMSTaskBase(setPriority, setStack, name), periodId(0), pst(setOverallPeriod) { - // All additional attributes are applied to the object. - this->deadlineMissedFunc = setDeadlineMissedFunc; -} + size_t setStack, TaskPeriod setOverallPeriod, + TaskDeadlineMissedFunction dlmFunc_) + : FixedTimeslotTaskBase(setOverallPeriod, dlmFunc_), + RTEMSTaskBase(setPriority, setStack, name), + periodId(0) {} -FixedTimeslotTask::~FixedTimeslotTask() {} +FixedTimeslotTask::~FixedTimeslotTask() = default; rtems_task FixedTimeslotTask::taskEntryPoint(rtems_task_argument argument) { /* The argument is re-interpreted as a FixedTimeslotTask */ - FixedTimeslotTask *originalTask(reinterpret_cast(argument)); + auto *originalTask(reinterpret_cast(argument)); /* The task's functionality is called. */ return originalTask->taskFunctionality(); /* Should never be reached */ @@ -46,16 +36,6 @@ rtems_task FixedTimeslotTask::taskEntryPoint(rtems_task_argument argument) { #endif } -void FixedTimeslotTask::missedDeadlineCounter() { - FixedTimeslotTask::deadlineMissedCount++; - if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount << " deadlines." - << std::endl; -#endif - } -} - ReturnValue_t FixedTimeslotTask::startTask() { rtems_status_code status = rtems_task_start(id, FixedTimeslotTask::taskEntryPoint, rtems_task_argument((void *)this)); @@ -68,65 +48,46 @@ ReturnValue_t FixedTimeslotTask::startTask() { switch (status) { case RTEMS_SUCCESSFUL: // ask started successfully - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; default: /* RTEMS_INVALID_ADDRESS - invalid task entry point RTEMS_INVALID_ID - invalid task id RTEMS_INCORRECT_STATE - task not in the dormant state RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } -ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep) { - ExecutableObjectIF *object = ObjectManager::instance()->get(componentId); - if (object != nullptr) { - pst.addSlot(componentId, slotTimeMs, executionStep, object, this); - return HasReturnvaluesIF::RETURN_OK; - } - -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "Component " << std::hex << componentId << " not found, not adding it to pst" - << std::endl; -#endif - return HasReturnvaluesIF::RETURN_FAILED; -} - -uint32_t FixedTimeslotTask::getPeriodMs() const { return pst.getLengthMs(); } - -ReturnValue_t FixedTimeslotTask::checkSequence() const { return pst.checkSequence(); } - -void FixedTimeslotTask::taskFunctionality() { +[[noreturn]] void FixedTimeslotTask::taskFunctionality() { /* A local iterator for the Polling Sequence Table is created to find the start time for the first entry. */ - FixedSlotSequence::SlotListIter it = pst.current; + auto it = pollingSeqTable.current; /* Initialize the PST with the correct calling task */ - pst.intializeSequenceAfterTaskCreation(); + pollingSeqTable.intializeSequenceAfterTaskCreation(); /* The start time for the first entry is read. */ rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs); RTEMSTaskBase::setAndStartPeriod(interval, &periodId); // The task's "infinite" inner loop is entered. - while (1) { - if (pst.slotFollowsImmediately()) { + while (true) { + if (pollingSeqTable.slotFollowsImmediately()) { /* Do nothing */ } else { /* The interval for the next polling slot is selected. */ - interval = RtemsBasic::convertMsToTicks(this->pst.getIntervalToNextSlotMs()); + interval = RtemsBasic::convertMsToTicks(pollingSeqTable.getIntervalToNextSlotMs()); /* The period is checked and restarted with the new interval. If the deadline was missed, the deadlineMissedFunc is called. */ rtems_status_code status = RTEMSTaskBase::restartPeriod(interval, periodId); if (status == RTEMS_TIMEOUT) { - if (this->deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); + if (dlmFunc != nullptr) { + dlmFunc(); } } } /* The device handler for this slot is executed and the next one is chosen. */ - this->pst.executeAndAdvance(); + this->pollingSeqTable.executeAndAdvance(); } } diff --git a/src/fsfw/osal/rtems/FixedTimeslotTask.h b/src/fsfw/osal/rtems/FixedTimeslotTask.h index 6dedfa44..781c93db 100644 --- a/src/fsfw/osal/rtems/FixedTimeslotTask.h +++ b/src/fsfw/osal/rtems/FixedTimeslotTask.h @@ -1,11 +1,11 @@ #ifndef FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_ #define FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_ -#include "../../tasks/FixedSlotSequence.h" -#include "../../tasks/FixedTimeslotTaskIF.h" #include "RTEMSTaskBase.h" +#include "fsfw/tasks/FixedSlotSequence.h" +#include "fsfw/tasks/FixedTimeslotTaskBase.h" -class FixedTimeslotTask : public RTEMSTaskBase, public FixedTimeslotTaskIF { +class FixedTimeslotTask : public FixedTimeslotTaskBase, public RTEMSTaskBase { public: /** * @brief The standard constructor of the class. @@ -17,7 +17,7 @@ class FixedTimeslotTask : public RTEMSTaskBase, public FixedTimeslotTaskIF { * @param getPst The object id of the completely initialized polling sequence. */ FixedTimeslotTask(const char *name, rtems_task_priority setPriority, size_t setStackSize, - uint32_t overallPeriod, void (*setDeadlineMissedFunc)()); + TaskPeriod overallPeriod, TaskDeadlineMissedFunction dlmFunc); /** * @brief The destructor of the class. @@ -25,44 +25,17 @@ class FixedTimeslotTask : public RTEMSTaskBase, public FixedTimeslotTaskIF { * The destructor frees all heap memory that was allocated on thread initialization * for the PST andthe device handlers. This is done by calling the PST's destructor. */ - virtual ~FixedTimeslotTask(void); + ~FixedTimeslotTask() override; ReturnValue_t startTask(void); - /** - * This static function can be used as #deadlineMissedFunc. - * It counts missedDeadlines and prints the number of missed deadlines every 10th time. - */ - static void missedDeadlineCounter(); - /** - * A helper variable to count missed deadlines. - */ - static uint32_t deadlineMissedCount; - ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep); - - uint32_t getPeriodMs() const; - - ReturnValue_t checkSequence() const; - - ReturnValue_t sleepFor(uint32_t ms); + ReturnValue_t sleepFor(uint32_t ms) override; protected: /** * @brief id of the associated OS period */ rtems_id periodId; - - FixedSlotSequence pst; - - /** - * @brief This attribute holds a function pointer that is executed when a deadline was missed. - * - * @details - * Another function may be announced to determine the actions to perform when a deadline - * was missed. Currently, only one function for missing any deadline is allowed. - * If not used, it shall be declared NULL. - */ - void (*deadlineMissedFunc)(void) = nullptr; /** * @brief This is the entry point in a new polling thread. * @details This method is the entry point in the new thread @@ -76,7 +49,7 @@ class FixedTimeslotTask : public RTEMSTaskBase, public FixedTimeslotTaskIF { * It links the functionalities provided by FixedSlotSequence with the OS's system calls to * keep the timing of the periods. */ - void taskFunctionality(void); + [[noreturn]] void taskFunctionality(); }; #endif /* FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_ */ diff --git a/src/fsfw/osal/rtems/InternalErrorCodes.cpp b/src/fsfw/osal/rtems/InternalErrorCodes.cpp index 4d78186c..9e0c1ae7 100644 --- a/src/fsfw/osal/rtems/InternalErrorCodes.cpp +++ b/src/fsfw/osal/rtems/InternalErrorCodes.cpp @@ -50,7 +50,7 @@ ReturnValue_t InternalErrorCodes::translate(uint8_t code) { // case INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0: // return UNLIMITED_AND_MAXIMUM_IS_0; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } diff --git a/src/fsfw/osal/rtems/MessageQueue.cpp b/src/fsfw/osal/rtems/MessageQueue.cpp index f52f1852..bae3b5e0 100644 --- a/src/fsfw/osal/rtems/MessageQueue.cpp +++ b/src/fsfw/osal/rtems/MessageQueue.cpp @@ -32,7 +32,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { this->last = message->getSender(); // Check size of incoming message. if (message->getMessageSize() < message->getMinimumMessageSize()) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } else { // No message was received. Keep lastPartner anyway, I might send something later. @@ -65,8 +65,8 @@ ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueu } ReturnValue_t returnCode = convertReturnCode(result); - if (result == MessageQueueIF::EMPTY) { - return HasReturnvaluesIF::RETURN_FAILED; + if (returnCode == MessageQueueIF::EMPTY) { + return returnvalue::FAILED; } return returnCode; @@ -75,23 +75,23 @@ ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueu ReturnValue_t MessageQueue::convertReturnCode(rtems_status_code inValue) { switch (inValue) { case RTEMS_SUCCESSFUL: - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; case RTEMS_INVALID_ID: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_TIMEOUT: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_OBJECT_WAS_DELETED: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_INVALID_ADDRESS: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_INVALID_SIZE: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_TOO_MANY: return MessageQueueIF::FULL; case RTEMS_UNSATISFIED: return MessageQueueIF::EMPTY; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } diff --git a/src/fsfw/osal/rtems/MessageQueue.h b/src/fsfw/osal/rtems/MessageQueue.h index 4648fdfa..6f1ce568 100644 --- a/src/fsfw/osal/rtems/MessageQueue.h +++ b/src/fsfw/osal/rtems/MessageQueue.h @@ -2,6 +2,7 @@ #define FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_ #include + #include "RtemsBasic.h" #include "fsfw/internalerror/InternalErrorReporterIF.h" #include "fsfw/ipc/MessageQueueIF.h" @@ -35,9 +36,9 @@ class MessageQueue : public MessageQueueBase { * @param max_message_size With this parameter, the maximum message size can be adjusted. * This should be left default. */ - MessageQueue(size_t message_depth = 3, - size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE, - MqArgs* args = nullptr); + explicit MessageQueue(size_t message_depth = 3, + size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE, + MqArgs* args = nullptr); /** Copying message queues forbidden */ MessageQueue(const MessageQueue&) = delete; @@ -47,18 +48,19 @@ class MessageQueue : public MessageQueueBase { * @brief The destructor deletes the formerly created message queue. * @details This is accomplished by using the delete call provided by the operating system. */ - virtual ~MessageQueue(); + ~MessageQueue() override; // Implement non-generic MessageQueueIF functions not handled by MessageQueueBase ReturnValue_t flush(uint32_t* count) override; + + ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override; ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, - MessageQueueId_t sentFrom = NO_QUEUE, - bool ignoreFault = false) override; + MessageQueueId_t sentFrom, bool ignoreFault) override; private: /** - * \brief This attribute stores a reference to the internal error reporter for reporting full - * queues. \details In the event of a full destination queue, the reporter will be notified. The + * @brief This attribute stores a reference to the internal error reporter for reporting full + * queues. @details In the event of a full destination queue, the reporter will be notified. The * reference is set by lazy loading */ InternalErrorReporterIF* internalErrorReporter; diff --git a/src/fsfw/osal/rtems/Mutex.cpp b/src/fsfw/osal/rtems/Mutex.cpp index 94f0041e..eb1a3718 100644 --- a/src/fsfw/osal/rtems/Mutex.cpp +++ b/src/fsfw/osal/rtems/Mutex.cpp @@ -43,7 +43,7 @@ ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType = TimeoutType::BLOCKING, switch (status) { case RTEMS_SUCCESSFUL: // semaphore obtained successfully - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; case RTEMS_UNSATISFIED: // semaphore not available return MUTEX_NOT_FOUND; @@ -57,7 +57,7 @@ ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType = TimeoutType::BLOCKING, // invalid semaphore id return MUTEX_INVALID_ID; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -66,7 +66,7 @@ ReturnValue_t Mutex::unlockMutex() { switch (status) { case RTEMS_SUCCESSFUL: // semaphore obtained successfully - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; case RTEMS_NOT_OWNER_OF_RESOURCE: // semaphore not available return CURR_THREAD_DOES_NOT_OWN_MUTEX; @@ -74,6 +74,6 @@ ReturnValue_t Mutex::unlockMutex() { // invalid semaphore id return MUTEX_INVALID_ID; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } diff --git a/src/fsfw/osal/rtems/PeriodicTask.cpp b/src/fsfw/osal/rtems/PeriodicTask.cpp index ae2ec426..5c397815 100644 --- a/src/fsfw/osal/rtems/PeriodicTask.cpp +++ b/src/fsfw/osal/rtems/PeriodicTask.cpp @@ -5,12 +5,12 @@ #include "fsfw/tasks/ExecutableObjectIF.h" PeriodicTask::PeriodicTask(const char* name, rtems_task_priority setPriority, size_t setStack, - rtems_interval setPeriod, void (*setDeadlineMissedFunc)()) - : RTEMSTaskBase(setPriority, setStack, name), - periodTicks(RtemsBasic::convertMsToTicks(setPeriod)), - deadlineMissedFunc(setDeadlineMissedFunc) {} + TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc_) + : PeriodicTaskBase(setPeriod, dlmFunc_), + RTEMSTaskBase(setPriority, setStack, name), + periodTicks(RtemsBasic::convertMsToTicks(static_cast(setPeriod * 1000.0))) {} -PeriodicTask::~PeriodicTask(void) { +PeriodicTask::~PeriodicTask() { /* Do not delete objects, we were responsible for pointers only. */ rtems_rate_monotonic_delete(periodId); } @@ -18,7 +18,7 @@ PeriodicTask::~PeriodicTask(void) { rtems_task PeriodicTask::taskEntryPoint(rtems_task_argument argument) { /* The argument is re-interpreted as MultiObjectTask. The Task object is global, so it is found from any place. */ - PeriodicTask* originalTask(reinterpret_cast(argument)); + auto* originalTask(reinterpret_cast(argument)); return originalTask->taskFunctionality(); ; } @@ -28,57 +28,41 @@ ReturnValue_t PeriodicTask::startTask() { rtems_task_start(id, PeriodicTask::taskEntryPoint, rtems_task_argument((void*)this)); if (status != RTEMS_SUCCESSFUL) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "ObjectTask::startTask for " << std::hex << this->getId() << std::dec - << " failed." << std::endl; + sif::error << "PeriodicTask::startTask for " << std::hex << this->getId() << std::dec + << " failed" << std::endl; +#else + sif::printError("PeriodicTask::startTask for 0x%08x failed\n", getId()); #endif } switch (status) { case RTEMS_SUCCESSFUL: /* Task started successfully */ - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; default: /* RTEMS_INVALID_ADDRESS - invalid task entry point RTEMS_INVALID_ID - invalid task id RTEMS_INCORRECT_STATE - task not in the dormant state RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { return RTEMSTaskBase::sleepFor(ms); } -void PeriodicTask::taskFunctionality() { +[[noreturn]] void PeriodicTask::taskFunctionality() { RTEMSTaskBase::setAndStartPeriod(periodTicks, &periodId); - for (const auto& object : objectList) { - object->initializeAfterTaskCreation(); - } + initObjsAfterTaskCreation(); + /* The task's "infinite" inner loop is entered. */ - while (1) { - for (const auto& object : objectList) { - object->performOperation(); + while (true) { + for (const auto& objectPair : objectList) { + objectPair.first->performOperation(objectPair.second); } rtems_status_code status = RTEMSTaskBase::restartPeriod(periodTicks, periodId); if (status == RTEMS_TIMEOUT) { - if (this->deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); + if (dlmFunc != nullptr) { + dlmFunc(); } } } } - -ReturnValue_t PeriodicTask::addComponent(object_id_t object) { - ExecutableObjectIF* newObject = ObjectManager::instance()->get(object); - return addComponent(newObject); -} - -ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) { - if (object == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - objectList.push_back(object); - object->setTaskIF(this); - - return HasReturnvaluesIF::RETURN_OK; -} - -uint32_t PeriodicTask::getPeriodMs() const { return RtemsBasic::convertTicksToMs(periodTicks); } diff --git a/src/fsfw/osal/rtems/PeriodicTask.h b/src/fsfw/osal/rtems/PeriodicTask.h index 24ce4af1..d987a82e 100644 --- a/src/fsfw/osal/rtems/PeriodicTask.h +++ b/src/fsfw/osal/rtems/PeriodicTask.h @@ -3,9 +3,10 @@ #include -#include "../../objectmanager/ObjectManagerIF.h" -#include "../../tasks/PeriodicTaskIF.h" #include "RTEMSTaskBase.h" +#include "fsfw/objectmanager/ObjectManagerIF.h" +#include "fsfw/tasks/PeriodicTaskBase.h" +#include "fsfw/tasks/PeriodicTaskIF.h" class ExecutableObjectIF; @@ -18,7 +19,7 @@ class ExecutableObjectIF; * @author baetz * @ingroup task_handling */ -class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF { +class PeriodicTask : public PeriodicTaskBase, public RTEMSTaskBase { public: /** * @brief Standard constructor of the class. @@ -36,12 +37,12 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF { * that shall be assigned. */ PeriodicTask(const char *name, rtems_task_priority setPriority, size_t setStack, - rtems_interval setPeriod, void (*setDeadlineMissedFunc)()); + TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc); /** * @brief Currently, the executed object's lifetime is not coupled with the task object's * lifetime, so the destructor is empty. */ - virtual ~PeriodicTask(void); + ~PeriodicTask() override; /** * @brief The method to start the task. @@ -50,34 +51,11 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF { * The address of the task object is passed as an argument * to the system call. */ - ReturnValue_t startTask(void); - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object Id of the object to add. - * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(object_id_t object) override; - -/** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object pointer to the object to add. - * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(ExecutableObjectIF* object) override; - - - uint32_t getPeriodMs() const override; + ReturnValue_t startTask() override; ReturnValue_t sleepFor(uint32_t ms) override; protected: - typedef std::vector ObjectList; //!< Typedef for the List of objects. - /** - * @brief This attribute holds a list of objects to be executed. - */ - ObjectList objectList; /** * @brief The period of the task. * @details The period determines the frequency of the task's execution. It is expressed in @@ -88,14 +66,7 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF { * @brief id of the associated OS period */ rtems_id periodId = 0; - /** - * @brief The pointer to the deadline-missed function. - * @details This pointer stores the function that is executed if the task's deadline is missed. - * So, each may react individually on a timing failure. The pointer may be - * nullptr, then nothing happens on missing the deadline. The deadline is equal to the next - * execution of the periodic task. - */ - void (*deadlineMissedFunc)(void); + /** * @brief This is the function executed in the new task's context. * @details It converts the argument back to the thread object type and copies the class @@ -111,7 +82,7 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF { * are called. Afterwards the checkAndRestartPeriod system call blocks the task until the next * period. On missing the deadline, the deadlineMissedFunction is executed. */ - void taskFunctionality(void); + [[noreturn]] void taskFunctionality(); }; #endif /* FSFW_OSAL_RTEMS_PERIODICTASK_H_ */ diff --git a/src/fsfw/osal/rtems/QueueFactory.cpp b/src/fsfw/osal/rtems/QueueFactory.cpp index 2519f444..1918f7bc 100644 --- a/src/fsfw/osal/rtems/QueueFactory.cpp +++ b/src/fsfw/osal/rtems/QueueFactory.cpp @@ -16,25 +16,25 @@ ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, switch (result) { case RTEMS_SUCCESSFUL: // message sent successfully - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; case RTEMS_INVALID_ID: // invalid queue id - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_INVALID_SIZE: // invalid message size - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_INVALID_ADDRESS: // buffer is NULL - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_UNSATISFIED: // out of message buffers - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_TOO_MANY: // queue's limit has been reached return MessageQueueIF::FULL; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -45,9 +45,9 @@ QueueFactory* QueueFactory::instance() { return factoryInstance; } -QueueFactory::QueueFactory() {} +QueueFactory::QueueFactory() = default; -QueueFactory::~QueueFactory() {} +QueueFactory::~QueueFactory() = default; MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs* args) { diff --git a/src/fsfw/osal/rtems/RTEMSTaskBase.cpp b/src/fsfw/osal/rtems/RTEMSTaskBase.cpp index a01b7802..b235f6a0 100644 --- a/src/fsfw/osal/rtems/RTEMSTaskBase.cpp +++ b/src/fsfw/osal/rtems/RTEMSTaskBase.cpp @@ -21,7 +21,7 @@ RTEMSTaskBase::RTEMSTaskBase(rtems_task_priority set_priority, size_t stack_size RTEMS_FLOATING_POINT, &id); } ReturnValue_t result = convertReturnCode(status); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "TaskBase::TaskBase: createTask with name " << std::hex << osalName << std::dec << " failed with return code " << (uint32_t)status << std::endl; @@ -32,7 +32,7 @@ RTEMSTaskBase::RTEMSTaskBase(rtems_task_priority set_priority, size_t stack_size RTEMSTaskBase::~RTEMSTaskBase() { rtems_task_delete(id); } -rtems_id RTEMSTaskBase::getId() { return this->id; } +rtems_id RTEMSTaskBase::getId() const { return this->id; } ReturnValue_t RTEMSTaskBase::sleepFor(uint32_t ms) { rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms)); @@ -42,21 +42,21 @@ ReturnValue_t RTEMSTaskBase::sleepFor(uint32_t ms) { ReturnValue_t RTEMSTaskBase::convertReturnCode(rtems_status_code inValue) { switch (inValue) { case RTEMS_SUCCESSFUL: - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; case RTEMS_MP_NOT_CONFIGURED: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_INVALID_NAME: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_TOO_MANY: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_INVALID_ADDRESS: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_UNSATISFIED: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; case RTEMS_INVALID_PRIORITY: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } diff --git a/src/fsfw/osal/rtems/RTEMSTaskBase.h b/src/fsfw/osal/rtems/RTEMSTaskBase.h index 9ae9e755..ed9972d3 100644 --- a/src/fsfw/osal/rtems/RTEMSTaskBase.h +++ b/src/fsfw/osal/rtems/RTEMSTaskBase.h @@ -36,9 +36,9 @@ class RTEMSTaskBase { /** * @brief This method returns the task id of this class. */ - rtems_id getId(); + rtems_id getId() const; - ReturnValue_t sleepFor(uint32_t ms); + static ReturnValue_t sleepFor(uint32_t ms); static ReturnValue_t setAndStartPeriod(rtems_interval period, rtems_id *periodId); static rtems_status_code restartPeriod(rtems_interval period, rtems_id periodId); diff --git a/src/fsfw/osal/rtems/RtemsBasic.h b/src/fsfw/osal/rtems/RtemsBasic.h index 3525799c..ea97c3af 100644 --- a/src/fsfw/osal/rtems/RtemsBasic.h +++ b/src/fsfw/osal/rtems/RtemsBasic.h @@ -8,7 +8,7 @@ #include -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" class RtemsBasic { public: diff --git a/src/fsfw/osal/rtems/SemaphoreFactory.cpp b/src/fsfw/osal/rtems/SemaphoreFactory.cpp index 35099ddc..1e470f40 100644 --- a/src/fsfw/osal/rtems/SemaphoreFactory.cpp +++ b/src/fsfw/osal/rtems/SemaphoreFactory.cpp @@ -1,5 +1,5 @@ #include "fsfw/osal/rtems/BinarySemaphore.h" -//#include "fsfw/osal/rtems/CountingSemaphore.h" +// #include "fsfw/osal/rtems/CountingSemaphore.h" #include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/tasks/SemaphoreFactory.h" diff --git a/src/fsfw/osal/rtems/TaskFactory.cpp b/src/fsfw/osal/rtems/TaskFactory.cpp index 8bfd53ed..4dbd254e 100644 --- a/src/fsfw/osal/rtems/TaskFactory.cpp +++ b/src/fsfw/osal/rtems/TaskFactory.cpp @@ -1,49 +1,46 @@ #include "fsfw/tasks/TaskFactory.h" #include "fsfw/osal/rtems/FixedTimeslotTask.h" -#include "fsfw/osal/rtems/InitTask.h" #include "fsfw/osal/rtems/PeriodicTask.h" #include "fsfw/osal/rtems/RtemsBasic.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" // TODO: Different variant than the lazy loading in QueueFactory. What's better and why? TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); -TaskFactory::~TaskFactory() {} +TaskFactory::TaskFactory() = default; + +TaskFactory::~TaskFactory() = default; TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; } PeriodicTaskIF* TaskFactory::createPeriodicTask( TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_, TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) { - rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond(); - - return static_cast( - new PeriodicTask(name_, taskPriority_, stackSize_, taskPeriod, deadLineMissedFunction_)); + return static_cast(new PeriodicTask(name_, taskPriority_, stackSize_, + periodInSeconds_, deadLineMissedFunction_)); } FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask( TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_, TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) { - rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond(); - return static_cast( - new FixedTimeslotTask(name_, taskPriority_, stackSize_, taskPeriod, deadLineMissedFunction_)); + return static_cast(new FixedTimeslotTask( + name_, taskPriority_, stackSize_, periodInSeconds_, deadLineMissedFunction_)); } ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { - // TODO not implemented - return HasReturnvaluesIF::RETURN_FAILED; + // This should call the OS specific destructor + delete (dynamic_cast(task)); + return returnvalue::FAILED; } ReturnValue_t TaskFactory::delayTask(uint32_t delayMs) { rtems_task_wake_after(RtemsBasic::convertMsToTicks(delayMs)); // Only return value is "RTEMS_SUCCESSFUL - always successful" so it has been neglected - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void TaskFactory::printMissedDeadline() { /* TODO: Implement */ return; } - -TaskFactory::TaskFactory() {} diff --git a/src/fsfw/osal/windows/CMakeLists.txt b/src/fsfw/osal/windows/CMakeLists.txt index 36a54765..e961b25b 100644 --- a/src/fsfw/osal/windows/CMakeLists.txt +++ b/src/fsfw/osal/windows/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - tcpipHelpers.cpp - winTaskHelpers.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE tcpipHelpers.cpp winTaskHelpers.cpp) diff --git a/src/fsfw/osal/windows/winTaskHelpers.cpp b/src/fsfw/osal/windows/winTaskHelpers.cpp index c863c4ca..235dca1e 100644 --- a/src/fsfw/osal/windows/winTaskHelpers.cpp +++ b/src/fsfw/osal/windows/winTaskHelpers.cpp @@ -1,5 +1,7 @@ #include "fsfw/osal/windows/winTaskHelpers.h" +#include + #include TaskPriority tasks::makeWinPriority(PriorityClass prioClass, PriorityNumber prioNumber) { @@ -89,7 +91,7 @@ ReturnValue_t tasks::setTaskPriority(HANDLE nativeHandle, TaskPriority priority) #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " << GetLastError() << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; #endif } result = SetThreadPriority(reinterpret_cast(nativeHandle), nPriorityNumber); @@ -97,8 +99,8 @@ ReturnValue_t tasks::setTaskPriority(HANDLE nativeHandle, TaskPriority priority) #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " << GetLastError() << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; #endif } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/src/fsfw/osal/windows/winTaskHelpers.h b/src/fsfw/osal/windows/winTaskHelpers.h index 87cd92ce..2d6ef9b4 100644 --- a/src/fsfw/osal/windows/winTaskHelpers.h +++ b/src/fsfw/osal/windows/winTaskHelpers.h @@ -1,10 +1,12 @@ #include #include -#include "../../tasks/TaskFactory.h" +#include "fsfw/tasks/TaskFactory.h" #ifdef _WIN32 +#include + namespace tasks { enum PriorityClass : uint16_t { diff --git a/src/fsfw/parameters/CMakeLists.txt b/src/fsfw/parameters/CMakeLists.txt index fb5e4590..98a8085c 100644 --- a/src/fsfw/parameters/CMakeLists.txt +++ b/src/fsfw/parameters/CMakeLists.txt @@ -1,6 +1,3 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - ParameterHelper.cpp - ParameterMessage.cpp - ParameterWrapper.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} PRIVATE ParameterHelper.cpp ParameterMessage.cpp + ParameterWrapper.cpp) diff --git a/src/fsfw/parameters/HasParametersIF.h b/src/fsfw/parameters/HasParametersIF.h index 48557b4a..d586ceba 100644 --- a/src/fsfw/parameters/HasParametersIF.h +++ b/src/fsfw/parameters/HasParametersIF.h @@ -3,7 +3,7 @@ #include -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "ParameterWrapper.h" /** diff --git a/src/fsfw/parameters/ParameterHelper.cpp b/src/fsfw/parameters/ParameterHelper.cpp index 58356af5..ba0e70a4 100644 --- a/src/fsfw/parameters/ParameterHelper.cpp +++ b/src/fsfw/parameters/ParameterHelper.cpp @@ -10,10 +10,10 @@ ParameterHelper::~ParameterHelper() {} ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage* message) { if (storage == nullptr) { // ParameterHelper was not initialized - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t result = returnvalue::FAILED; switch (message->getCommand()) { case ParameterMessage::CMD_PARAMETER_DUMP: { ParameterWrapper description; @@ -21,7 +21,7 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage* message) { uint8_t uniqueIdentifier = HasParametersIF::getUniqueIdentifierId(ParameterMessage::getParameterId(message)); result = owner->getParameter(domain, uniqueIdentifier, &description, &description, 0); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { result = sendParameter(message->getSender(), ParameterMessage::getParameterId(message), &description); } @@ -42,7 +42,7 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage* message) { ConstStorageAccessor accessor(storeId); result = storage->getData(storeId, accessor); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "ParameterHelper::handleParameterMessage: Getting" << " store data failed for load command." << std::endl; @@ -52,19 +52,19 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage* message) { ParameterWrapper streamWrapper; result = streamWrapper.set(type, rows, columns, accessor.data(), accessor.size()); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } ParameterWrapper ownerWrapper; result = owner->getParameter(domain, uniqueIdentifier, &ownerWrapper, &streamWrapper, linearIndex); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = ownerWrapper.copyFrom(&streamWrapper, linearIndex); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -73,14 +73,14 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage* message) { break; } default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { rejectCommand(message->getSender(), result, message->getCommand()); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id, @@ -91,7 +91,7 @@ ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id, store_address_t address; ReturnValue_t result = storage->getFreeElement(&address, serializedSize, &storeElement); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -100,7 +100,7 @@ ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id, result = description->serialize(&storeElement, &storeElementSize, serializedSize, SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { storage->deleteData(address); return result; } @@ -111,7 +111,7 @@ ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id, MessageQueueSenderIF::sendMessage(to, &reply, ownerQueueId); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t ParameterHelper::initialize() { @@ -121,7 +121,7 @@ ReturnValue_t ParameterHelper::initialize() { if (storage == nullptr) { return ObjectManagerIF::CHILD_INIT_FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void ParameterHelper::rejectCommand(MessageQueueId_t to, ReturnValue_t reason, diff --git a/src/fsfw/parameters/ParameterMessage.cpp b/src/fsfw/parameters/ParameterMessage.cpp index 9dc58365..9a7b5288 100644 --- a/src/fsfw/parameters/ParameterMessage.cpp +++ b/src/fsfw/parameters/ParameterMessage.cpp @@ -44,7 +44,7 @@ store_address_t ParameterMessage::getParameterLoadCommand(const CommandMessage* *pfc = packedParamSettings >> 16 & 0xff; *rows = packedParamSettings >> 8 & 0xff; *columns = packedParamSettings & 0xff; - return message->getParameter2(); + return static_cast(message->getParameter2()); } void ParameterMessage::clear(CommandMessage* message) { diff --git a/src/fsfw/parameters/ParameterWrapper.cpp b/src/fsfw/parameters/ParameterWrapper.cpp index 27552290..522a68b1 100644 --- a/src/fsfw/parameters/ParameterWrapper.cpp +++ b/src/fsfw/parameters/ParameterWrapper.cpp @@ -28,16 +28,16 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t **buffer, size_t *size, size_t ReturnValue_t result; result = SerializeAdapter::serialize(&type, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&columns, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&rows, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -91,11 +91,11 @@ template ReturnValue_t ParameterWrapper::serializeData(uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) const { const T *element = (const T *)readonlyData; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; uint16_t dataSize = columns * rows; while (dataSize != 0) { result = SerializeAdapter::serialize(element, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } element++; @@ -112,7 +112,7 @@ ReturnValue_t ParameterWrapper::deSerializeData(uint8_t startingRow, uint8_t sta const uint8_t *fromAsStream = reinterpret_cast(from); size_t streamSize = fromRows * fromColumns * sizeof(T); - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; for (uint8_t fromRow = 0; fromRow < fromRows; fromRow++) { // get the start element of this row in data @@ -122,7 +122,7 @@ ReturnValue_t ParameterWrapper::deSerializeData(uint8_t startingRow, uint8_t sta for (uint8_t fromColumn = 0; fromColumn < fromColumns; fromColumn++) { result = SerializeAdapter::deSerialize(dataWithDataType + fromColumn, &fromAsStream, &streamSize, SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } } @@ -142,7 +142,7 @@ ReturnValue_t ParameterWrapper::deSerialize(const uint8_t **buffer, size_t *size ParameterWrapper streamDescription; ReturnValue_t result = streamDescription.set(*buffer, *size, buffer, size); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -163,24 +163,24 @@ ReturnValue_t ParameterWrapper::set(Type type, uint8_t rows, uint8_t columns, co this->data = nullptr; this->readonlyData = data; pointsToStream = true; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t ParameterWrapper::set(const uint8_t *stream, size_t streamSize, const uint8_t **remainingStream, size_t *remainingSize) { ReturnValue_t result = SerializeAdapter::deSerialize(&type, &stream, &streamSize, SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::deSerialize(&columns, &stream, &streamSize, SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::deSerialize(&rows, &stream, &streamSize, SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -203,7 +203,7 @@ ReturnValue_t ParameterWrapper::set(const uint8_t *stream, size_t streamSize, *remainingSize = streamSize; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from, @@ -265,7 +265,7 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from, uint8_t typeSize = type.getSize(); - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t result = returnvalue::FAILED; // copy data if (from->pointsToStream) { switch (type) { diff --git a/src/fsfw/parameters/ParameterWrapper.h b/src/fsfw/parameters/ParameterWrapper.h index 873db7b2..05251b8a 100644 --- a/src/fsfw/parameters/ParameterWrapper.h +++ b/src/fsfw/parameters/ParameterWrapper.h @@ -4,7 +4,7 @@ #include #include "../globalfunctions/Type.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeIF.h" @@ -40,13 +40,15 @@ class ParameterWrapper : public SerializeIF { ParameterWrapper(Type type, uint8_t rows, uint8_t columns, const void *data); virtual ~ParameterWrapper(); - virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const override; + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override; - virtual size_t getSerializedSize() const override; + size_t getSerializedSize() const override; - virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, - Endianness streamEndianness) override; + using SerializeIF::deSerialize; // we overloaded this function, so this is needed to unconfuse + // the compiler + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override; virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, Endianness streamEndianness, uint16_t startWritingAtIndex = 0); @@ -58,7 +60,7 @@ class ParameterWrapper : public SerializeIF { * @param row * @param column * @return - * -@c RETURN_OK if element was retrieved successfully + * -@c returnvalue::OK if element was retrieved successfully * -@c NOT_SET data has not been set yet * -@c DATATYPE_MISSMATCH Invalid supplied type * -@c OUT_OF_BOUNDS Invalid row and/or column. @@ -185,7 +187,7 @@ inline ReturnValue_t ParameterWrapper::getElement(T *value, uint8_t row, uint8_t } else { const T *dataWithType = static_cast(readonlyData); *value = dataWithType[row * columns + column]; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } } diff --git a/src/fsfw/power/CMakeLists.txt b/src/fsfw/power/CMakeLists.txt index 1c625db1..b4ab0006 100644 --- a/src/fsfw/power/CMakeLists.txt +++ b/src/fsfw/power/CMakeLists.txt @@ -1,7 +1,4 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - Fuse.cpp - PowerComponent.cpp - PowerSensor.cpp - PowerSwitcher.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE Fuse.cpp PowerComponent.cpp PowerSensor.cpp PowerSwitcher.cpp + DummyPowerSwitcher.cpp PowerSwitcherComponent.cpp) diff --git a/src/fsfw/power/DummyPowerSwitcher.cpp b/src/fsfw/power/DummyPowerSwitcher.cpp new file mode 100644 index 00000000..952a5a57 --- /dev/null +++ b/src/fsfw/power/DummyPowerSwitcher.cpp @@ -0,0 +1,47 @@ +#include "DummyPowerSwitcher.h" + +DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches, + size_t numberOfFuses, bool registerGlobally, + uint32_t switchDelayMs) + : SystemObject(objectId, registerGlobally), + switcherList(numberOfSwitches), + fuseList(numberOfFuses), + switchDelayMs(switchDelayMs) {} + +void DummyPowerSwitcher::setInitialSwitcherList(std::vector switcherList) { + this->switcherList = switcherList; +} + +void DummyPowerSwitcher::setInitialFusesList(std::vector fuseList) { + this->fuseList = fuseList; +} + +ReturnValue_t DummyPowerSwitcher::sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) { + if (switchNr < switcherList.size()) { + switcherList[switchNr] = onOff; + } + return returnvalue::FAILED; +} + +ReturnValue_t DummyPowerSwitcher::sendFuseOnCommand(uint8_t fuseNr) { + if (fuseNr < fuseList.size()) { + fuseList[fuseNr] = FUSE_ON; + } + return returnvalue::FAILED; +} + +ReturnValue_t DummyPowerSwitcher::getSwitchState(power::Switch_t switchNr) const { + if (switchNr < switcherList.size()) { + return switcherList[switchNr]; + } + return returnvalue::FAILED; +} + +ReturnValue_t DummyPowerSwitcher::getFuseState(uint8_t fuseNr) const { + if (fuseNr < fuseList.size()) { + return fuseList[fuseNr]; + } + return returnvalue::FAILED; +} + +uint32_t DummyPowerSwitcher::getSwitchDelayMs(void) const { return switchDelayMs; } diff --git a/src/fsfw/power/DummyPowerSwitcher.h b/src/fsfw/power/DummyPowerSwitcher.h new file mode 100644 index 00000000..6ccd8dd7 --- /dev/null +++ b/src/fsfw/power/DummyPowerSwitcher.h @@ -0,0 +1,38 @@ +#ifndef FSFW_SRC_FSFW_POWER_DUMMYPOWERSWITCHER_H_ +#define FSFW_SRC_FSFW_POWER_DUMMYPOWERSWITCHER_H_ + +#include +#include + +#include "PowerSwitchIF.h" +#include "definitions.h" +#include "fsfw/objectmanager/SystemObject.h" + +/** + * @brief This component can be used to simulate a power switcher like a + * Power Control Distribution Unit (PCDU) + * @details + * The dummy switcher will simply cache the commanded fuse and switch states and return them + * in the according switch getter functions. In that sense, it simulates an ideal PCDU. + */ +class DummyPowerSwitcher : public SystemObject, public PowerSwitchIF { + public: + DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches, size_t numberOfFuses, + bool registerGlobally = true, uint32_t switchDelayMs = 5000); + + void setInitialSwitcherList(std::vector switcherList); + void setInitialFusesList(std::vector switcherList); + + virtual ReturnValue_t sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) override; + virtual ReturnValue_t sendFuseOnCommand(uint8_t fuseNr) override; + virtual ReturnValue_t getSwitchState(power::Switch_t switchNr) const override; + virtual ReturnValue_t getFuseState(uint8_t fuseNr) const override; + virtual uint32_t getSwitchDelayMs(void) const override; + + private: + std::vector switcherList; + std::vector fuseList; + uint32_t switchDelayMs = 5000; +}; + +#endif /* FSFW_SRC_FSFW_POWER_DUMMYPOWERSWITCHER_H_ */ diff --git a/src/fsfw/power/Fuse.cpp b/src/fsfw/power/Fuse.cpp index 81b51c89..73b29452 100644 --- a/src/fsfw/power/Fuse.cpp +++ b/src/fsfw/power/Fuse.cpp @@ -32,22 +32,22 @@ void Fuse::addDevice(PowerComponentIF* switchSet) { devices.push_back(switchSet) ReturnValue_t Fuse::initialize() { ReturnValue_t result = SystemObject::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = parameterHelper.initialize(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = healthHelper.initialize(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } powerIF = ObjectManager::instance()->get(powerSwitchId); if (powerIF == NULL) { - return RETURN_FAILED; + return returnvalue::FAILED; } - return RETURN_OK; + return returnvalue::OK; } void Fuse::calculatePowerLimits(float* low, float* high) { @@ -66,7 +66,7 @@ ReturnValue_t Fuse::check() { set.setValidity(false, true); return set.commit(); } - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; checkFuseState(); calculateFusePower(); // Check if power is valid and if fuse state is off or invalid. @@ -89,14 +89,14 @@ ReturnValue_t Fuse::check() { ReturnValue_t Fuse::serialize(uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness) const { - ReturnValue_t result = RETURN_FAILED; + ReturnValue_t result = returnvalue::FAILED; for (DeviceList::const_iterator iter = devices.begin(); iter != devices.end(); iter++) { result = (*iter)->serialize(buffer, size, maxSize, streamEndianness); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } } - return RETURN_OK; + return returnvalue::OK; } size_t Fuse::getSerializedSize() const { @@ -108,21 +108,21 @@ size_t Fuse::getSerializedSize() const { } ReturnValue_t Fuse::deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { - ReturnValue_t result = RETURN_FAILED; + ReturnValue_t result = returnvalue::FAILED; for (DeviceList::iterator iter = devices.begin(); iter != devices.end(); iter++) { result = (*iter)->deSerialize(buffer, size, streamEndianness); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } } - return RETURN_OK; + return returnvalue::OK; } uint8_t Fuse::getFuseId() const { return fuseId; } void Fuse::calculateFusePower() { ReturnValue_t result1 = currentLimit.check(); - if (result1 != HasReturnvaluesIF::RETURN_OK || !(voltage.isValid())) { + if (result1 != returnvalue::OK || !(voltage.isValid())) { power.setValid(PoolVariableIF::INVALID); return; } @@ -133,7 +133,7 @@ void Fuse::calculateFusePower() { ReturnValue_t Fuse::performOperation(uint8_t opCode) { checkCommandQueue(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void Fuse::reportEvents(Event event) { @@ -157,15 +157,15 @@ void Fuse::setAllMonitorsToUnchecked() { void Fuse::checkCommandQueue() { CommandMessage command; ReturnValue_t result = commandQueue->receiveMessage(&command); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return; } result = healthHelper.handleHealthCommand(&command); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { return; } result = parameterHelper.handleParameterMessage(&command); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { return; } command.setToUnknownCommand(); @@ -227,7 +227,7 @@ bool Fuse::isPowerValid() { return power.isValid(); } ReturnValue_t Fuse::setHealth(HealthState health) { healthHelper.setHealth(health); - return RETURN_OK; + return returnvalue::OK; } HasHealthIF::HealthState Fuse::getHealth() { return healthHelper.getHealth(); } @@ -238,6 +238,6 @@ ReturnValue_t Fuse::PowerMonitor::checkPower(float sample, float lowerLimit, flo } else if (sample < lowerLimit) { return this->monitorStateIs(MonitoringIF::BELOW_LOW_LIMIT, sample, lowerLimit); } else { - return this->monitorStateIs(RETURN_OK, sample, 0.0); // Within limits. + return this->monitorStateIs(returnvalue::OK, sample, 0.0); // Within limits. } } diff --git a/src/fsfw/power/Fuse.h b/src/fsfw/power/Fuse.h index e6f9c149..c1b35899 100644 --- a/src/fsfw/power/Fuse.h +++ b/src/fsfw/power/Fuse.h @@ -7,7 +7,7 @@ #include "../devicehandlers/HealthDevice.h" #include "../monitoring/AbsLimitMonitor.h" #include "../parameters/ParameterHelper.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "PowerComponentIF.h" #include "PowerSwitchIF.h" namespace Factory { @@ -16,7 +16,6 @@ void setStaticFrameworkObjectIds(); class Fuse : public SystemObject, public HasHealthIF, - public HasReturnvaluesIF, public ReceivesParameterMessagesIF, public SerializeIF { friend void(Factory::setStaticFrameworkObjectIds)(); @@ -33,15 +32,15 @@ class Fuse : public SystemObject, gp_id_t poolIdPower; }; - 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. + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::POWER_SWITCH_IF; + //! 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 DeviceList; Fuse(object_id_t fuseObjectId, uint8_t fuseId, sid_t variableSet, VariableIds ids, @@ -54,7 +53,7 @@ class Fuse : public SystemObject, ReturnValue_t check(); uint8_t getFuseId() const; - ReturnValue_t initialize(); + ReturnValue_t initialize() override; DeviceList devices; ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, SerializeIF::Endianness streamEndianness) const override; diff --git a/src/fsfw/power/PowerComponent.cpp b/src/fsfw/power/PowerComponent.cpp index e4c336c7..fd780841 100644 --- a/src/fsfw/power/PowerComponent.cpp +++ b/src/fsfw/power/PowerComponent.cpp @@ -18,7 +18,7 @@ ReturnValue_t PowerComponent::serialize(uint8_t** buffer, size_t* size, size_t m Endianness streamEndianness) const { ReturnValue_t result = SerializeAdapter::serialize(&minPower, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return SerializeAdapter::serialize(&maxPower, buffer, size, maxSize, streamEndianness); @@ -41,7 +41,7 @@ float PowerComponent::getMax() { return maxPower; } ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::deSerialize(&minPower, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return SerializeAdapter::deSerialize(&maxPower, buffer, size, streamEndianness); @@ -64,5 +64,5 @@ ReturnValue_t PowerComponent::getParameter(uint8_t domainId, uint8_t uniqueId, default: return INVALID_IDENTIFIER_ID; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/src/fsfw/power/PowerSensor.cpp b/src/fsfw/power/PowerSensor.cpp index 08ff4724..69c9e272 100644 --- a/src/fsfw/power/PowerSensor.cpp +++ b/src/fsfw/power/PowerSensor.cpp @@ -22,8 +22,8 @@ PowerSensor::~PowerSensor() { QueueFactory::instance()->deleteMessageQueue(comma ReturnValue_t PowerSensor::calculatePower() { powerSensorSet.read(); - ReturnValue_t result1 = HasReturnvaluesIF::RETURN_FAILED; - ReturnValue_t result2 = HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t result1 = returnvalue::FAILED; + ReturnValue_t result2 = returnvalue::FAILED; if (healthHelper.healthTable->isHealthy(getObjectId()) && voltage.isValid() && current.isValid()) { result1 = voltageLimit.doCheck(voltage.value); @@ -33,7 +33,7 @@ ReturnValue_t PowerSensor::calculatePower() { currentLimit.setToInvalid(); result1 = OBJECT_NOT_HEALTHY; } - if (result1 != HasReturnvaluesIF::RETURN_OK || result2 != HasReturnvaluesIF::RETURN_OK) { + if (result1 != returnvalue::OK || result2 != returnvalue::OK) { result1 = MonitoringIF::INVALID; power.setValid(PoolVariableIF::INVALID); } else { @@ -46,22 +46,22 @@ ReturnValue_t PowerSensor::calculatePower() { ReturnValue_t PowerSensor::performOperation(uint8_t opCode) { checkCommandQueue(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } MessageQueueId_t PowerSensor::getCommandQueue() const { return commandQueue->getId(); } ReturnValue_t PowerSensor::initialize() { ReturnValue_t result = SystemObject::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = healthHelper.initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = parameterHelper.initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return result; @@ -75,15 +75,15 @@ void PowerSensor::setAllMonitorsToUnchecked() { void PowerSensor::checkCommandQueue() { CommandMessage command; ReturnValue_t result = commandQueue->receiveMessage(&command); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return; } result = healthHelper.handleHealthCommand(&command); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { return; } result = parameterHelper.handleParameterMessage(&command); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { return; } command.setToUnknownCommand(); @@ -106,7 +106,7 @@ float PowerSensor::getPower() { ReturnValue_t PowerSensor::setHealth(HealthState health) { healthHelper.setHealth(health); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } HasHealthIF::HealthState PowerSensor::getHealth() { return healthHelper.getHealth(); } diff --git a/src/fsfw/power/PowerSwitchIF.h b/src/fsfw/power/PowerSwitchIF.h index a31d8971..0b331e11 100644 --- a/src/fsfw/power/PowerSwitchIF.h +++ b/src/fsfw/power/PowerSwitchIF.h @@ -2,7 +2,8 @@ #define FSFW_POWER_POWERSWITCHIF_H_ #include "../events/Event.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" +#include "definitions.h" /** * * @brief This interface defines a connection to a device that is capable of @@ -12,14 +13,14 @@ * because they can be called asynchronosuly (const ending). * @ingroup interfaces */ -class PowerSwitchIF : public HasReturnvaluesIF { +class PowerSwitchIF { public: /** * Empty dtor. */ virtual ~PowerSwitchIF() {} /** - * The Returnvalues id of this class, required by HasReturnvaluesIF + * The Returnvalues id of this class */ static const uint8_t INTERFACE_ID = CLASS_ID::POWER_SWITCH_IF; static const ReturnValue_t SWITCH_ON = MAKE_RETURN_CODE(1); @@ -27,21 +28,23 @@ class PowerSwitchIF : public HasReturnvaluesIF { static const ReturnValue_t SWITCH_TIMEOUT = MAKE_RETURN_CODE(2); static const ReturnValue_t FUSE_ON = MAKE_RETURN_CODE(3); static const ReturnValue_t FUSE_OFF = MAKE_RETURN_CODE(4); - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_2; - static const Event SWITCH_WENT_OFF = MAKE_EVENT( - 0, severity::LOW); //!< Someone detected that a switch went off which shouldn't. Severity: - //!< Low, Parameter1: switchId1, Parameter2: switchId2 + static const ReturnValue_t SWITCH_UNKNOWN = MAKE_RETURN_CODE(5); + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::POWER_SWITCH_IF; + //!< Someone detected that a switch went off which shouldn't. Severity: + //!< Low, Parameter1: switchId1, Parameter2: switchId2 + static const Event SWITCH_WENT_OFF = MAKE_EVENT(0, severity::LOW); /** * send a direct command to the Power Unit to enable/disable the specified switch. * * @param switchNr * @param onOff on == @c SWITCH_ON; off != @c SWITCH_ON */ - virtual void sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) const = 0; + virtual ReturnValue_t sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) = 0; /** * Sends a command to the Power Unit to enable a certain fuse. */ - virtual void sendFuseOnCommand(uint8_t fuseNr) const = 0; + virtual ReturnValue_t sendFuseOnCommand(uint8_t fuseNr) = 0; /** * get the state of the Switches. @@ -49,16 +52,17 @@ class PowerSwitchIF : public HasReturnvaluesIF { * @return * - @c SWITCH_ON if the specified switch is on. * - @c SWITCH_OFF if the specified switch is off. - * - @c RETURN_FAILED if an error occured + * - @c SWITCH_UNKNOWN if the state of the specified switch is unknown. + * - @c returnvalue::FAILED if an error occured */ - virtual ReturnValue_t getSwitchState(uint8_t switchNr) const = 0; + virtual ReturnValue_t getSwitchState(power::Switch_t switchNr) const = 0; /** * get state of a fuse. * @param fuseNr * @return * - @c FUSE_ON if the specified fuse is on. * - @c FUSE_OFF if the specified fuse is off. - * - @c RETURN_FAILED if an error occured + * - @c returnvalue::FAILED if an error occured */ virtual ReturnValue_t getFuseState(uint8_t fuseNr) const = 0; /** diff --git a/src/fsfw/power/PowerSwitcher.cpp b/src/fsfw/power/PowerSwitcher.cpp index 0a3f8521..77733884 100644 --- a/src/fsfw/power/PowerSwitcher.cpp +++ b/src/fsfw/power/PowerSwitcher.cpp @@ -1,19 +1,12 @@ #include "fsfw/power/PowerSwitcher.h" +#include "definitions.h" #include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/serviceinterface/ServiceInterface.h" -PowerSwitcher::PowerSwitcher(uint8_t setSwitch1, uint8_t setSwitch2, - PowerSwitcher::State_t setStartState) - : state(setStartState), firstSwitch(setSwitch1), secondSwitch(setSwitch2) {} - -ReturnValue_t PowerSwitcher::initialize(object_id_t powerSwitchId) { - power = ObjectManager::instance()->get(powerSwitchId); - if (power == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - return HasReturnvaluesIF::RETURN_OK; -} +PowerSwitcher::PowerSwitcher(PowerSwitchIF* switcher, power::Switch_t setSwitch1, + power::Switch_t setSwitch2, PowerSwitcher::State_t setStartState) + : power(switcher), state(setStartState), firstSwitch(setSwitch1), secondSwitch(setSwitch2) {} ReturnValue_t PowerSwitcher::getStateOfSwitches() { SwitchReturn_t result = howManySwitches(); @@ -31,11 +24,11 @@ ReturnValue_t PowerSwitcher::getStateOfSwitches() { (secondSwitchState == PowerSwitchIF::SWITCH_OFF)) { return PowerSwitchIF::SWITCH_OFF; } else { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -52,18 +45,37 @@ void PowerSwitcher::commandSwitches(ReturnValue_t onOff) { return; } -void PowerSwitcher::turnOn() { +void PowerSwitcher::turnOn(bool checkCurrentState) { + if (checkCurrentState) { + if (getStateOfSwitches() == PowerSwitchIF::SWITCH_ON) { + state = SWITCH_IS_ON; + return; + } + } commandSwitches(PowerSwitchIF::SWITCH_ON); state = WAIT_ON; } -void PowerSwitcher::turnOff() { +void PowerSwitcher::turnOff(bool checkCurrentState) { + if (checkCurrentState) { + if (getStateOfSwitches() == PowerSwitchIF::SWITCH_OFF) { + state = SWITCH_IS_OFF; + return; + } + } commandSwitches(PowerSwitchIF::SWITCH_OFF); state = WAIT_OFF; } +bool PowerSwitcher::active() { + if (state == WAIT_OFF or state == WAIT_ON) { + return true; + } + return false; +} + PowerSwitcher::SwitchReturn_t PowerSwitcher::howManySwitches() { - if (secondSwitch == NO_SWITCH) { + if (secondSwitch == power::NO_SWITCH) { return ONE_SWITCH; } else { return TWO_SWITCHES; @@ -99,18 +111,18 @@ ReturnValue_t PowerSwitcher::checkSwitchState() { return IN_POWER_TRANSITION; case SWITCH_IS_OFF: if (getStateOfSwitches() == PowerSwitchIF::SWITCH_OFF) { - return RETURN_OK; + return returnvalue::OK; } else { return SWITCH_STATE_MISMATCH; } case SWITCH_IS_ON: if (getStateOfSwitches() == PowerSwitchIF::SWITCH_ON) { - return RETURN_OK; + return returnvalue::OK; } else { return SWITCH_STATE_MISMATCH; } } - return RETURN_FAILED; + return returnvalue::FAILED; } PowerSwitcher::State_t PowerSwitcher::getState() { return state; } diff --git a/src/fsfw/power/PowerSwitcher.h b/src/fsfw/power/PowerSwitcher.h index c72c241d..7a38336c 100644 --- a/src/fsfw/power/PowerSwitcher.h +++ b/src/fsfw/power/PowerSwitcher.h @@ -2,11 +2,11 @@ #define FSFW_POWER_POWERSWITCHER_H_ #include "../objectmanager/SystemObjectIF.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "../timemanager/Countdown.h" #include "PowerSwitchIF.h" -class PowerSwitcher : public HasReturnvaluesIF { +class PowerSwitcher { public: enum State_t { WAIT_OFF, @@ -14,28 +14,29 @@ class PowerSwitcher : public HasReturnvaluesIF { SWITCH_IS_OFF, SWITCH_IS_ON, }; - State_t state; + static const uint8_t INTERFACE_ID = CLASS_ID::POWER_SWITCHER; static const ReturnValue_t IN_POWER_TRANSITION = MAKE_RETURN_CODE(1); static const ReturnValue_t SWITCH_STATE_MISMATCH = MAKE_RETURN_CODE(2); - PowerSwitcher(uint8_t setSwitch1, uint8_t setSwitch2 = NO_SWITCH, + PowerSwitcher(PowerSwitchIF* switcher, power::Switch_t setSwitch1, + power::Switch_t setSwitch2 = power::NO_SWITCH, State_t setStartState = SWITCH_IS_OFF); - ReturnValue_t initialize(object_id_t powerSwitchId); - void turnOn(); - void turnOff(); + void turnOn(bool checkCurrentState = true); + void turnOff(bool checkCurrentState = true); + bool active(); void doStateMachine(); State_t getState(); ReturnValue_t checkSwitchState(); uint32_t getSwitchDelay(); - uint8_t getFirstSwitch() const; - uint8_t getSecondSwitch() const; + power::Switch_t getFirstSwitch() const; + power::Switch_t getSecondSwitch() const; private: - uint8_t firstSwitch; - uint8_t secondSwitch; PowerSwitchIF* power = nullptr; + State_t state; + power::Switch_t firstSwitch = power::NO_SWITCH; + power::Switch_t secondSwitch = power::NO_SWITCH; - static const uint8_t NO_SWITCH = 0xFF; enum SwitchReturn_t { ONE_SWITCH = 1, TWO_SWITCHES = 2 }; ReturnValue_t getStateOfSwitches(); void commandSwitches(ReturnValue_t onOff); diff --git a/src/fsfw/power/PowerSwitcherComponent.cpp b/src/fsfw/power/PowerSwitcherComponent.cpp new file mode 100644 index 00000000..b6b67a83 --- /dev/null +++ b/src/fsfw/power/PowerSwitcherComponent.cpp @@ -0,0 +1,107 @@ +#include "PowerSwitcherComponent.h" + +#include +#include + +PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher, + power::Switch_t pwrSwitch) + : SystemObject(objectId), + switcher(pwrSwitcher, pwrSwitch), + modeHelper(this), + healthHelper(this, objectId) { + queue = QueueFactory::instance()->createMessageQueue(); +} + +ReturnValue_t PowerSwitcherComponent::performOperation(uint8_t opCode) { + ReturnValue_t result; + CommandMessage command; + + for (result = queue->receiveMessage(&command); result == returnvalue::OK; + result = queue->receiveMessage(&command)) { + result = healthHelper.handleHealthCommand(&command); + if (result == returnvalue::OK) { + continue; + } + + result = modeHelper.handleModeCommand(&command); + if (result == returnvalue::OK) { + continue; + } + } + if (switcher.active()) { + switcher.doStateMachine(); + auto currState = switcher.getState(); + if (currState == PowerSwitcher::SWITCH_IS_OFF) { + setMode(MODE_OFF, 0); + } else if (currState == PowerSwitcher::SWITCH_IS_ON) { + setMode(MODE_ON, 0); + } + } + return returnvalue::OK; +} + +ReturnValue_t PowerSwitcherComponent::initialize() { + ReturnValue_t result = modeHelper.initialize(); + if (result != returnvalue::OK) { + return result; + } + result = healthHelper.initialize(); + if (result != returnvalue::OK) { + return result; + } + return SystemObject::initialize(); +} + +MessageQueueId_t PowerSwitcherComponent::getCommandQueue() const { return queue->getId(); } + +void PowerSwitcherComponent::getMode(Mode_t *mode, Submode_t *submode) { + *mode = this->mode; + *submode = this->submode; +} + +ReturnValue_t PowerSwitcherComponent::setHealth(HealthState health) { + healthHelper.setHealth(health); + return returnvalue::OK; +} + +ReturnValue_t PowerSwitcherComponent::checkModeCommand(Mode_t mode, Submode_t submode, + uint32_t *msToReachTheMode) { + *msToReachTheMode = 5000; + if (mode != MODE_ON and mode != MODE_OFF) { + return TRANS_NOT_ALLOWED; + } + return returnvalue::OK; +} + +void PowerSwitcherComponent::startTransition(Mode_t mode, Submode_t submode) { + if (mode == MODE_OFF) { + switcher.turnOff(true); + switcher.doStateMachine(); + if (switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) { + setMode(MODE_OFF, 0); + } + } else if (mode == MODE_ON) { + switcher.turnOn(true); + switcher.doStateMachine(); + if (switcher.getState() == PowerSwitcher::SWITCH_IS_ON) { + setMode(MODE_ON, 0); + } + } +} + +void PowerSwitcherComponent::setToExternalControl() { + healthHelper.setHealth(HasHealthIF::EXTERNAL_CONTROL); +} + +void PowerSwitcherComponent::announceMode(bool recursive) { + triggerEvent(MODE_INFO, mode, submode); +} + +void PowerSwitcherComponent::setMode(Mode_t newMode, Submode_t newSubmode) { + this->mode = newMode; + this->submode = newSubmode; + modeHelper.modeChanged(mode, submode); + announceMode(false); +} + +HasHealthIF::HealthState PowerSwitcherComponent::getHealth() { return healthHelper.getHealth(); } diff --git a/src/fsfw/power/PowerSwitcherComponent.h b/src/fsfw/power/PowerSwitcherComponent.h new file mode 100644 index 00000000..01689bef --- /dev/null +++ b/src/fsfw/power/PowerSwitcherComponent.h @@ -0,0 +1,61 @@ +#ifndef _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ +#define _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +class PowerSwitchIF; + +/** + * @brief Allows to create an power switch object with its own mode and health + * @details + * This basic component allows to create an object which is solely responsible for managing a + * switch. It also has a mode and a health by implementing the respective interface components + * which allows integrating this component into a system mode tree. + * + * Commanding this component to MODE_OFF will cause the switcher to turn the switch off while + * commanding in to MODE_ON will cause the switcher to turn the switch on. + */ +class PowerSwitcherComponent : public SystemObject, + public ExecutableObjectIF, + public HasModesIF, + public HasHealthIF { + public: + PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher, + power::Switch_t pwrSwitch); + + private: + MessageQueueIF *queue = nullptr; + PowerSwitcher switcher; + + Mode_t mode = MODE_OFF; + Submode_t submode = 0; + + ModeHelper modeHelper; + HealthHelper healthHelper; + + void setMode(Mode_t newMode, Submode_t newSubmode); + + virtual ReturnValue_t performOperation(uint8_t opCode) override; + + ReturnValue_t initialize() override; + + MessageQueueId_t getCommandQueue() const override; + void getMode(Mode_t *mode, Submode_t *submode) override; + ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, + uint32_t *msToReachTheMode) override; + void startTransition(Mode_t mode, Submode_t submode) override; + void setToExternalControl() override; + void announceMode(bool recursive) override; + + ReturnValue_t setHealth(HealthState health) override; + HasHealthIF::HealthState getHealth() override; +}; + +#endif /* _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ */ diff --git a/src/fsfw/power/definitions.h b/src/fsfw/power/definitions.h new file mode 100644 index 00000000..ed2a0037 --- /dev/null +++ b/src/fsfw/power/definitions.h @@ -0,0 +1,13 @@ +#ifndef FSFW_SRC_FSFW_POWER_DEFINITIONS_H_ +#define FSFW_SRC_FSFW_POWER_DEFINITIONS_H_ + +#include + +namespace power { + +using Switch_t = uint8_t; +static constexpr Switch_t NO_SWITCH = 0xFF; + +} // namespace power + +#endif /* FSFW_SRC_FSFW_POWER_DEFINITIONS_H_ */ diff --git a/src/fsfw/pus/CMakeLists.txt b/src/fsfw/pus/CMakeLists.txt index 8b55adf0..7c5b340c 100644 --- a/src/fsfw/pus/CMakeLists.txt +++ b/src/fsfw/pus/CMakeLists.txt @@ -1,12 +1,12 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - Service1TelecommandVerification.cpp - Service2DeviceAccess.cpp - Service3Housekeeping.cpp - Service5EventReporting.cpp - Service8FunctionManagement.cpp - Service9TimeManagement.cpp - Service17Test.cpp - Service20ParameterManagement.cpp - CService200ModeCommanding.cpp - CService201HealthCommanding.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE Service1TelecommandVerification.cpp + Service2DeviceAccess.cpp + Service3Housekeeping.cpp + Service5EventReporting.cpp + Service8FunctionManagement.cpp + Service9TimeManagement.cpp + Service17Test.cpp + Service20ParameterManagement.cpp + CService200ModeCommanding.cpp + CServiceHealthCommanding.cpp) diff --git a/src/fsfw/pus/CService200ModeCommanding.cpp b/src/fsfw/pus/CService200ModeCommanding.cpp index 41be3d13..0dbdedfe 100644 --- a/src/fsfw/pus/CService200ModeCommanding.cpp +++ b/src/fsfw/pus/CService200ModeCommanding.cpp @@ -10,8 +10,8 @@ CService200ModeCommanding::CService200ModeCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId, uint8_t numParallelCommands, uint16_t commandTimeoutSeconds) - : CommandingServiceBase(objectId, apid, serviceId, numParallelCommands, commandTimeoutSeconds) { -} + : CommandingServiceBase(objectId, apid, "PUS 200 Mode MGMT", serviceId, numParallelCommands, + commandTimeoutSeconds) {} CService200ModeCommanding::~CService200ModeCommanding() {} @@ -19,8 +19,9 @@ ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) { switch (subservice) { case (Subservice::COMMAND_MODE_COMMAND): case (Subservice::COMMAND_MODE_READ): - case (Subservice::COMMAND_MODE_ANNCOUNCE): - return RETURN_OK; + case (Subservice::COMMAND_MODE_ANNOUNCE): + case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY): + return returnvalue::OK; default: return AcceptsTelecommandsIF::INVALID_SUBSERVICE; } @@ -41,28 +42,44 @@ ReturnValue_t CService200ModeCommanding::getMessageQueueAndObject(uint8_t subser ReturnValue_t CService200ModeCommanding::checkInterfaceAndAcquireMessageQueue( MessageQueueId_t *messageQueueToSet, object_id_t *objectId) { - HasModesIF *destination = ObjectManager::instance()->get(*objectId); + auto *destination = ObjectManager::instance()->get(*objectId); if (destination == nullptr) { return CommandingServiceBase::INVALID_OBJECT; } *messageQueueToSet = destination->getCommandQueue(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message, uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, uint32_t *state, object_id_t objectId) { - ModePacket modeCommandPacket; - ReturnValue_t result = - modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG); - if (result != RETURN_OK) { - return result; - } + bool recursive = false; + switch (subservice) { + case (Subservice::COMMAND_MODE_COMMAND): { + ModePacket modeCommandPacket; + ReturnValue_t result = + modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG); + if (result != returnvalue::OK) { + return result; + } - ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(), - modeCommandPacket.getSubmode()); - return result; + ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND, + modeCommandPacket.getMode(), modeCommandPacket.getSubmode()); + return returnvalue::OK; + } + case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY): + recursive = true; + [[fallthrough]]; + case (Subservice::COMMAND_MODE_ANNOUNCE): + ModeMessage::setModeAnnounceMessage(*message, recursive); + return EXECUTION_COMPLETE; + case (Subservice::COMMAND_MODE_READ): + ModeMessage::setModeReadMessage(*message); + return returnvalue::OK; + default: + return CommandingServiceBase::INVALID_SUBSERVICE; + } } ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply, @@ -70,11 +87,13 @@ ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply CommandMessage *optionalNextCommand, object_id_t objectId, bool *isStep) { Command_t replyId = reply->getCommand(); - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t result = returnvalue::FAILED; switch (replyId) { case (ModeMessage::REPLY_MODE_REPLY): { - result = prepareModeReply(reply, objectId); - break; + if (previousCommand != ModeMessage::CMD_MODE_COMMAND) { + return prepareModeReply(reply, objectId); + } + return returnvalue::OK; } case (ModeMessage::REPLY_WRONG_MODE_REPLY): { result = prepareWrongModeReply(reply, objectId); @@ -88,7 +107,7 @@ ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply result = INVALID_REPLY; break; default: - result = RETURN_FAILED; + result = returnvalue::FAILED; } return result; } @@ -96,16 +115,16 @@ ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply ReturnValue_t CService200ModeCommanding::prepareModeReply(const CommandMessage *reply, object_id_t objectId) { ModePacket modeReplyPacket(objectId, ModeMessage::getMode(reply), ModeMessage::getSubmode(reply)); - return sendTmPacket(Subservice::REPLY_MODE_REPLY, &modeReplyPacket); + return sendTmPacket(Subservice::REPLY_MODE_REPLY, modeReplyPacket); } ReturnValue_t CService200ModeCommanding::prepareWrongModeReply(const CommandMessage *reply, object_id_t objectId) { ModePacket wrongModeReply(objectId, ModeMessage::getMode(reply), ModeMessage::getSubmode(reply)); - ReturnValue_t result = sendTmPacket(Subservice::REPLY_WRONG_MODE_REPLY, &wrongModeReply); - if (result == RETURN_OK) { + ReturnValue_t result = sendTmPacket(Subservice::REPLY_WRONG_MODE_REPLY, wrongModeReply); + if (result == returnvalue::OK) { // We want to produce an error here in any case because the mode was not correct - return RETURN_FAILED; + return returnvalue::FAILED; } return result; } @@ -113,10 +132,10 @@ ReturnValue_t CService200ModeCommanding::prepareWrongModeReply(const CommandMess ReturnValue_t CService200ModeCommanding::prepareCantReachModeReply(const CommandMessage *reply, object_id_t objectId) { CantReachModePacket cantReachModePacket(objectId, ModeMessage::getCantReachModeReason(reply)); - ReturnValue_t result = sendTmPacket(Subservice::REPLY_CANT_REACH_MODE, &cantReachModePacket); - if (result == RETURN_OK) { + ReturnValue_t result = sendTmPacket(Subservice::REPLY_CANT_REACH_MODE, cantReachModePacket); + if (result == returnvalue::OK) { // We want to produce an error here in any case because the mode was not reached - return RETURN_FAILED; + return returnvalue::FAILED; } return result; } diff --git a/src/fsfw/pus/CService200ModeCommanding.h b/src/fsfw/pus/CService200ModeCommanding.h index 830e5950..cf2baf7e 100644 --- a/src/fsfw/pus/CService200ModeCommanding.h +++ b/src/fsfw/pus/CService200ModeCommanding.h @@ -52,7 +52,7 @@ class CService200ModeCommanding : public CommandingServiceBase { COMMAND_MODE_READ = 3, //!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event. //! This command does NOT have a reply - COMMAND_MODE_ANNCOUNCE = 4, + COMMAND_MODE_ANNOUNCE = 4, //!< [EXPORT] : [COMMAND] Trigger a ModeInfo Event and to send this //! command to every child. This command does NOT have a reply. COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5, diff --git a/src/fsfw/pus/CService201HealthCommanding.cpp b/src/fsfw/pus/CService201HealthCommanding.cpp deleted file mode 100644 index 4d9806f9..00000000 --- a/src/fsfw/pus/CService201HealthCommanding.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include "fsfw/pus/CService201HealthCommanding.h" - -#include "fsfw/health/HasHealthIF.h" -#include "fsfw/health/HealthMessage.h" -#include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/pus/servicepackets/Service201Packets.h" -#include "fsfw/serviceinterface/ServiceInterface.h" - -CService201HealthCommanding::CService201HealthCommanding(object_id_t objectId, uint16_t apid, - uint8_t serviceId, - uint8_t numParallelCommands, - uint16_t commandTimeoutSeconds) - : CommandingServiceBase(objectId, apid, serviceId, numParallelCommands, commandTimeoutSeconds) { -} - -CService201HealthCommanding::~CService201HealthCommanding() {} - -ReturnValue_t CService201HealthCommanding::isValidSubservice(uint8_t subservice) { - switch (subservice) { - case (Subservice::COMMAND_SET_HEALTH): - case (Subservice::COMMAND_ANNOUNCE_HEALTH): - case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): - return RETURN_OK; - default: -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "Invalid Subservice" << std::endl; -#endif - return AcceptsTelecommandsIF::INVALID_SUBSERVICE; - } -} - -ReturnValue_t CService201HealthCommanding::getMessageQueueAndObject(uint8_t subservice, - const uint8_t *tcData, - size_t tcDataLen, - MessageQueueId_t *id, - object_id_t *objectId) { - if (tcDataLen < sizeof(object_id_t)) { - return CommandingServiceBase::INVALID_TC; - } - SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::BIG); - - return checkInterfaceAndAcquireMessageQueue(id, objectId); -} - -ReturnValue_t CService201HealthCommanding::checkInterfaceAndAcquireMessageQueue( - MessageQueueId_t *messageQueueToSet, object_id_t *objectId) { - HasHealthIF *destination = ObjectManager::instance()->get(*objectId); - if (destination == nullptr) { - return CommandingServiceBase::INVALID_OBJECT; - } - - *messageQueueToSet = destination->getCommandQueue(); - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t CService201HealthCommanding::prepareCommand(CommandMessage *message, - uint8_t subservice, const uint8_t *tcData, - size_t tcDataLen, uint32_t *state, - object_id_t objectId) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - switch (subservice) { - case (Subservice::COMMAND_SET_HEALTH): { - HealthSetCommand healthCommand; - result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG); - if (result != RETURN_OK) { - break; - } - HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_SET, - healthCommand.getHealth()); - break; - } - case (Subservice::COMMAND_ANNOUNCE_HEALTH): { - HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE); - break; - } - case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): { - HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE_ALL); - break; - } - } - return result; -} - -ReturnValue_t CService201HealthCommanding::handleReply(const CommandMessage *reply, - Command_t previousCommand, uint32_t *state, - CommandMessage *optionalNextCommand, - object_id_t objectId, bool *isStep) { - Command_t replyId = reply->getCommand(); - if (replyId == HealthMessage::REPLY_HEALTH_SET) { - return EXECUTION_COMPLETE; - } else if (replyId == CommandMessageIF::REPLY_REJECTED) { - return reply->getReplyRejectedReason(); - } - return CommandingServiceBase::INVALID_REPLY; -} - -// Not used for now, health state already reported by event -ReturnValue_t CService201HealthCommanding::prepareHealthSetReply(const CommandMessage *reply) { - prepareHealthSetReply(reply); - uint8_t health = static_cast(HealthMessage::getHealth(reply)); - uint8_t oldHealth = static_cast(HealthMessage::getOldHealth(reply)); - HealthSetReply healthSetReply(health, oldHealth); - return sendTmPacket(Subservice::REPLY_HEALTH_SET, &healthSetReply); -} diff --git a/src/fsfw/pus/CServiceHealthCommanding.cpp b/src/fsfw/pus/CServiceHealthCommanding.cpp new file mode 100644 index 00000000..3ced4ffb --- /dev/null +++ b/src/fsfw/pus/CServiceHealthCommanding.cpp @@ -0,0 +1,161 @@ +#include +#include + +#include "fsfw/health/HasHealthIF.h" +#include "fsfw/health/HealthMessage.h" +#include "fsfw/objectmanager/ObjectManager.h" +#include "fsfw/pus/servicepackets/Service201Packets.h" +#include "fsfw/serviceinterface/ServiceInterface.h" + +CServiceHealthCommanding::CServiceHealthCommanding(HealthServiceCfg args) + : CommandingServiceBase(args.objectId, args.apid, "PUS 201 Health MGMT", args.service, + args.numParallelCommands, args.commandTimeoutSeconds), + healthTableId(args.table), + maxNumHealthInfoPerCycle(args.maxNumHealthInfoPerCycle) {} + +ReturnValue_t CServiceHealthCommanding::initialize() { + ReturnValue_t result = CommandingServiceBase::initialize(); + if (result != returnvalue::OK) { + return result; + } + + healthTable = ObjectManager::instance()->get(healthTableId); + if (healthTable == nullptr) { + return returnvalue::FAILED; + } + + return returnvalue::OK; +} + +ReturnValue_t CServiceHealthCommanding::isValidSubservice(uint8_t subservice) { + switch (subservice) { + case (Subservice::COMMAND_SET_HEALTH): + case (Subservice::COMMAND_ANNOUNCE_HEALTH): + case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): + return returnvalue::OK; + default: +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "Invalid Subservice" << std::endl; +#endif + return AcceptsTelecommandsIF::INVALID_SUBSERVICE; + } +} + +ReturnValue_t CServiceHealthCommanding::getMessageQueueAndObject(uint8_t subservice, + const uint8_t *tcData, + size_t tcDataLen, + MessageQueueId_t *id, + object_id_t *objectId) { + switch (subservice) { + case (Subservice::COMMAND_SET_HEALTH): + case (Subservice::COMMAND_ANNOUNCE_HEALTH): { + if (tcDataLen < sizeof(object_id_t)) { + return CommandingServiceBase::INVALID_TC; + } + SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::BIG); + + return checkInterfaceAndAcquireMessageQueue(id, objectId); + } + case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): { + return returnvalue::OK; + } + default: { + return returnvalue::FAILED; + } + } +} + +ReturnValue_t CServiceHealthCommanding::checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t *messageQueueToSet, const object_id_t *objectId) { + auto *destination = ObjectManager::instance()->get(*objectId); + if (destination == nullptr) { + return CommandingServiceBase::INVALID_OBJECT; + } + + *messageQueueToSet = destination->getCommandQueue(); + return returnvalue::OK; +} + +ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message, uint8_t subservice, + const uint8_t *tcData, size_t tcDataLen, + uint32_t *state, object_id_t objectId) { + ReturnValue_t result = returnvalue::OK; + switch (subservice) { + case (Subservice::COMMAND_SET_HEALTH): { + if (tcDataLen != sizeof(object_id_t) + sizeof(HasHealthIF::HealthState)) { + return CommandingServiceBase::INVALID_TC; + } + HealthSetCommand healthCommand; + result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG); + if (result != returnvalue::OK) { + break; + } + HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_SET, + healthCommand.getHealth()); + break; + } + case (Subservice::COMMAND_ANNOUNCE_HEALTH): { + HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE); + return CommandingServiceBase::EXECUTION_COMPLETE; + } + case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): { + ReturnValue_t result = iterateHealthTable(true); + if (result == returnvalue::OK) { + reportAllHealth = true; + return EXECUTION_COMPLETE; + } + return result; + } + default: { + // Should never happen, subservice was already checked + result = returnvalue::FAILED; + } + } + return result; +} + +ReturnValue_t CServiceHealthCommanding::handleReply(const CommandMessage *reply, + Command_t previousCommand, uint32_t *state, + CommandMessage *optionalNextCommand, + object_id_t objectId, bool *isStep) { + Command_t replyId = reply->getCommand(); + if (replyId == HealthMessage::REPLY_HEALTH_SET) { + return EXECUTION_COMPLETE; + } else if (replyId == CommandMessageIF::REPLY_REJECTED) { + return reply->getReplyRejectedReason(); + } + return CommandingServiceBase::INVALID_REPLY; +} + +void CServiceHealthCommanding::doPeriodicOperation() { + if (reportAllHealth) { + for (uint8_t i = 0; i < maxNumHealthInfoPerCycle; i++) { + ReturnValue_t result = iterateHealthTable(false); + if (result != returnvalue::OK) { + reportAllHealth = false; + break; + } + } + } +} + +// Not used for now, health state already reported by event +[[maybe_unused]] ReturnValue_t CServiceHealthCommanding::prepareHealthSetReply( + const CommandMessage *reply) { + auto health = static_cast(HealthMessage::getHealth(reply)); + auto oldHealth = static_cast(HealthMessage::getOldHealth(reply)); + HealthSetReply healthSetReply(health, oldHealth); + return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply); +} + +ReturnValue_t CServiceHealthCommanding::iterateHealthTable(bool reset) { + std::pair pair; + + ReturnValue_t result = healthTable->iterate(&pair, reset); + if (result != returnvalue::OK) { + return result; + } else { + EventManagerIF::triggerEvent(pair.first, HasHealthIF::HEALTH_INFO, pair.second, pair.second); + return returnvalue::OK; + } +} diff --git a/src/fsfw/pus/CService201HealthCommanding.h b/src/fsfw/pus/CServiceHealthCommanding.h similarity index 60% rename from src/fsfw/pus/CService201HealthCommanding.h rename to src/fsfw/pus/CServiceHealthCommanding.h index 5e52ab39..2cc16589 100644 --- a/src/fsfw/pus/CService201HealthCommanding.h +++ b/src/fsfw/pus/CServiceHealthCommanding.h @@ -1,7 +1,25 @@ #ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_ #define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_ -#include "../tmtcservices/CommandingServiceBase.h" +#include + +#include "fsfw/tmtcservices/CommandingServiceBase.h" + +struct HealthServiceCfg { + HealthServiceCfg(object_id_t objectId, uint16_t apid, object_id_t healthTable, + uint16_t maxNumHealthInfoPerCycle) + : objectId(objectId), + apid(apid), + table(healthTable), + maxNumHealthInfoPerCycle(maxNumHealthInfoPerCycle) {} + object_id_t objectId; + uint16_t apid; + object_id_t table; + uint16_t maxNumHealthInfoPerCycle; + uint8_t service = 201; + uint8_t numParallelCommands = 4; + uint16_t commandTimeoutSeconds = 60; +}; /** * @brief Custom PUS service to set health of all objects @@ -17,11 +35,12 @@ * child class like this service * */ -class CService201HealthCommanding : public CommandingServiceBase { +class CServiceHealthCommanding : public CommandingServiceBase { public: - CService201HealthCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId, - uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60); - virtual ~CService201HealthCommanding(); + CServiceHealthCommanding(HealthServiceCfg args); + ~CServiceHealthCommanding() override = default; + + ReturnValue_t initialize() override; protected: /* CSB abstract function implementations */ @@ -37,13 +56,18 @@ class CService201HealthCommanding : public CommandingServiceBase { CommandMessage *optionalNextCommand, object_id_t objectId, bool *isStep) override; - private: - ReturnValue_t checkAndAcquireTargetID(object_id_t *objectIdToSet, const uint8_t *tcData, - size_t tcDataLen); - ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet, - object_id_t *objectId); + void doPeriodicOperation() override; - ReturnValue_t prepareHealthSetReply(const CommandMessage *reply); + private: + const object_id_t healthTableId; + HealthTable *healthTable; + uint16_t maxNumHealthInfoPerCycle = 0; + bool reportAllHealth = false; + ReturnValue_t iterateHealthTable(bool reset); + static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet, + const object_id_t *objectId); + + [[maybe_unused]] ReturnValue_t prepareHealthSetReply(const CommandMessage *reply); enum Subservice { //! [EXPORT] : [TC] Set health of target object diff --git a/src/fsfw/pus/Service11TelecommandScheduling.h b/src/fsfw/pus/Service11TelecommandScheduling.h new file mode 100644 index 00000000..83b2b4c0 --- /dev/null +++ b/src/fsfw/pus/Service11TelecommandScheduling.h @@ -0,0 +1,202 @@ +#ifndef MISSION_PUS_SERVICE11TELECOMMANDSCHEDULING_H_ +#define MISSION_PUS_SERVICE11TELECOMMANDSCHEDULING_H_ + +#include +#include +#include + +#include "fsfw/FSFW.h" +#include "fsfw/returnvalues/FwClassIds.h" + +/** + * @brief: PUS-Service 11 - Telecommand scheduling. + * @details: + * PUS-Service 11 - Telecommand scheduling. + * Full documentation: ECSS-E-ST-70-41C, p. 168: + * ST[11] time-based scheduling + * + * This service provides the capability to command pre-loaded + * application processes (telecommands) by releasing them at their + * due-time. + * References to telecommands are stored together with their due-timepoints + * and are released at their corresponding due-time. + * + * Necessary subservice functionalities are implemented. + * Those are: + * TC[11,4] activity insertion + * TC[11,5] activity deletion + * TC[11,6] filter-based activity deletion + * TC[11,7] activity time-shift + * TC[11,8] filter-based activity time-shift + * + * Groups are not supported. + * This service remains always enabled. Sending a disable-request has no effect. + */ +template +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 = returnvalue::makeCode(CLASS_ID, 1); + static constexpr ReturnValue_t INVALID_TIME_WINDOW = returnvalue::makeCode(CLASS_ID, 2); + static constexpr ReturnValue_t TIMESHIFTING_NOT_POSSIBLE = returnvalue::makeCode(CLASS_ID, 3); + static constexpr ReturnValue_t INVALID_RELATIVE_TIME = returnvalue::makeCode(CLASS_ID, 4); + static constexpr ReturnValue_t CONTAINED_TC_TOO_SMALL = returnvalue::makeCode(CLASS_ID, 5); + static constexpr ReturnValue_t CONTAINED_TC_CRC_MISSMATCH = returnvalue::makeCode(CLASS_ID, 6); + + static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_11; + + //! [EXPORT] : [COMMENT] Deletion of a TC from the map failed. + //! P1: First 32 bit of request ID, P2. Last 32 bit of Request ID + static constexpr Event TC_DELETION_FAILED = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM); + + // The types of PUS-11 subservices + enum Subservice : uint8_t { + ENABLE_SCHEDULING = 1, + DISABLE_SCHEDULING = 2, + RESET_SCHEDULING = 3, + INSERT_ACTIVITY = 4, + DELETE_ACTIVITY = 5, + FILTER_DELETE_ACTIVITY = 6, + TIMESHIFT_ACTIVITY = 7, + FILTER_TIMESHIFT_ACTIVITY = 8, + DETAIL_REPORT = 9, + TIMEBASE_SCHEDULE_DETAIL_REPORT = 10, + TIMESHIFT_ALL_SCHEDULE_ACTIVITIES = 15 + }; + + // The types of time windows for TC[11,6] and TC[11,8], as defined in ECSS-E-ST-70-41C, + // requirement 8.11.3c (p. 507) + enum TypeOfTimeWindow : uint32_t { + SELECT_ALL = 0, + FROM_TIMETAG_TO_TIMETAG = 1, + FROM_TIMETAG = 2, + TO_TIMETAG = 3 + }; + + Service11TelecommandScheduling(PsbParams params, AcceptsTelecommandsIF* tcRecipient, + uint16_t releaseTimeMarginSeconds = DEFAULT_RELEASE_TIME_MARGIN, + bool debugMode = false); + + ~Service11TelecommandScheduling() override; + + void enableExpiredTcDeletion(); + void disableExpiredTcDeletion(); + + /** PusServiceBase overrides */ + ReturnValue_t handleRequest(uint8_t subservice) override; + ReturnValue_t performService() override; + ReturnValue_t initialize() override; + + private: + struct TelecommandStruct { + uint64_t requestId{}; + uint32_t seconds{}; + store_address_t storeAddr; // uint16 + }; + + static constexpr uint16_t DEFAULT_RELEASE_TIME_MARGIN = 5; + + // minimum release time offset to insert into schedule + const uint16_t RELEASE_TIME_MARGIN_SECONDS = 5; + + /** + * By default, the scheduling will be disabled. This is a standard requirement + */ + bool schedulingEnabled = false; + bool deleteExpiredTcWhenDisabled = true; + bool debugMode = false; + StorageManagerIF* tcStore = nullptr; + AcceptsTelecommandsIF* tcRecipient = nullptr; + MessageQueueId_t recipientMsgQueueId = 0; + + /** + * The telecommand map uses the exectution time as a Unix time stamp as + * the key. This is mapped to a generic telecommand struct. + */ + using TelecommandMap = etl::multimap; + using TcMapIter = typename TelecommandMap::iterator; + + TelecommandMap telecommandMap; + + ReturnValue_t handleResetCommand(); + /** + * @brief Logic to be performed on an incoming TC[11,4]. + * @return returnvalue::OK if successful + */ + ReturnValue_t doInsertActivity(const uint8_t* data, size_t size); + + /** + * @brief Logic to be performed on an incoming TC[11,5]. + * @return returnvalue::OK if successful + */ + ReturnValue_t doDeleteActivity(const uint8_t* data, size_t size); + + /** + * @brief Logic to be performed on an incoming TC[11,6]. + * @return returnvalue::OK if successful + */ + ReturnValue_t doFilterDeleteActivity(const uint8_t* data, size_t size); + + /** + * @brief Logic to be performed on an incoming TC[11,7]. + * @return returnvalue::OK if successful + */ + ReturnValue_t doTimeshiftActivity(const uint8_t* data, size_t size); + + /** + * @brief Logic to be performed on an incoming TC[11,8]. + * @return returnvalue::OK if successful + */ + ReturnValue_t doFilterTimeshiftActivity(const uint8_t* data, size_t size); + + /** + * @brief Extracts the Request ID from the Application Data of a TC by utilizing a ctor of the + * class TcPacketPus. + * NOTE: This only works if the payload data is a TC (e.g. not for TC[11,5] which does not + * send a TC as payload)! + * @param data The Application data of the TC (get via getApplicationData()). + * @return requestId + */ + [[nodiscard]] uint64_t getRequestIdFromTc() const; + + /** + * @brief Extracts the Request ID from the Application Data directly, assuming it is packed + * as follows (acc. to ECSS): | source ID (uint32) | apid (uint32) | ssc (uint32) |. + * @param data Pointer to first byte described data + * @param dataSize Remaining size of data NOTE: non-const, this is modified by the function + * @param [out] requestId Request ID + * @return returnvalue::OK if successful + */ + ReturnValue_t getRequestIdFromData(const uint8_t*& data, size_t& dataSize, uint64_t& requestId); + + /** + * @brief Builds the Request ID from its three elements. + * @param sourceId Source ID + * @param apid Application Process ID (APID) + * @param ssc Source Sequence Count + * @return Request ID + */ + [[nodiscard]] uint64_t buildRequestId(uint32_t sourceId, uint16_t apid, uint16_t ssc) const; + + /** + * @brief Gets the filter range for filter TCs from a data packet + * @param data TC data + * @param dataSize TC data size + * @param [out] itBegin Begin of filter range + * @param [out] itEnd End of filter range + * @return returnvalue::OK if successful + */ + 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. + */ + void debugPrintMultimapContent() const; +}; + +#include "Service11TelecommandScheduling.tpp" + +#endif /* MISSION_PUS_SERVICE11TELECOMMANDSCHEDULING_H_ */ diff --git a/src/fsfw/pus/Service11TelecommandScheduling.tpp b/src/fsfw/pus/Service11TelecommandScheduling.tpp new file mode 100644 index 00000000..ac08f02c --- /dev/null +++ b/src/fsfw/pus/Service11TelecommandScheduling.tpp @@ -0,0 +1,645 @@ +#pragma once + +#include + +#include "fsfw/globalfunctions/CRC.h" +#include "fsfw/objectmanager/ObjectManager.h" +#include "fsfw/serialize/SerializeAdapter.h" +#include "fsfw/serviceinterface.h" +#include "fsfw/tmtcpacket/pus/tc/PusTcIF.h" +#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h" + +static constexpr auto DEF_END = SerializeIF::Endianness::BIG; + +template +inline Service11TelecommandScheduling::Service11TelecommandScheduling( + PsbParams params, AcceptsTelecommandsIF *tcRecipient, uint16_t releaseTimeMarginSeconds, + bool debugMode) + : PusServiceBase(params), + RELEASE_TIME_MARGIN_SECONDS(releaseTimeMarginSeconds), + debugMode(debugMode), + tcRecipient(tcRecipient) { + params.name = "PUS 11 TC Scheduling"; +} + +template +inline Service11TelecommandScheduling::~Service11TelecommandScheduling() = default; + +template +inline ReturnValue_t Service11TelecommandScheduling::handleRequest( + uint8_t subservice) { + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::handleRequest: Handling request " << static_cast(subservice); +#else + sif::printInfo("PUS11::handleRequest: Handling request %d\n", subservice); +#endif + } + // Get de-serialized Timestamp + const uint8_t *data = currentPacket.getUserData(); + size_t size = currentPacket.getUserDataLen(); + switch (subservice) { + case Subservice::ENABLE_SCHEDULING: { + schedulingEnabled = true; + break; + } + case Subservice::DISABLE_SCHEDULING: { + schedulingEnabled = false; + break; + } + case Subservice::RESET_SCHEDULING: { + return handleResetCommand(); + } + case Subservice::INSERT_ACTIVITY: + return doInsertActivity(data, size); + case Subservice::DELETE_ACTIVITY: + return doDeleteActivity(data, size); + case Subservice::FILTER_DELETE_ACTIVITY: + return doFilterDeleteActivity(data, size); + case Subservice::TIMESHIFT_ACTIVITY: + return doTimeshiftActivity(data, size); + case Subservice::FILTER_TIMESHIFT_ACTIVITY: + return doFilterTimeshiftActivity(data, size); + default: + return AcceptsTelecommandsIF::INVALID_SUBSERVICE; + } + return returnvalue::OK; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::performService() { + if (not schedulingEnabled) { + return returnvalue::OK; + } + // get current time as UNIX timestamp + timeval tNow = {}; + Clock::getClock_timeval(&tNow); + + // TODO: Optionally limit the max number of released TCs per cycle? + // NOTE: The iterator is increased in the loop here. Increasing the iterator as for-loop arg + // does not work in this case as we are deleting the current element here. + for (auto it = telecommandMap.begin(); it != telecommandMap.end();) { + if (it->first <= tNow.tv_sec) { + if (schedulingEnabled) { + // release tc + TmTcMessage releaseMsg(it->second.storeAddr); + auto sendRet = psbParams.reqQueue->sendMessage(recipientMsgQueueId, &releaseMsg, false); + + if (sendRet != returnvalue::OK) { + return sendRet; + } + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "Released TC & erased it from TC map" << std::endl; +#else + sif::printInfo("Released TC & erased it from TC map\n"); +#endif + } + telecommandMap.erase(it++); + } else if (deleteExpiredTcWhenDisabled) { + telecommandMap.erase(it++); + } + continue; + } + it++; + } + + return returnvalue::OK; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::initialize() { + ReturnValue_t res = PusServiceBase::initialize(); + if (res != returnvalue::OK) { + return res; + } + + tcStore = ObjectManager::instance()->get(objects::TC_STORE); + if (!tcStore) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + if (tcRecipient == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + recipientMsgQueueId = tcRecipient->getRequestQueue(); + + return res; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::handleResetCommand() { + for (auto it = telecommandMap.begin(); it != telecommandMap.end(); it++) { + ReturnValue_t result = tcStore->deleteData(it->second.storeAddr); + if (result != returnvalue::OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + // This should not happen + sif::warning << "Service11TelecommandScheduling::handleRequestDeleting: Deletion failed" + << std::endl; +#else + sif::printWarning("Service11TelecommandScheduling::handleRequestDeleting: Deletion failed\n"); +#endif + triggerEvent(TC_DELETION_FAILED, (it->second.requestId >> 32) & 0xffffffff, + it->second.requestId & 0xffffffff); + } + } + telecommandMap.clear(); + return returnvalue::OK; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::doInsertActivity( + const uint8_t *data, size_t size) { + uint32_t timestamp = 0; + ReturnValue_t result = SerializeAdapter::deSerialize(×tamp, &data, &size, DEF_END); + if (result != returnvalue::OK) { + return result; + } + + // Insert possible if sched. time is above margin + // (See requirement for Time margin) + timeval tNow = {}; + Clock::getClock_timeval(&tNow); + if (timestamp - tNow.tv_sec <= RELEASE_TIME_MARGIN_SECONDS) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "Service11TelecommandScheduling::doInsertActivity: Release time too close to " + "current time" + << std::endl; +#else + sif::printWarning( + "Service11TelecommandScheduling::doInsertActivity: Release time too close to current " + "time\n"); +#endif + return returnvalue::FAILED; + } + + if (size < PusTcIF::MIN_SIZE) { + return CONTAINED_TC_TOO_SMALL; + } + + if (CRC::crc16ccitt(data, size) != 0) { + return CONTAINED_TC_CRC_MISSMATCH; + } + + // store currentPacket and receive the store address + store_address_t addr{}; + if (tcStore->addData(&addr, data, size) != returnvalue::OK || + addr.raw == store_address_t::INVALID_RAW) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "Service11TelecommandScheduling::doInsertActivity: Adding data to TC Store failed" + << std::endl; +#else + sif::printError( + "Service11TelecommandScheduling::doInsertActivity: Adding data to TC Store failed\n"); +#endif + return returnvalue::FAILED; + } + + // insert into multimap with new store address + TelecommandStruct tc; + tc.seconds = timestamp; + tc.storeAddr = addr; + tc.requestId = getRequestIdFromTc(); // TODO: Missing sanity check of the returned request id + + auto it = telecommandMap.insert(std::pair(timestamp, tc)); + if (it == telecommandMap.end()) { + return returnvalue::FAILED; + } + + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::doInsertActivity: Inserted into Multimap:" << std::endl; +#else + sif::printInfo("PUS11::doInsertActivity: Inserted into Multimap:\n"); +#endif + debugPrintMultimapContent(); + } + return returnvalue::OK; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::doDeleteActivity( + const uint8_t *data, size_t size) { + // Get request ID + uint64_t requestId; + ReturnValue_t result = getRequestIdFromData(data, size, requestId); + if (result != returnvalue::OK) { + return result; + } + + // DEBUG + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::doDeleteActivity: requestId: " << requestId << std::endl; +#else + sif::printInfo("PUS11::doDeleteActivity: requestId: %d\n", requestId); +#endif + } + + TcMapIter tcToDelete; // handle to the TC to be deleted, can be used if counter is valid + int tcToDeleteCount = 0; // counter of all found TCs. Should be 1. + + for (auto it = telecommandMap.begin(); it != telecommandMap.end(); it++) { + if (it->second.requestId == requestId) { + tcToDelete = it; + tcToDeleteCount++; + } + } + + // check if 1 explicit TC is found via request ID + if (tcToDeleteCount == 0 || tcToDeleteCount > 1) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "Service11TelecommandScheduling::doDeleteActivity: No or more than 1 TC found. " + "Cannot explicitly delete TC" + << std::endl; +#else + sif::printWarning( + "Service11TelecommandScheduling::doDeleteActivity: No or more than 1 TC found. " + "Cannot explicitly delete TC"); +#endif + return returnvalue::FAILED; + } + + // delete packet from store + if (tcStore->deleteData(tcToDelete->second.storeAddr) != returnvalue::OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "Service11TelecommandScheduling::doDeleteActivity: Could not delete TC from Store" + << std::endl; +#else + sif::printError( + "Service11TelecommandScheduling::doDeleteActivity: Could not delete TC from Store\n"); +#endif + return returnvalue::FAILED; + } + + telecommandMap.erase(tcToDelete); + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::doDeleteActivity: Deleted TC from map" << std::endl; +#else + sif::printInfo("PUS11::doDeleteActivity: Deleted TC from map\n"); +#endif + } + + return returnvalue::OK; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::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 (result != returnvalue::OK) { + return result; + } + + int deletedTCs = 0; + for (TcMapIter it = itBegin; it != itEnd; it++) { + // delete packet from store + if (tcStore->deleteData(it->second.storeAddr) != returnvalue::OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "Service11TelecommandScheduling::doFilterDeleteActivity: Could not delete TC " + "from Store" + << std::endl; +#else + sif::printError( + "Service11TelecommandScheduling::doFilterDeleteActivity: Could not delete TC from " + "Store\n"); +#endif + continue; + } + deletedTCs++; + } + + // NOTE: Spec says this function erases all elements including itBegin but not itEnd, + // see here: https://www.cplusplus.com/reference/map/multimap/erase/ + // Therefore we need to increase itEnd by 1. (Note that end() returns the "past-the-end" iterator) + if (itEnd != telecommandMap.end()) { + itEnd++; + } + + telecommandMap.erase(itBegin, itEnd); + + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::doFilterDeleteActivity: Deleted " << deletedTCs << " TCs" << std::endl; +#else + sif::printInfo("PUS11::doFilterDeleteActivity: Deleted %d TCs\n", deletedTCs); +#endif + } + return returnvalue::OK; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::doTimeshiftActivity( + const uint8_t *data, size_t size) { + // Get relative time + uint32_t relativeTime = 0; + ReturnValue_t result = SerializeAdapter::deSerialize(&relativeTime, &data, &size, DEF_END); + if (result != returnvalue::OK) { + return result; + } + if (relativeTime == 0) { + return INVALID_RELATIVE_TIME; + } + // TODO further check sanity of the relative time? + + // Get request ID + uint64_t requestId; + result = getRequestIdFromData(data, size, requestId); + if (result != returnvalue::OK) { + return result; + } + + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::doTimeshiftActivity: requestId: " << requestId << std::endl; +#else + sif::printInfo("PUS11::doTimeshiftActivity: requestId: %d\n", requestId); +#endif + } + + // NOTE: Despite having C++17 ETL multimap has no member function extract :( + + TcMapIter tcToTimeshiftIt; + int tcToTimeshiftCount = 0; + + for (auto it = telecommandMap.begin(); it != telecommandMap.end(); it++) { + if (it->second.requestId == requestId) { + tcToTimeshiftIt = it; + tcToTimeshiftCount++; + } + } + + if (tcToTimeshiftCount == 0 || tcToTimeshiftCount > 1) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "Service11TelecommandScheduling::doTimeshiftActivity: Either 0 or more than 1 " + "TCs found. No explicit timeshifting " + "possible" + << std::endl; + +#else + sif::printWarning( + "Service11TelecommandScheduling::doTimeshiftActivity: Either 0 or more than 1 TCs found. " + "No explicit timeshifting possible\n"); +#endif + return TIMESHIFTING_NOT_POSSIBLE; + } + + // temporarily hold the item + TelecommandStruct tempTc(tcToTimeshiftIt->second); + uint32_t tempKey = tcToTimeshiftIt->first + relativeTime; + + // delete old entry from the mm + telecommandMap.erase(tcToTimeshiftIt); + + // and then insert it again as new entry + telecommandMap.insert(std::make_pair(tempKey, tempTc)); + + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::doTimeshiftActivity: Shifted TC" << std::endl; +#else + sif::printDebug("PUS11::doTimeshiftActivity: Shifted TC\n"); +#endif + debugPrintMultimapContent(); + } + + return returnvalue::OK; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::doFilterTimeshiftActivity( + const uint8_t *data, size_t size) { + // Get relative time + uint32_t relativeTime = 0; + ReturnValue_t result = SerializeAdapter::deSerialize(&relativeTime, &data, &size, DEF_END); + if (result != returnvalue::OK) { + return result; + } + if (relativeTime == 0) { + return INVALID_RELATIVE_TIME; + } + + // Do time window + TcMapIter itBegin; + TcMapIter itEnd; + result = getMapFilterFromData(data, size, itBegin, itEnd); + if (result != returnvalue::OK) { + return result; + } + + int shiftedItemsCount = 0; + for (auto it = itBegin; it != itEnd;) { + // temporarily hold the item + TelecommandStruct tempTc(it->second); + uint32_t tempKey = it->first + relativeTime; + + // delete the old entry from the mm + telecommandMap.erase(it++); + + // and then insert it again as new entry + telecommandMap.insert(std::make_pair(tempKey, tempTc)); + shiftedItemsCount++; + } + + if (debugMode) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "PUS11::doFilterTimeshiftActivity: shiftedItemsCount: " << shiftedItemsCount + << std::endl; +#else + sif::printInfo("PUS11::doFilterTimeshiftActivity: shiftedItemsCount: %d\n", shiftedItemsCount); +#endif + debugPrintMultimapContent(); + } + + if (shiftedItemsCount > 0) { + return returnvalue::OK; + } + return returnvalue::FAILED; +} + +template +inline uint64_t Service11TelecommandScheduling::getRequestIdFromTc() const { + uint32_t sourceId = currentPacket.getSourceId(); + uint16_t apid = currentPacket.getApid(); + uint16_t sequenceCount = currentPacket.getSequenceCount(); + + return buildRequestId(sourceId, apid, sequenceCount); +} + +template +inline ReturnValue_t Service11TelecommandScheduling::getRequestIdFromData( + const uint8_t *&data, size_t &dataSize, uint64_t &requestId) { + uint32_t srcId = 0; + uint16_t apid = 0; + uint16_t ssc = 0; + + ReturnValue_t result = SerializeAdapter::deSerialize(&srcId, &data, &dataSize, DEF_END); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&apid, &data, &dataSize, DEF_END); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&ssc, &data, &dataSize, DEF_END); + if (result != returnvalue::OK) { + return result; + } + requestId = buildRequestId(srcId, apid, ssc); + + return returnvalue::OK; +} + +template +inline uint64_t Service11TelecommandScheduling::buildRequestId(uint32_t sourceId, + uint16_t apid, + uint16_t ssc) const { + auto sourceId64 = static_cast(sourceId); + auto apid64 = static_cast(apid); + auto ssc64 = static_cast(ssc); + + return (sourceId64 << 32) | (apid64 << 16) | ssc64; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::getMapFilterFromData( + const uint8_t *&data, size_t &dataSize, TcMapIter &itBegin, TcMapIter &itEnd) { + // get filter type first + uint32_t typeRaw = 0; + ReturnValue_t result = SerializeAdapter::deSerialize(&typeRaw, &data, &dataSize, DEF_END); + if (result != returnvalue::OK) { + return result; + } + + if (typeRaw > 3) { + return INVALID_TYPE_TIME_WINDOW; + } + auto type = static_cast(typeRaw); + + // we now have the type of delete activity - so now we set the range to delete, + // according to the type of time window. + // NOTE: Blocks are used in this switch-case statement so that timestamps can be + // cleanly redefined for each case. + switch (type) { + case TypeOfTimeWindow::SELECT_ALL: { + itBegin = telecommandMap.begin(); + itEnd = telecommandMap.end(); + break; + } + + case TypeOfTimeWindow::FROM_TIMETAG: { + uint32_t fromTimestamp = 0; + result = SerializeAdapter::deSerialize(&fromTimestamp, &data, &dataSize, DEF_END); + if (result != returnvalue::OK) { + return result; + } + + itBegin = telecommandMap.begin(); + while (itBegin->first < fromTimestamp && itBegin != telecommandMap.end()) { + itBegin++; + } + + itEnd = telecommandMap.end(); + break; + } + + case TypeOfTimeWindow::TO_TIMETAG: { + uint32_t toTimestamp; + result = SerializeAdapter::deSerialize(&toTimestamp, &data, &dataSize, DEF_END); + if (result != returnvalue::OK) { + return result; + } + itBegin = telecommandMap.begin(); + itEnd = telecommandMap.begin(); + while (itEnd->first <= toTimestamp && itEnd != telecommandMap.end()) { + itEnd++; + } + break; + } + + case TypeOfTimeWindow::FROM_TIMETAG_TO_TIMETAG: { + uint32_t fromTimestamp; + uint32_t toTimestamp; + + result = SerializeAdapter::deSerialize(&fromTimestamp, &data, &dataSize, + SerializeIF::Endianness::BIG); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::deSerialize(&toTimestamp, &data, &dataSize, + SerializeIF::Endianness::BIG); + if (result != returnvalue::OK) { + return result; + } + if (fromTimestamp > toTimestamp) { + return INVALID_TIME_WINDOW; + } + itBegin = telecommandMap.begin(); + + while (itBegin->first < fromTimestamp && itBegin != telecommandMap.end()) { + itBegin++; + } + + // start looking for end beginning at begin + itEnd = itBegin; + while (itEnd->first <= toTimestamp && itEnd != telecommandMap.end()) { + itEnd++; + } + break; + } + + default: + return returnvalue::FAILED; + } + // the map range should now be set according to the sent filter. + return returnvalue::OK; +} + +template +inline ReturnValue_t Service11TelecommandScheduling::handleInvalidData( + const char *ctx) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "Service11TelecommandScheduling:: " << ctx << ": Invalid buffer" << std::endl; +#else + sif::printWarning("Service11TelecommandScheduling::%s: Invalid buffer\n", ctx); +#endif +#endif + return returnvalue::FAILED; +} + +template +inline void Service11TelecommandScheduling::debugPrintMultimapContent() const { +#if FSFW_DISABLE_PRINTOUT == 0 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::debug << "Service11TelecommandScheduling::debugPrintMultimapContent: Multimap Content" + << std::endl; +#else + sif::printDebug("Service11TelecommandScheduling::debugPrintMultimapContent: Multimap Content\n"); +#endif + for (const auto &dit : telecommandMap) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::debug << "[" << dit.first << "]: Request ID: " << dit.second.requestId << " | " + << "Store Address: " << dit.second.storeAddr.raw << std::endl; +#else + sif::printDebug("[%d]: Request ID: %d | Store Address: %d\n", dit.first, dit.second.requestId, + dit.second.storeAddr); +#endif + } +#endif +} + +template +inline void Service11TelecommandScheduling::enableExpiredTcDeletion() { + deleteExpiredTcWhenDisabled = true; +} + +template +inline void Service11TelecommandScheduling::disableExpiredTcDeletion() { + deleteExpiredTcWhenDisabled = false; +} diff --git a/src/fsfw/pus/Service17Test.cpp b/src/fsfw/pus/Service17Test.cpp index f784acf4..bea2eeb8 100644 --- a/src/fsfw/pus/Service17Test.cpp +++ b/src/fsfw/pus/Service17Test.cpp @@ -1,43 +1,59 @@ #include "fsfw/pus/Service17Test.h" #include "fsfw/FSFW.h" +#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/objectmanager/SystemObject.h" -#include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tmtcpacket/pus/tm/TmPacketStored.h" +#include "fsfw/tmtcservices/tmHelpers.h" -Service17Test::Service17Test(object_id_t objectId, uint16_t apid, uint8_t serviceId) - : PusServiceBase(objectId, apid, serviceId), packetSubCounter(0) {} +Service17Test::Service17Test(PsbParams params) + : PusServiceBase(params), + storeHelper(params.apid), + tmHelper(params.serviceId, storeHelper, sendHelper) { + params.name = "PUS 17 Test"; +} -Service17Test::~Service17Test() {} +Service17Test::~Service17Test() = default; ReturnValue_t Service17Test::handleRequest(uint8_t subservice) { switch (subservice) { case Subservice::CONNECTION_TEST: { -#if FSFW_USE_PUS_C_TELEMETRY == 0 - TmPacketStoredPusA connectionPacket(apid, serviceId, Subservice::CONNECTION_TEST_REPORT, - packetSubCounter++); -#else - TmPacketStoredPusC connectionPacket(apid, serviceId, Subservice::CONNECTION_TEST_REPORT, - packetSubCounter++); -#endif - connectionPacket.sendPacket(requestQueue->getDefaultDestination(), requestQueue->getId()); - return HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = tmHelper.prepareTmPacket(Subservice::CONNECTION_TEST_REPORT); + if (result != returnvalue::OK) { + return result; + } + return tmHelper.storeAndSendTmPacket(); } case Subservice::EVENT_TRIGGER_TEST: { -#if FSFW_USE_PUS_C_TELEMETRY == 0 - TmPacketStoredPusA connectionPacket(apid, serviceId, Subservice::CONNECTION_TEST_REPORT, - packetSubCounter++); -#else - TmPacketStoredPusC connectionPacket(apid, serviceId, Subservice::CONNECTION_TEST_REPORT, - packetSubCounter++); -#endif - connectionPacket.sendPacket(requestQueue->getDefaultDestination(), requestQueue->getId()); triggerEvent(TEST, 1234, 5678); - return RETURN_OK; + ReturnValue_t result = tmHelper.prepareTmPacket(Subservice::EVENT_TRIGGER_TEST); + if (result != returnvalue::OK) { + return result; + } + return tmHelper.storeAndSendTmPacket(); } default: return AcceptsTelecommandsIF::INVALID_SUBSERVICE; } } -ReturnValue_t Service17Test::performService() { return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t Service17Test::performService() { return returnvalue::OK; } + +ReturnValue_t Service17Test::initialize() { + ReturnValue_t result = PusServiceBase::initialize(); + if (result != returnvalue::OK) { + return result; + } + initializeTmHelpers(sendHelper, storeHelper); + if (storeHelper.getTmStore() == nullptr) { + auto* tmStore = ObjectManager::instance()->get(objects::TM_STORE); + if (tmStore == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + storeHelper.setTmStore(*tmStore); + } + return result; +} + +void Service17Test::setCustomTmStore(StorageManagerIF& tmStore_) { + storeHelper.setTmStore(tmStore_); +} diff --git a/src/fsfw/pus/Service17Test.h b/src/fsfw/pus/Service17Test.h index c2248020..f2ec6e4f 100644 --- a/src/fsfw/pus/Service17Test.h +++ b/src/fsfw/pus/Service17Test.h @@ -3,6 +3,8 @@ #include "fsfw/objectmanager/SystemObject.h" #include "fsfw/tmtcservices/PusServiceBase.h" +#include "fsfw/tmtcservices/TmStoreAndSendHelper.h" +#include "fsfw/tmtcservices/TmStoreHelper.h" /** * @brief Test Service @@ -32,13 +34,19 @@ class Service17Test : public PusServiceBase { EVENT_TRIGGER_TEST = 128, }; - Service17Test(object_id_t objectId, uint16_t apid, uint8_t serviceId); - virtual ~Service17Test(); - virtual ReturnValue_t handleRequest(uint8_t subservice) override; - virtual ReturnValue_t performService() override; + explicit Service17Test(PsbParams params); + + void setCustomTmStore(StorageManagerIF& tmStore); + + ~Service17Test() override; + ReturnValue_t handleRequest(uint8_t subservice) override; + ReturnValue_t performService() override; + ReturnValue_t initialize() override; protected: - uint16_t packetSubCounter = 0; + TmStoreHelper storeHelper; + TmSendHelper sendHelper; + TmStoreAndSendWrapper tmHelper; }; #endif /* FSFW_PUS_SERVICE17TEST_H_ */ diff --git a/src/fsfw/pus/Service1TelecommandVerification.cpp b/src/fsfw/pus/Service1TelecommandVerification.cpp index 13d6a1c4..a3248045 100644 --- a/src/fsfw/pus/Service1TelecommandVerification.cpp +++ b/src/fsfw/pus/Service1TelecommandVerification.cpp @@ -3,19 +3,21 @@ #include "fsfw/ipc/QueueFactory.h" #include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/pus/servicepackets/Service1Packets.h" -#include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tmtcpacket/pus/tm/TmPacketStored.h" #include "fsfw/tmtcservices/AcceptsTelemetryIF.h" #include "fsfw/tmtcservices/PusVerificationReport.h" +#include "fsfw/tmtcservices/tmHelpers.h" Service1TelecommandVerification::Service1TelecommandVerification(object_id_t objectId, uint16_t apid, uint8_t serviceId, object_id_t targetDestination, - uint16_t messageQueueDepth) + uint16_t messageQueueDepth, + TimeWriterIF* timeStamper) : SystemObject(objectId), apid(apid), serviceId(serviceId), - targetDestination(targetDestination) { + targetDestination(targetDestination), + storeHelper(apid), + tmHelper(serviceId, storeHelper, sendHelper) { tmQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth); } @@ -30,15 +32,15 @@ MessageQueueId_t Service1TelecommandVerification::getVerificationQueue() { ReturnValue_t Service1TelecommandVerification::performOperation(uint8_t operationCode) { PusVerificationMessage message; ReturnValue_t status = tmQueue->receiveMessage(&message); - while (status == HasReturnvaluesIF::RETURN_OK) { + while (status == returnvalue::OK) { status = sendVerificationReport(&message); - if (status != HasReturnvaluesIF::RETURN_OK) { + if (status != returnvalue::OK) { return status; } status = tmQueue->receiveMessage(&message); } if (status == MessageQueueIF::EMPTY) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { return status; } @@ -47,12 +49,25 @@ ReturnValue_t Service1TelecommandVerification::performOperation(uint8_t operatio ReturnValue_t Service1TelecommandVerification::sendVerificationReport( PusVerificationMessage* message) { ReturnValue_t result; + uint8_t reportId = message->getReportId(); + if (reportId == 0 or reportId > 8) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "Service1TelecommandVerification::sendVerificationReport: Invalid report ID " + << static_cast(reportId) << " detected" << std::endl; +#else + sif::printError( + "Service1TelecommandVerification::sendVerificationReport: Invalid report ID " + "%d detected\n", + reportId); +#endif + return returnvalue::FAILED; + } if (message->getReportId() % 2 == 0) { result = generateFailureReport(message); } else { result = generateSuccessReport(message); } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "Service1TelecommandVerification::sendVerificationReport: " "Sending verification packet failed !" @@ -67,32 +82,37 @@ ReturnValue_t Service1TelecommandVerification::generateFailureReport( FailureReport report(message->getReportId(), message->getTcPacketId(), message->getTcSequenceControl(), message->getStep(), message->getErrorCode(), message->getParameter1(), message->getParameter2()); -#if FSFW_USE_PUS_C_TELEMETRY == 0 - TmPacketStoredPusA tmPacket(apid, serviceId, message->getReportId(), packetSubCounter++, &report); -#else - TmPacketStoredPusC tmPacket(apid, serviceId, message->getReportId(), packetSubCounter++, &report); -#endif - ReturnValue_t result = tmPacket.sendPacket(tmQueue->getDefaultDestination(), tmQueue->getId()); - return result; + ReturnValue_t result = + storeHelper.preparePacket(serviceId, message->getReportId(), packetSubCounter++); + if (result != returnvalue::OK) { + return result; + } + result = storeHelper.setSourceDataSerializable(report); + if (result != returnvalue::OK) { + return result; + } + return tmHelper.storeAndSendTmPacket(); } ReturnValue_t Service1TelecommandVerification::generateSuccessReport( PusVerificationMessage* message) { SuccessReport report(message->getReportId(), message->getTcPacketId(), message->getTcSequenceControl(), message->getStep()); -#if FSFW_USE_PUS_C_TELEMETRY == 0 - TmPacketStoredPusA tmPacket(apid, serviceId, message->getReportId(), packetSubCounter++, &report); -#else - TmPacketStoredPusC tmPacket(apid, serviceId, message->getReportId(), packetSubCounter++, &report); -#endif - ReturnValue_t result = tmPacket.sendPacket(tmQueue->getDefaultDestination(), tmQueue->getId()); - return result; + ReturnValue_t result = + storeHelper.preparePacket(serviceId, message->getReportId(), packetSubCounter++); + if (result != returnvalue::OK) { + return result; + } + result = storeHelper.setSourceDataSerializable(report); + if (result != returnvalue::OK) { + return result; + } + return tmHelper.storeAndSendTmPacket(); } ReturnValue_t Service1TelecommandVerification::initialize() { // Get target object for TC verification messages - AcceptsTelemetryIF* funnel = - ObjectManager::instance()->get(targetDestination); + auto* funnel = ObjectManager::instance()->get(targetDestination); if (funnel == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "Service1TelecommandVerification::initialize: Specified" @@ -102,6 +122,33 @@ ReturnValue_t Service1TelecommandVerification::initialize() { #endif return ObjectManagerIF::CHILD_INIT_FAILED; } + if (tmQueue == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } tmQueue->setDefaultDestination(funnel->getReportReceptionQueue()); + if (tmStore == nullptr) { + tmStore = ObjectManager::instance()->get(objects::TM_STORE); + if (tmStore == nullptr) { + return ObjectManager::CHILD_INIT_FAILED; + } + storeHelper.setTmStore(*tmStore); + } + if (timeStamper == nullptr) { + timeStamper = ObjectManager::instance()->get(objects::TIME_STAMPER); + if (timeStamper == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + } else { + } + storeHelper.setTimeStamper(*timeStamper); + + sendHelper.setMsgQueue(*tmQueue); + if (errReporter == nullptr) { + errReporter = + ObjectManager::instance()->get(objects::INTERNAL_ERROR_REPORTER); + if (errReporter != nullptr) { + sendHelper.setInternalErrorReporter(*errReporter); + } + } return SystemObject::initialize(); } diff --git a/src/fsfw/pus/Service1TelecommandVerification.h b/src/fsfw/pus/Service1TelecommandVerification.h index 10d2da0e..f5844995 100644 --- a/src/fsfw/pus/Service1TelecommandVerification.h +++ b/src/fsfw/pus/Service1TelecommandVerification.h @@ -3,10 +3,13 @@ #include "fsfw/ipc/MessageQueueIF.h" #include "fsfw/objectmanager/SystemObject.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/tasks/ExecutableObjectIF.h" #include "fsfw/tmtcservices/AcceptsVerifyMessageIF.h" #include "fsfw/tmtcservices/PusVerificationReport.h" +#include "fsfw/tmtcservices/TmSendHelper.h" +#include "fsfw/tmtcservices/TmStoreAndSendHelper.h" +#include "fsfw/tmtcservices/TmStoreHelper.h" /** * @brief Verify TC acceptance, start, progress and execution. @@ -38,20 +41,20 @@ */ class Service1TelecommandVerification : public AcceptsVerifyMessageIF, public SystemObject, - public ExecutableObjectIF, - public HasReturnvaluesIF { + public ExecutableObjectIF { public: static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_1; Service1TelecommandVerification(object_id_t objectId, uint16_t apid, uint8_t serviceId, - object_id_t targetDestination, uint16_t messageQueueDepth); - virtual ~Service1TelecommandVerification(); + object_id_t targetDestination, uint16_t messageQueueDepth, + TimeWriterIF* timeStamper = nullptr); + ~Service1TelecommandVerification() override; /** * * @return ID of Verification Queue */ - virtual MessageQueueId_t getVerificationQueue() override; + MessageQueueId_t getVerificationQueue() override; /** * Performs the service periodically as specified in init_mission(). @@ -59,7 +62,7 @@ class Service1TelecommandVerification : public AcceptsVerifyMessageIF, * @param operationCode * @return */ - ReturnValue_t performOperation(uint8_t operationCode = 0) override; + ReturnValue_t performOperation(uint8_t operationCode) override; /** * Initializes the destination for TC verification messages and initializes @@ -80,6 +83,12 @@ class Service1TelecommandVerification : public AcceptsVerifyMessageIF, uint16_t packetSubCounter = 0; + TmSendHelper sendHelper; + TmStoreHelper storeHelper; + TmStoreAndSendWrapper tmHelper; + InternalErrorReporterIF* errReporter = nullptr; + TimeWriterIF* timeStamper = nullptr; + StorageManagerIF* tmStore = nullptr; MessageQueueIF* tmQueue = nullptr; enum class Subservice : uint8_t { diff --git a/src/fsfw/pus/Service20ParameterManagement.cpp b/src/fsfw/pus/Service20ParameterManagement.cpp index 61e29412..87bd5a13 100644 --- a/src/fsfw/pus/Service20ParameterManagement.cpp +++ b/src/fsfw/pus/Service20ParameterManagement.cpp @@ -11,16 +11,16 @@ Service20ParameterManagement::Service20ParameterManagement(object_id_t objectId, uint8_t serviceId, uint8_t numberOfParallelCommands, uint16_t commandTimeoutSeconds) - : CommandingServiceBase(objectId, apid, serviceId, numberOfParallelCommands, - commandTimeoutSeconds) {} + : CommandingServiceBase(objectId, apid, "PUS 20 Parameter MGMT", serviceId, + numberOfParallelCommands, commandTimeoutSeconds) {} -Service20ParameterManagement::~Service20ParameterManagement() {} +Service20ParameterManagement::~Service20ParameterManagement() = default; ReturnValue_t Service20ParameterManagement::isValidSubservice(uint8_t subservice) { switch (static_cast(subservice)) { case Subservice::PARAMETER_LOAD: case Subservice::PARAMETER_DUMP: - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; default: #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "Invalid Subservice for Service 20" << std::endl; @@ -37,7 +37,7 @@ ReturnValue_t Service20ParameterManagement::getMessageQueueAndObject(uint8_t sub MessageQueueId_t* id, object_id_t* objectId) { ReturnValue_t result = checkAndAcquireTargetID(objectId, tcData, tcDataLen); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } return checkInterfaceAndAcquireMessageQueue(id, objectId); @@ -47,7 +47,7 @@ ReturnValue_t Service20ParameterManagement::checkAndAcquireTargetID(object_id_t* const uint8_t* tcData, size_t tcDataLen) { if (SerializeAdapter::deSerialize(objectIdToSet, &tcData, &tcDataLen, - SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) { + SerializeIF::Endianness::BIG) != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "Service20ParameterManagement::checkAndAcquireTargetID: " << "Invalid data." << std::endl; @@ -58,32 +58,31 @@ ReturnValue_t Service20ParameterManagement::checkAndAcquireTargetID(object_id_t* #endif return CommandingServiceBase::INVALID_TC; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Service20ParameterManagement::checkInterfaceAndAcquireMessageQueue( MessageQueueId_t* messageQueueToSet, object_id_t* objectId) { // check ReceivesParameterMessagesIF property of target - ReceivesParameterMessagesIF* possibleTarget = - ObjectManager::instance()->get(*objectId); + auto* possibleTarget = ObjectManager::instance()->get(*objectId); if (possibleTarget == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "Service20ParameterManagement::checkInterfaceAndAcquire" << "MessageQueue: Can't access object" << std::endl; - sif::error << "Object ID: " << std::hex << objectId << std::dec << std::endl; - sif::error << "Make sure it implements ReceivesParameterMessagesIF!" << std::endl; + sif::error << "Object ID: 0x" << std::hex << *objectId << std::dec << std::endl; + sif::error << "Make sure it implements ReceivesParameterMessagesIF" << std::endl; #else sif::printError( "Service20ParameterManagement::checkInterfaceAndAcquire" "MessageQueue: Can't access object\n"); sif::printError("Object ID: 0x%08x\n", *objectId); - sif::printError("Make sure it implements ReceivesParameterMessagesIF!\n"); + sif::printError("Make sure it implements ReceivesParameterMessagesIF\n"); #endif return CommandingServiceBase::INVALID_OBJECT; } *messageQueueToSet = possibleTarget->getCommandQueue(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Service20ParameterManagement::prepareCommand(CommandMessage* message, @@ -98,7 +97,7 @@ ReturnValue_t Service20ParameterManagement::prepareCommand(CommandMessage* messa return prepareLoadCommand(message, tcData, tcDataLen); } break; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -111,7 +110,7 @@ ReturnValue_t Service20ParameterManagement::prepareDumpCommand(CommandMessage* m tcDataLen -= sizeof(object_id_t); ParameterId_t parameterId; if (SerializeAdapter::deSerialize(¶meterId, &tcData, &tcDataLen, - SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) { + SerializeIF::Endianness::BIG) != returnvalue::OK) { return CommandingServiceBase::INVALID_TC; } /* The length should have been decremented to 0 by this point */ @@ -120,7 +119,7 @@ ReturnValue_t Service20ParameterManagement::prepareDumpCommand(CommandMessage* m } ParameterMessage::setParameterDumpCommand(message, parameterId); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Service20ParameterManagement::prepareLoadCommand(CommandMessage* message, @@ -137,8 +136,8 @@ ReturnValue_t Service20ParameterManagement::prepareLoadCommand(CommandMessage* m if (parameterDataLen == 0) { return CommandingServiceBase::INVALID_TC; } - ReturnValue_t result = IPCStore->getFreeElement(&storeAddress, parameterDataLen, &storePointer); - if (result != HasReturnvaluesIF::RETURN_OK) { + ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, parameterDataLen, &storePointer); + if (result != returnvalue::OK) { return result; } @@ -151,14 +150,14 @@ ReturnValue_t Service20ParameterManagement::prepareLoadCommand(CommandMessage* m 4. Number of columns */ ParameterLoadCommand command(storePointer, parameterDataLen); result = command.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } ParameterMessage::setParameterLoadCommand(message, command.getParameterId(), storeAddress, command.getPtc(), command.getPfc(), command.getRows(), command.getColumns()); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Service20ParameterManagement::handleReply(const CommandMessage* reply, @@ -169,16 +168,15 @@ ReturnValue_t Service20ParameterManagement::handleReply(const CommandMessage* re switch (replyId) { case ParameterMessage::REPLY_PARAMETER_DUMP: { - ConstAccessorPair parameterData = IPCStore->getData(ParameterMessage::getStoreId(reply)); - if (parameterData.first != HasReturnvaluesIF::RETURN_OK) { - return HasReturnvaluesIF::RETURN_FAILED; + ConstAccessorPair parameterData = ipcStore->getData(ParameterMessage::getStoreId(reply)); + if (parameterData.first != returnvalue::OK) { + return returnvalue::FAILED; } ParameterId_t parameterId = ParameterMessage::getParameterId(reply); ParameterDumpReply parameterReply(objectId, parameterId, parameterData.second.data(), parameterData.second.size()); - sendTmPacket(static_cast(Subservice::PARAMETER_DUMP_REPLY), ¶meterReply); - return HasReturnvaluesIF::RETURN_OK; + return sendTmPacket(static_cast(Subservice::PARAMETER_DUMP_REPLY), parameterReply); } default: return CommandingServiceBase::INVALID_REPLY; diff --git a/src/fsfw/pus/Service2DeviceAccess.cpp b/src/fsfw/pus/Service2DeviceAccess.cpp index 3430271e..517c35e6 100644 --- a/src/fsfw/pus/Service2DeviceAccess.cpp +++ b/src/fsfw/pus/Service2DeviceAccess.cpp @@ -14,8 +14,8 @@ Service2DeviceAccess::Service2DeviceAccess(object_id_t objectId, uint16_t apid, uint8_t serviceId, uint8_t numberOfParallelCommands, uint16_t commandTimeoutSeconds) - : CommandingServiceBase(objectId, apid, serviceId, numberOfParallelCommands, - commandTimeoutSeconds) {} + : CommandingServiceBase(objectId, apid, "PUS 2 Raw Commanding", serviceId, + numberOfParallelCommands, commandTimeoutSeconds) {} Service2DeviceAccess::~Service2DeviceAccess() {} @@ -23,7 +23,7 @@ ReturnValue_t Service2DeviceAccess::isValidSubservice(uint8_t subservice) { switch (static_cast(subservice)) { case Subservice::COMMAND_RAW_COMMANDING: case Subservice::COMMAND_TOGGLE_WIRETAPPING: - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; default: #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "Invalid Subservice" << std::endl; @@ -51,7 +51,7 @@ ReturnValue_t Service2DeviceAccess::checkInterfaceAndAcquireMessageQueue( return CommandingServiceBase::INVALID_OBJECT; } *messageQueueToSet = possibleTarget->getCommandQueue(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Service2DeviceAccess::prepareCommand(CommandMessage* message, uint8_t subservice, @@ -65,7 +65,7 @@ ReturnValue_t Service2DeviceAccess::prepareCommand(CommandMessage* message, uint return prepareWiretappingCommand(message, tcData, tcDataLen); } break; default: - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -75,7 +75,7 @@ ReturnValue_t Service2DeviceAccess::prepareRawCommand(CommandMessage* messageToS // store command into the Inter Process Communication Store store_address_t storeAddress; ReturnValue_t result = - IPCStore->addData(&storeAddress, RawCommand.getCommand(), RawCommand.getCommandSize()); + ipcStore->addData(&storeAddress, RawCommand.getCommand(), RawCommand.getCommandSize()); DeviceHandlerMessage::setDeviceHandlerRawCommandMessage(messageToSet, storeAddress); return result; } @@ -99,7 +99,7 @@ ReturnValue_t Service2DeviceAccess::handleReply(const CommandMessage* reply, object_id_t objectId, bool* isStep) { switch (reply->getCommand()) { case CommandMessage::REPLY_COMMAND_OK: - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; case CommandMessage::REPLY_REJECTED: return reply->getReplyRejectedReason(); default: @@ -135,8 +135,8 @@ void Service2DeviceAccess::sendWiretappingTm(CommandMessage* reply, uint8_t subs store_address_t storeAddress = DeviceHandlerMessage::getStoreAddress(reply); const uint8_t* data = nullptr; size_t size = 0; - ReturnValue_t result = IPCStore->getData(storeAddress, &data, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { + ReturnValue_t result = ipcStore->getData(storeAddress, &data, &size); + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "Service2DeviceAccess::sendWiretappingTm: Data Lost in " "handleUnrequestedReply with failure ID " @@ -147,10 +147,12 @@ void Service2DeviceAccess::sendWiretappingTm(CommandMessage* reply, uint8_t subs // Init our dummy packet and correct endianness of object ID before // sending it back. - WiretappingPacket TmPacket(DeviceHandlerMessage::getDeviceObjectId(reply), data); - TmPacket.objectId = EndianConverter::convertBigEndian(TmPacket.objectId); - sendTmPacket(subservice, TmPacket.data, size, reinterpret_cast(&TmPacket.objectId), - sizeof(TmPacket.objectId)); + WiretappingPacket tmPacket(DeviceHandlerMessage::getDeviceObjectId(reply), data); + result = sendTmPacket(subservice, tmPacket.objectId, tmPacket.data, size); + if (result != returnvalue::OK) { + // TODO: Warning + return; + } } MessageQueueId_t Service2DeviceAccess::getDeviceQueue() { return commandQueue->getId(); } diff --git a/src/fsfw/pus/Service3Housekeeping.cpp b/src/fsfw/pus/Service3Housekeeping.cpp index 07574783..3ce93c70 100644 --- a/src/fsfw/pus/Service3Housekeeping.cpp +++ b/src/fsfw/pus/Service3Housekeeping.cpp @@ -5,7 +5,7 @@ #include "fsfw/pus/servicepackets/Service3Packets.h" Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId) - : CommandingServiceBase(objectId, apid, serviceId, NUM_OF_PARALLEL_COMMANDS, + : CommandingServiceBase(objectId, apid, "PUS 3 HK", serviceId, NUM_OF_PARALLEL_COMMANDS, COMMAND_TIMEOUT_SECONDS) {} Service3Housekeeping::~Service3Housekeeping() {} @@ -22,7 +22,7 @@ ReturnValue_t Service3Housekeeping::isValidSubservice(uint8_t subservice) { case Subservice::GENERATE_ONE_DIAGNOSTICS_REPORT: case Subservice::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL: case Subservice::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL: - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; // Telemetry or invalid subservice. case Subservice::HK_DEFINITIONS_REPORT: case Subservice::DIAGNOSTICS_DEFINITION_REPORT: @@ -38,7 +38,7 @@ ReturnValue_t Service3Housekeeping::getMessageQueueAndObject(uint8_t subservice, size_t tcDataLen, MessageQueueId_t* id, object_id_t* objectId) { ReturnValue_t result = checkAndAcquireTargetID(objectId, tcData, tcDataLen); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } return checkInterfaceAndAcquireMessageQueue(id, objectId); @@ -48,10 +48,10 @@ ReturnValue_t Service3Housekeeping::checkAndAcquireTargetID(object_id_t* objectI const uint8_t* tcData, size_t tcDataLen) { if (SerializeAdapter::deSerialize(objectIdToSet, &tcData, &tcDataLen, - SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) { + SerializeIF::Endianness::BIG) != returnvalue::OK) { return CommandingServiceBase::INVALID_TC; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Service3Housekeeping::checkInterfaceAndAcquireMessageQueue( @@ -63,7 +63,7 @@ ReturnValue_t Service3Housekeeping::checkInterfaceAndAcquireMessageQueue( return CommandingServiceBase::INVALID_OBJECT; } *messageQueueToSet = possibleTarget->getCommandQueue(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Service3Housekeeping::prepareCommand(CommandMessage* message, uint8_t subservice, @@ -100,9 +100,9 @@ ReturnValue_t Service3Housekeeping::prepareCommand(CommandMessage* message, uint return CommandingServiceBase::INVALID_TC; default: // should never happen, subservice was already checked. - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Service3Housekeeping::prepareReportingTogglingCommand( @@ -116,7 +116,7 @@ ReturnValue_t Service3Housekeeping::prepareReportingTogglingCommand( sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen); HousekeepingMessage::setToggleReportingCommand(command, targetSid, enableReporting, isDiagnostics); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Service3Housekeeping::prepareStructureReportingCommand(CommandMessage* command, @@ -131,7 +131,7 @@ ReturnValue_t Service3Housekeeping::prepareStructureReportingCommand(CommandMess sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen); HousekeepingMessage::setStructureReportingCommand(command, targetSid, isDiagnostics); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Service3Housekeeping::prepareOneShotReportCommand(CommandMessage* command, @@ -146,7 +146,7 @@ ReturnValue_t Service3Housekeeping::prepareOneShotReportCommand(CommandMessage* sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen); HousekeepingMessage::setOneShotReportCommand(command, targetSid, isDiagnostics); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Service3Housekeeping::prepareCollectionIntervalModificationCommand( @@ -163,7 +163,7 @@ ReturnValue_t Service3Housekeeping::prepareCollectionIntervalModificationCommand SerializeIF::Endianness::BIG); HousekeepingMessage::setCollectionIntervalModificationCommand( command, targetSid, newCollectionInterval, isDiagnostics); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply, @@ -174,7 +174,7 @@ ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply, switch (command) { case (HousekeepingMessage::HK_REPORT): { ReturnValue_t result = generateHkReply(reply, static_cast(Subservice::HK_REPORT)); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return CommandingServiceBase::EXECUTION_COMPLETE; @@ -183,7 +183,7 @@ ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply, case (HousekeepingMessage::DIAGNOSTICS_REPORT): { ReturnValue_t result = generateHkReply(reply, static_cast(Subservice::DIAGNOSTICS_REPORT)); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return CommandingServiceBase::EXECUTION_COMPLETE; @@ -205,7 +205,7 @@ ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply, case (HousekeepingMessage::HK_REQUEST_FAILURE): { failureParameter1 = objectId; - ReturnValue_t error = HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t error = returnvalue::FAILED; HousekeepingMessage::getHkRequestFailureReply(reply, &error); failureParameter2 = error; return CommandingServiceBase::EXECUTION_COMPLETE; @@ -223,11 +223,11 @@ ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply, #endif return CommandingServiceBase::INVALID_REPLY; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void Service3Housekeeping::handleUnrequestedReply(CommandMessage* reply) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; Command_t command = reply->getCommand(); switch (command) { @@ -264,7 +264,7 @@ void Service3Housekeeping::handleUnrequestedReply(CommandMessage* reply) { } } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { /* Configuration error */ #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "Service3Housekeeping::handleUnrequestedReply: Could not generate reply!" @@ -284,14 +284,13 @@ ReturnValue_t Service3Housekeeping::generateHkReply(const CommandMessage* hkMess store_address_t storeId; sid_t sid = HousekeepingMessage::getHkDataReply(hkMessage, &storeId); - auto resultPair = IPCStore->getData(storeId); - if (resultPair.first != HasReturnvaluesIF::RETURN_OK) { + auto resultPair = ipcStore->getData(storeId); + if (resultPair.first != returnvalue::OK) { return resultPair.first; } HkPacket hkPacket(sid, resultPair.second.data(), resultPair.second.size()); - return sendTmPacket(static_cast(subserviceId), hkPacket.hkData, hkPacket.hkSize, nullptr, - 0); + return sendTmPacket(static_cast(subserviceId), hkPacket.hkData, hkPacket.hkSize); } sid_t Service3Housekeeping::buildSid(object_id_t objectId, const uint8_t** tcData, diff --git a/src/fsfw/pus/Service3Housekeeping.h b/src/fsfw/pus/Service3Housekeeping.h index c1928891..70f15762 100644 --- a/src/fsfw/pus/Service3Housekeeping.h +++ b/src/fsfw/pus/Service3Housekeeping.h @@ -43,7 +43,7 @@ class Service3Housekeeping : public CommandingServiceBase, public AcceptsHkPacke CommandMessage* optionalNextCommand, object_id_t objectId, bool* isStep) override; - virtual MessageQueueId_t getHkQueue() const; + virtual MessageQueueId_t getHkQueue() const override; private: enum class Subservice { diff --git a/src/fsfw/pus/Service5EventReporting.cpp b/src/fsfw/pus/Service5EventReporting.cpp index 4517bc26..9145920c 100644 --- a/src/fsfw/pus/Service5EventReporting.cpp +++ b/src/fsfw/pus/Service5EventReporting.cpp @@ -5,13 +5,15 @@ #include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/pus/servicepackets/Service5Packets.h" #include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tmtcpacket/pus/tm/TmPacketStored.h" +#include "fsfw/tmtcservices/tmHelpers.h" -Service5EventReporting::Service5EventReporting(object_id_t objectId, uint16_t apid, - uint8_t serviceId, size_t maxNumberReportsPerCycle, +Service5EventReporting::Service5EventReporting(PsbParams params, size_t maxNumberReportsPerCycle, uint32_t messageQueueDepth) - : PusServiceBase(objectId, apid, serviceId), + : PusServiceBase(params), + storeHelper(params.apid), + tmHelper(params.serviceId, storeHelper, sendHelper), maxNumberReportsPerCycle(maxNumberReportsPerCycle) { + psbParams.name = "PUS 5 Event Reporting"; eventQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth); } @@ -21,17 +23,17 @@ Service5EventReporting::~Service5EventReporting() { ReturnValue_t Service5EventReporting::performService() { EventMessage message; - ReturnValue_t status = RETURN_OK; + ReturnValue_t status = returnvalue::OK; for (uint8_t counter = 0; counter < maxNumberReportsPerCycle; counter++) { // Receive messages even if reporting is disabled for now. status = eventQueue->receiveMessage(&message); if (status == MessageQueueIF::EMPTY) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } if (enableEventReport) { status = generateEventReport(message); - if (status != HasReturnvaluesIF::RETURN_OK) { + if (status != returnvalue::OK) { return status; } } @@ -39,22 +41,16 @@ ReturnValue_t Service5EventReporting::performService() { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "Service5EventReporting::generateEventReport: Too many events" << std::endl; #endif - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Service5EventReporting::generateEventReport(EventMessage message) { EventReport report(message.getEventId(), message.getReporter(), message.getParameter1(), message.getParameter2()); -#if FSFW_USE_PUS_C_TELEMETRY == 0 - TmPacketStoredPusA tmPacket(PusServiceBase::apid, PusServiceBase::serviceId, - message.getSeverity(), packetSubCounter++, &report); -#else - TmPacketStoredPusC tmPacket(PusServiceBase::apid, PusServiceBase::serviceId, - message.getSeverity(), packetSubCounter++, &report); -#endif - ReturnValue_t result = - tmPacket.sendPacket(requestQueue->getDefaultDestination(), requestQueue->getId()); - if (result != HasReturnvaluesIF::RETURN_OK) { + storeHelper.preparePacket(psbParams.serviceId, message.getSeverity(), tmHelper.sendCounter); + storeHelper.setSourceDataSerializable(report); + ReturnValue_t result = tmHelper.storeAndSendTmPacket(); + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "Service5EventReporting::generateEventReport: " "Could not send TM packet" @@ -72,11 +68,11 @@ ReturnValue_t Service5EventReporting::handleRequest(uint8_t subservice) { switch (subservice) { case Subservice::ENABLE: { enableEventReport = true; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } case Subservice::DISABLE: { enableEventReport = false; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } default: return AcceptsTelecommandsIF::INVALID_SUBSERVICE; @@ -86,14 +82,19 @@ ReturnValue_t Service5EventReporting::handleRequest(uint8_t subservice) { // In addition to the default PUSServiceBase initialization, this service needs // to be registered to the event manager to listen for events. ReturnValue_t Service5EventReporting::initialize() { - EventManagerIF* manager = ObjectManager::instance()->get(objects::EVENT_MANAGER); - if (manager == NULL) { - return RETURN_FAILED; - } - // register Service 5 as listener for events - ReturnValue_t result = manager->registerListener(eventQueue->getId(), true); - if (result != HasReturnvaluesIF::RETURN_OK) { + ReturnValue_t result = PusServiceBase::initialize(); + if (result != returnvalue::OK) { return result; } - return PusServiceBase::initialize(); + auto* manager = ObjectManager::instance()->get(objects::EVENT_MANAGER); + if (manager == nullptr) { + return returnvalue::FAILED; + } + // register Service 5 as listener for events + result = manager->registerListener(eventQueue->getId(), true); + if (result != returnvalue::OK) { + return result; + } + initializeTmHelpers(sendHelper, storeHelper); + return result; } diff --git a/src/fsfw/pus/Service5EventReporting.h b/src/fsfw/pus/Service5EventReporting.h index 74264130..1f4e5a3a 100644 --- a/src/fsfw/pus/Service5EventReporting.h +++ b/src/fsfw/pus/Service5EventReporting.h @@ -3,6 +3,7 @@ #include "fsfw/events/EventMessage.h" #include "fsfw/tmtcservices/PusServiceBase.h" +#include "fsfw/tmtcservices/TmStoreAndSendHelper.h" /** * @brief Report on-board events like information or errors @@ -40,9 +41,9 @@ */ class Service5EventReporting : public PusServiceBase { public: - Service5EventReporting(object_id_t objectId, uint16_t apid, uint8_t serviceId, - size_t maxNumberReportsPerCycle = 10, uint32_t messageQueueDepth = 10); - virtual ~Service5EventReporting(); + Service5EventReporting(PsbParams params, size_t maxNumberReportsPerCycle = 10, + uint32_t messageQueueDepth = 10); + ~Service5EventReporting() override; /*** * Check for events and generate event reports if required. @@ -74,9 +75,11 @@ class Service5EventReporting : public PusServiceBase { }; private: - uint16_t packetSubCounter = 0; MessageQueueIF* eventQueue = nullptr; bool enableEventReport = true; + TmSendHelper sendHelper; + TmStoreHelper storeHelper; + TmStoreAndSendWrapper tmHelper; const uint8_t maxNumberReportsPerCycle; ReturnValue_t generateEventReport(EventMessage message); diff --git a/src/fsfw/pus/Service8FunctionManagement.cpp b/src/fsfw/pus/Service8FunctionManagement.cpp index be8d9058..8b7c6972 100644 --- a/src/fsfw/pus/Service8FunctionManagement.cpp +++ b/src/fsfw/pus/Service8FunctionManagement.cpp @@ -12,15 +12,15 @@ Service8FunctionManagement::Service8FunctionManagement(object_id_t objectId, uin uint8_t serviceId, uint8_t numParallelCommands, uint16_t commandTimeoutSeconds) - : CommandingServiceBase(objectId, apid, serviceId, numParallelCommands, commandTimeoutSeconds) { -} + : CommandingServiceBase(objectId, apid, "PUS 8 Functional Commanding", serviceId, + numParallelCommands, commandTimeoutSeconds) {} Service8FunctionManagement::~Service8FunctionManagement() {} ReturnValue_t Service8FunctionManagement::isValidSubservice(uint8_t subservice) { switch (static_cast(subservice)) { case Subservice::COMMAND_DIRECT_COMMANDING: - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; default: return AcceptsTelecommandsIF::INVALID_SUBSERVICE; } @@ -48,7 +48,7 @@ ReturnValue_t Service8FunctionManagement::checkInterfaceAndAcquireMessageQueue( return CommandingServiceBase::INVALID_OBJECT; } *messageQueueToSet = possibleTarget->getCommandQueue(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Service8FunctionManagement::prepareCommand(CommandMessage* message, @@ -62,7 +62,7 @@ ReturnValue_t Service8FunctionManagement::prepareDirectCommand(CommandMessage* m const uint8_t* tcData, size_t tcDataLen) { if (message == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (tcDataLen < sizeof(object_id_t) + sizeof(ActionId_t)) { #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -78,7 +78,7 @@ ReturnValue_t Service8FunctionManagement::prepareDirectCommand(CommandMessage* m // store additional parameters into the IPC Store store_address_t parameterAddress; ReturnValue_t result = - IPCStore->addData(¶meterAddress, command.getParameters(), command.getParametersSize()); + ipcStore->addData(¶meterAddress, command.getParameters(), command.getParametersSize()); // setCommand expects a Command Message, an Action ID and a store adress // pointing to additional parameters @@ -91,7 +91,7 @@ ReturnValue_t Service8FunctionManagement::handleReply(const CommandMessage* repl CommandMessage* optionalNextCommand, object_id_t objectId, bool* isStep) { Command_t replyId = reply->getCommand(); - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t result = returnvalue::FAILED; ActionId_t actionId = ActionMessage::getActionId(reply); ReturnValue_t returnCode = ActionMessage::getReturnCode(reply); @@ -103,7 +103,7 @@ ReturnValue_t Service8FunctionManagement::handleReply(const CommandMessage* repl } case ActionMessage::STEP_SUCCESS: { *isStep = true; - result = HasReturnvaluesIF::RETURN_OK; + result = returnvalue::OK; break; } case ActionMessage::DATA_REPLY: { @@ -130,18 +130,18 @@ ReturnValue_t Service8FunctionManagement::handleDataReply(const CommandMessage* store_address_t storeId = ActionMessage::getStoreId(reply); size_t size = 0; const uint8_t* buffer = nullptr; - ReturnValue_t result = IPCStore->getData(storeId, &buffer, &size); - if (result != RETURN_OK) { + ReturnValue_t result = ipcStore->getData(storeId, &buffer, &size); + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "Service 8: Could not retrieve data for data reply" << std::endl; #endif return result; } DataReply dataReply(objectId, actionId, buffer, size); - result = sendTmPacket(static_cast(Subservice::REPLY_DIRECT_COMMANDING_DATA), &dataReply); + result = sendTmPacket(static_cast(Subservice::REPLY_DIRECT_COMMANDING_DATA), dataReply); - auto deletionResult = IPCStore->deleteData(storeId); - if (deletionResult != HasReturnvaluesIF::RETURN_OK) { + auto deletionResult = ipcStore->deleteData(storeId); + if (deletionResult != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "Service8FunctionManagement::handleReply: Deletion" << " of data in pool failed." << std::endl; diff --git a/src/fsfw/pus/Service8FunctionManagement.h b/src/fsfw/pus/Service8FunctionManagement.h index 649b3257..38aaf4f4 100644 --- a/src/fsfw/pus/Service8FunctionManagement.h +++ b/src/fsfw/pus/Service8FunctionManagement.h @@ -32,7 +32,7 @@ class Service8FunctionManagement : public CommandingServiceBase { public: Service8FunctionManagement(object_id_t objectId, uint16_t apid, uint8_t serviceId, uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60); - virtual ~Service8FunctionManagement(); + ~Service8FunctionManagement() override; protected: /* CSB abstract functions implementation . See CSB documentation. */ diff --git a/src/fsfw/pus/Service9TimeManagement.cpp b/src/fsfw/pus/Service9TimeManagement.cpp index 86eef93a..fb32f60e 100644 --- a/src/fsfw/pus/Service9TimeManagement.cpp +++ b/src/fsfw/pus/Service9TimeManagement.cpp @@ -1,23 +1,33 @@ #include "fsfw/pus/Service9TimeManagement.h" +#include + #include "fsfw/events/EventManagerIF.h" #include "fsfw/pus/servicepackets/Service9Packets.h" #include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/timemanager/CCSDSTime.h" -Service9TimeManagement::Service9TimeManagement(object_id_t objectId, uint16_t apid, - uint8_t serviceId) - : PusServiceBase(objectId, apid, serviceId) {} +Service9TimeManagement::Service9TimeManagement(PsbParams params) : PusServiceBase(params) { + params.name = "PUS 9 Time MGMT"; +} -Service9TimeManagement::~Service9TimeManagement() {} +Service9TimeManagement::~Service9TimeManagement() = default; -ReturnValue_t Service9TimeManagement::performService() { return RETURN_OK; } +ReturnValue_t Service9TimeManagement::performService() { return returnvalue::OK; } ReturnValue_t Service9TimeManagement::handleRequest(uint8_t subservice) { switch (subservice) { - case SUBSERVICE::SET_TIME: { + case Subservice::SET_TIME: { return setTime(); } + case Subservice::DUMP_TIME: { + timeval newTime; + Clock::getClock_timeval(&newTime); + uint32_t subsecondMs = + static_cast(std::floor(static_cast(newTime.tv_usec) / 1000.0)); + triggerEvent(CLOCK_DUMP, newTime.tv_sec, subsecondMs); + return returnvalue::OK; + } default: return AcceptsTelecommandsIF::INVALID_SUBSERVICE; } @@ -25,25 +35,25 @@ ReturnValue_t Service9TimeManagement::handleRequest(uint8_t subservice) { ReturnValue_t Service9TimeManagement::setTime() { Clock::TimeOfDay_t timeToSet; - TimePacket timePacket(currentPacket.getApplicationData(), currentPacket.getApplicationDataSize()); + TimePacket timePacket(currentPacket.getUserData(), currentPacket.getUserDataLen()); ReturnValue_t result = CCSDSTime::convertFromCcsds(&timeToSet, timePacket.getTime(), timePacket.getTimeSize()); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { triggerEvent(CLOCK_SET_FAILURE, result, 0); return result; } - uint32_t formerUptime; - Clock::getUptime(&formerUptime); + timeval time; + Clock::getClock_timeval(&time); result = Clock::setClock(&timeToSet); - if (result == RETURN_OK) { - uint32_t newUptime; - Clock::getUptime(&newUptime); - triggerEvent(CLOCK_SET, newUptime, formerUptime); - return RETURN_OK; + if (result == returnvalue::OK) { + timeval newTime; + Clock::getClock_timeval(&newTime); + triggerEvent(CLOCK_SET, time.tv_sec, newTime.tv_sec); + return returnvalue::OK; } else { triggerEvent(CLOCK_SET_FAILURE, result, 0); - return RETURN_FAILED; + return returnvalue::FAILED; } } diff --git a/src/fsfw/pus/Service9TimeManagement.h b/src/fsfw/pus/Service9TimeManagement.h index 9369e207..556f3df3 100644 --- a/src/fsfw/pus/Service9TimeManagement.h +++ b/src/fsfw/pus/Service9TimeManagement.h @@ -6,32 +6,36 @@ 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: old timeval seconds. P2: new timeval seconds. + static constexpr Event CLOCK_SET = MAKE_EVENT(0, severity::INFO); + //!< Clock dump event. P1: timeval seconds P2: timeval milliseconds. + static constexpr Event CLOCK_DUMP = MAKE_EVENT(1, severity::INFO); + //!< Clock could not be set. P1: Returncode. + static constexpr Event CLOCK_SET_FAILURE = MAKE_EVENT(2, severity::LOW); static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9; /** * @brief This service provides the capability to set the on-board time. */ - Service9TimeManagement(object_id_t objectId, uint16_t apid, uint8_t serviceId); + explicit Service9TimeManagement(PsbParams params); - virtual ~Service9TimeManagement(); + ~Service9TimeManagement() override; - virtual ReturnValue_t performService() override; + ReturnValue_t performService() override; /** * @brief Sets the onboard-time by retrieving the time to set from TC[9,128]. */ - virtual ReturnValue_t handleRequest(uint8_t subservice) override; + ReturnValue_t handleRequest(uint8_t subservice) override; virtual ReturnValue_t setTime(); private: - enum SUBSERVICE { - SET_TIME = 128 //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format + enum Subservice { + SET_TIME = 128, //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format + DUMP_TIME = 129, }; }; diff --git a/src/fsfw/pus/servicepackets/Service1Packets.h b/src/fsfw/pus/servicepackets/Service1Packets.h index df70f670..70bf167e 100644 --- a/src/fsfw/pus/servicepackets/Service1Packets.h +++ b/src/fsfw/pus/servicepackets/Service1Packets.h @@ -42,26 +42,26 @@ class FailureReport : public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 2, 4, 6 SerializeIF::Endianness streamEndianness) const override { ReturnValue_t result = SerializeAdapter::serialize(&packetId, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&packetSequenceControl, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } - if (failureSubtype == tc_verification::PROGRESS_FAILURE) { + if (failureSubtype == tcverif::PROGRESS_FAILURE) { result = SerializeAdapter::serialize(&stepNumber, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } } result = SerializeAdapter::serialize(&errorCode, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&errorParameter1, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -73,7 +73,7 @@ class FailureReport : public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 2, 4, 6 size_t size = 0; size += SerializeAdapter::getSerializedSize(&packetId); size += sizeof(packetSequenceControl); - if (failureSubtype == tc_verification::PROGRESS_FAILURE) { + if (failureSubtype == tcverif::PROGRESS_FAILURE) { size += SerializeAdapter::getSerializedSize(&stepNumber); } size += SerializeAdapter::getSerializedSize(&errorCode); @@ -91,7 +91,7 @@ class FailureReport : public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 2, 4, 6 */ ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, SerializeIF::Endianness streamEndianness) override { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } private: @@ -122,17 +122,17 @@ class SuccessReport : public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 1, 3, 5 SerializeIF::Endianness streamEndianness) const override { ReturnValue_t result = SerializeAdapter::serialize(&packetId, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&packetSequenceControl, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } - if (subtype == tc_verification::PROGRESS_SUCCESS) { + if (subtype == tcverif::PROGRESS_SUCCESS) { result = SerializeAdapter::serialize(&stepNumber, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } } @@ -143,7 +143,7 @@ class SuccessReport : public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 1, 3, 5 size_t size = 0; size += SerializeAdapter::getSerializedSize(&packetId); size += sizeof(packetSequenceControl); - if (subtype == tc_verification::PROGRESS_SUCCESS) { + if (subtype == tcverif::PROGRESS_SUCCESS) { size += SerializeAdapter::getSerializedSize(&stepNumber); } return size; @@ -151,7 +151,7 @@ class SuccessReport : public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 1, 3, 5 ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, SerializeIF::Endianness streamEndianness) override { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } private: diff --git a/src/fsfw/pus/servicepackets/Service5Packets.h b/src/fsfw/pus/servicepackets/Service5Packets.h index 9ff2e4d4..1357b3c0 100644 --- a/src/fsfw/pus/servicepackets/Service5Packets.h +++ b/src/fsfw/pus/servicepackets/Service5Packets.h @@ -24,29 +24,29 @@ class EventReport : public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 1, 2, 3, parameter1(parameter1_), parameter2(parameter2_) {} - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - SerializeIF::Endianness streamEndianness) const override { + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const override { ReturnValue_t result = SerializeAdapter::serialize(&reportId, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&objectId, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(¶meter1, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(¶meter2, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return result; } - virtual size_t getSerializedSize() const override { + size_t getSerializedSize() const override { uint32_t size = 0; size += SerializeAdapter::getSerializedSize(&reportId); size += SerializeAdapter::getSerializedSize(&objectId); @@ -55,9 +55,9 @@ class EventReport : public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 1, 2, 3, return size; } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - SerializeIF::Endianness streamEndianness) override { - return HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override { + return returnvalue::FAILED; } private: diff --git a/src/fsfw/pus/servicepackets/Service9Packets.h b/src/fsfw/pus/servicepackets/Service9Packets.h index 076536e8..082a65fa 100644 --- a/src/fsfw/pus/servicepackets/Service9Packets.h +++ b/src/fsfw/pus/servicepackets/Service9Packets.h @@ -1,7 +1,7 @@ #ifndef FSFW_PUS_SERVICEPACKETS_SERVICE9PACKETS_H_ #define FSFW_PUS_SERVICEPACKETS_SERVICE9PACKETS_H_ -#include "../../serialize/SerialLinkedListAdapter.h" +#include "fsfw/serialize/SerialLinkedListAdapter.h" /** * @brief Subservice 128 @@ -11,16 +11,16 @@ */ class TimePacket : SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 128 public: + TimePacket(const TimePacket& command) = delete; TimePacket(const uint8_t* timeBuffer_, uint32_t timeSize_) { timeBuffer = timeBuffer_; timeSize = timeSize_; } const uint8_t* getTime() { return timeBuffer; } - uint32_t getTimeSize() const { return timeSize; } + [[nodiscard]] uint32_t getTimeSize() const { return timeSize; } private: - TimePacket(const TimePacket& command); const uint8_t* timeBuffer; uint32_t timeSize; //!< [EXPORT] : [IGNORE] }; diff --git a/src/fsfw/returnvalues/FwClassIds.h b/src/fsfw/returnvalues/FwClassIds.h index d07cedc9..9a5cc812 100644 --- a/src/fsfw/returnvalues/FwClassIds.h +++ b/src/fsfw/returnvalues/FwClassIds.h @@ -34,9 +34,10 @@ enum : uint8_t { FIFO_CLASS, // FF MESSAGE_PROXY, // MQP TRIPLE_REDUNDACY_CHECK, // TRC - TC_PACKET_CHECK, // TCC + TMTC_DISTRIBUTION, // TCC PACKET_DISTRIBUTION, // TCD - ACCEPTS_TELECOMMANDS_IF, // PUS + ACCEPTS_TELECOMMANDS_IF, // ATC + PUS_IF, // PUS DEVICE_SERVICE_BASE, // DSB COMMAND_SERVICE_BASE, // CSB TM_STORE_BACKEND_IF, // TMB @@ -72,6 +73,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 diff --git a/src/fsfw/returnvalues/HasReturnvaluesIF.h b/src/fsfw/returnvalues/HasReturnvaluesIF.h index eec80228..325b07e9 100644 --- a/src/fsfw/returnvalues/HasReturnvaluesIF.h +++ b/src/fsfw/returnvalues/HasReturnvaluesIF.h @@ -1,31 +1,8 @@ -#ifndef FSFW_RETURNVALUES_HASRETURNVALUESIF_H_ -#define FSFW_RETURNVALUES_HASRETURNVALUESIF_H_ +#ifndef FSFW_RETURNVALUES_HASRETURNVALUES_IF_H_ +#define FSFW_RETURNVALUES_HASRETURNVALUES_IF_H_ -#include +#warning "This header is deprecated, please include returnvalue.h" -#include +#include "returnvalue.h" -#include "FwClassIds.h" - -#define MAKE_RETURN_CODE(number) ((INTERFACE_ID << 8) + (number)) -typedef uint16_t ReturnValue_t; - -class HasReturnvaluesIF { - public: - static const ReturnValue_t RETURN_OK = 0; - static const ReturnValue_t RETURN_FAILED = 1; - virtual ~HasReturnvaluesIF() {} - - /** - * It is discouraged to use the input parameters 0,0 and 0,1 as this - * will generate the RETURN_OK and RETURN_FAILED returnvalues. - * @param interfaceId - * @param number - * @return - */ - static constexpr ReturnValue_t makeReturnCode(uint8_t classId, uint8_t number) { - return (static_cast(classId) << 8) + number; - } -}; - -#endif /* FSFW_RETURNVALUES_HASRETURNVALUESIF_H_ */ +#endif /* FSFW_RETURNVALUES_HASRETURNVALUES_IF_H_ */ diff --git a/src/fsfw/returnvalues/returnvalue.h b/src/fsfw/returnvalues/returnvalue.h new file mode 100644 index 00000000..8396cbbf --- /dev/null +++ b/src/fsfw/returnvalues/returnvalue.h @@ -0,0 +1,29 @@ +#ifndef FSFW_RETURNVALUES_RETURNVALUE_H_ +#define FSFW_RETURNVALUES_RETURNVALUE_H_ + +#include + +#include "FwClassIds.h" + +#define MAKE_RETURN_CODE(number) ((INTERFACE_ID << 8) + (number)) + +typedef uint16_t ReturnValue_t; + +namespace returnvalue { +static const ReturnValue_t OK = 0; +static const ReturnValue_t FAILED = 1; + +/** + * It is discouraged to use the input parameters 0,0 and 0,1 as this + * will generate the returnvalue::OK and returnvalue::FAILED returnvalues. + * @param interfaceId + * @param number + * @return + */ +static constexpr ReturnValue_t makeCode(uint8_t classId, uint8_t number) { + return (static_cast(classId) << 8) + number; +} + +} // namespace returnvalue + +#endif /* FSFW_RETURNVALUES_RETURNVALUE_H_ */ diff --git a/src/fsfw/retval.h b/src/fsfw/retval.h new file mode 100644 index 00000000..1ef15ab3 --- /dev/null +++ b/src/fsfw/retval.h @@ -0,0 +1,6 @@ +#ifndef FSFW_RETVAL_H +#define FSFW_RETVAL_H + +#include "fsfw/returnvalues/returnvalue.h" + +#endif // FSFW_RETVAL_H diff --git a/src/fsfw/rmap/CMakeLists.txt b/src/fsfw/rmap/CMakeLists.txt index 78c99e42..44184860 100644 --- a/src/fsfw/rmap/CMakeLists.txt +++ b/src/fsfw/rmap/CMakeLists.txt @@ -1,7 +1,2 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - RMAP.cpp - RMAPCookie.cpp - RmapDeviceCommunicationIF.cpp -) - +target_sources(${LIB_FSFW_NAME} PRIVATE RMAP.cpp RMAPCookie.cpp + RmapDeviceCommunicationIF.cpp) diff --git a/src/fsfw/rmap/RMAP.h b/src/fsfw/rmap/RMAP.h index d274fb15..df6eaf5e 100644 --- a/src/fsfw/rmap/RMAP.h +++ b/src/fsfw/rmap/RMAP.h @@ -1,7 +1,7 @@ #ifndef FSFW_RMAP_RMAP_H_ #define FSFW_RMAP_RMAP_H_ -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/rmap/RMAPCookie.h" #include "rmapConf.h" @@ -36,7 +36,7 @@ * assignment can be changed at runtime to allow for example redundancy switching. This API is * static as the information which channel to use is contained within the cookie. */ -class RMAP : public HasReturnvaluesIF { +class RMAP { public: static const uint8_t INTERFACE_ID = CLASS_ID::RMAP_CHANNEL; diff --git a/src/fsfw/rmap/RMAPChannelIF.h b/src/fsfw/rmap/RMAPChannelIF.h index 9e666dfb..60d439d0 100644 --- a/src/fsfw/rmap/RMAPChannelIF.h +++ b/src/fsfw/rmap/RMAPChannelIF.h @@ -4,7 +4,7 @@ #include #include "RMAPCookie.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "rmapConf.h" class RMAPChannelIF { @@ -21,7 +21,7 @@ class RMAPChannelIF { * @return * - @c LINK_DOWN when the link is down and all replies were missed * - @c COMMAND_CHANNEL_DEACTIVATED if the channel's port is NULL - * - @c RETURN_OK else + * - @c returnvalue::OK else */ virtual ReturnValue_t reset() = 0; @@ -72,7 +72,7 @@ class RMAPChannelIF { * @param data data to be sent * @param datalen length of data * @return - * - @c RETURN_OK + * - @c returnvalue::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 diff --git a/src/fsfw/rmap/RmapDeviceCommunicationIF.cpp b/src/fsfw/rmap/RmapDeviceCommunicationIF.cpp index cf5d49ea..70a5e7a6 100644 --- a/src/fsfw/rmap/RmapDeviceCommunicationIF.cpp +++ b/src/fsfw/rmap/RmapDeviceCommunicationIF.cpp @@ -26,7 +26,7 @@ ReturnValue_t RmapDeviceCommunicationIF::readReceivedMessage(CookieIF *cookie, u ReturnValue_t RmapDeviceCommunicationIF::setAddress(CookieIF *cookie, uint32_t address) { ((RMAPCookie *)cookie)->setAddress(address); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } uint32_t RmapDeviceCommunicationIF::getAddress(CookieIF *cookie) { @@ -35,7 +35,7 @@ uint32_t RmapDeviceCommunicationIF::getAddress(CookieIF *cookie) { ReturnValue_t RmapDeviceCommunicationIF::setParameter(CookieIF *cookie, uint32_t parameter) { // TODO Empty? - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } uint32_t RmapDeviceCommunicationIF::getParameter(CookieIF *cookie) { return 0; } diff --git a/src/fsfw/rmap/RmapDeviceCommunicationIF.h b/src/fsfw/rmap/RmapDeviceCommunicationIF.h index abe94685..9bbf8466 100644 --- a/src/fsfw/rmap/RmapDeviceCommunicationIF.h +++ b/src/fsfw/rmap/RmapDeviceCommunicationIF.h @@ -25,7 +25,7 @@ class RmapDeviceCommunicationIF : public DeviceCommunicationIF { * this can be performed in this function, which is called on device handler * initialization. * @param cookie - * @return -@c RETURN_OK if initialization was successfull + * @return -@c returnvalue::OK if initialization was successfull * - Everything else triggers failure event with returnvalue as parameter 1 */ virtual ReturnValue_t initializeInterface(CookieIF *cookie) = 0; @@ -37,7 +37,7 @@ class RmapDeviceCommunicationIF : public DeviceCommunicationIF { * @param cookie * @param data * @param len - * @return -@c RETURN_OK for successfull send + * @return -@c returnvalue::OK for successfull send * - Everything else triggers failure event with returnvalue as parameter 1 */ virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen); @@ -46,7 +46,7 @@ class RmapDeviceCommunicationIF : public DeviceCommunicationIF { * Called by DHB in the GET_WRITE doGetWrite(). * Get send confirmation that the data in sendMessage() was sent successfully. * @param cookie - * @return -@c RETURN_OK if data was sent successfull + * @return -@c returnvalue::OK if data was sent successfull * - Everything else triggers falure event with returnvalue as parameter 1 */ virtual ReturnValue_t getSendSuccess(CookieIF *cookie); @@ -57,7 +57,7 @@ class RmapDeviceCommunicationIF : public DeviceCommunicationIF { * from a device. * * @param cookie - * @return -@c RETURN_OK to confirm the request for data has been sent. + * @return -@c returnvalue::OK to confirm the request for data has been sent. * -@c NO_READ_REQUEST if no request shall be made. readReceivedMessage() * will not be called in the respective communication cycle. * - Everything else triggers failure event with returnvalue as parameter 1 @@ -71,7 +71,7 @@ class RmapDeviceCommunicationIF : public DeviceCommunicationIF { * @param cookie * @param data * @param len - * @return @c RETURN_OK for successfull receive + * @return @c returnvalue::OK for successfull receive * - Everything else triggers failure event with returnvalue as parameter 1 */ virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size); diff --git a/src/fsfw/rmap/rmapStructs.h b/src/fsfw/rmap/rmapStructs.h index 55e32606..1e86734b 100644 --- a/src/fsfw/rmap/rmapStructs.h +++ b/src/fsfw/rmap/rmapStructs.h @@ -10,11 +10,11 @@ ////////////////////////////////////////////////////////////////////////////////// // RMAP command bits -//#define RMAP_COMMAND_BIT_INCREMENT 2 -//#define RMAP_COMMAND_BIT_REPLY 3 -//#define RMAP_COMMAND_BIT_WRITE 5 -//#define RMAP_COMMAND_BIT_VERIFY 4 -//#define RMAP_COMMAND_BIT 6 +// #define RMAP_COMMAND_BIT_INCREMENT 2 +// #define RMAP_COMMAND_BIT_REPLY 3 +// #define RMAP_COMMAND_BIT_WRITE 5 +// #define RMAP_COMMAND_BIT_VERIFY 4 +// #define RMAP_COMMAND_BIT 6 namespace RMAPIds { @@ -32,14 +32,14 @@ static const uint8_t RMAP_COMMAND_READ = ((1 << RMAP_COMMAND_BIT) | (1 << RMAP_C static const uint8_t RMAP_REPLY_WRITE = ((1 << RMAP_COMMAND_BIT_WRITE) | (1 << RMAP_COMMAND_BIT_REPLY)); static const uint8_t RMAP_REPLY_READ = ((1 << RMAP_COMMAND_BIT_REPLY)); -//#define RMAP_COMMAND_WRITE ((1< #include -#include "../osal/Endiness.h" +#include "fsfw/osal/Endiness.h" /** * Helper class to convert variables or bitstreams between machine @@ -36,7 +36,7 @@ */ class EndianConverter { private: - EndianConverter(){}; + EndianConverter() = default; public: /** @@ -49,8 +49,8 @@ class EndianConverter { #error BYTE_ORDER_SYSTEM not defined #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN T tmp; - uint8_t *pointerOut = (uint8_t *)&tmp; - uint8_t *pointerIn = (uint8_t *)∈ + auto *pointerOut = reinterpret_cast(&tmp); + auto *pointerIn = reinterpret_cast(&in); for (size_t count = 0; count < sizeof(T); count++) { pointerOut[sizeof(T) - count - 1] = pointerIn[count]; } @@ -73,10 +73,8 @@ class EndianConverter { for (size_t count = 0; count < size; count++) { out[size - count - 1] = in[count]; } - return; #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN memcpy(out, in, size); - return; #endif } @@ -90,8 +88,8 @@ class EndianConverter { #error BYTE_ORDER_SYSTEM not defined #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN T tmp; - uint8_t *pointerOut = (uint8_t *)&tmp; - uint8_t *pointerIn = (uint8_t *)∈ + auto *pointerOut = reinterpret_cast(&tmp); + auto *pointerIn = reinterpret_cast(&in); for (size_t count = 0; count < sizeof(T); count++) { pointerOut[sizeof(T) - count - 1] = pointerIn[count]; } @@ -113,10 +111,8 @@ class EndianConverter { for (size_t count = 0; count < size; count++) { out[size - count - 1] = in[count]; } - return; #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN memcpy(out, in, size); - return; #endif } }; diff --git a/src/fsfw/serialize/SerialArrayListAdapter.h b/src/fsfw/serialize/SerialArrayListAdapter.h index d7c99aae..670eb700 100644 --- a/src/fsfw/serialize/SerialArrayListAdapter.h +++ b/src/fsfw/serialize/SerialArrayListAdapter.h @@ -16,8 +16,10 @@ class SerialArrayListAdapter : public SerializeIF { public: SerialArrayListAdapter(ArrayList* adaptee) : adaptee(adaptee) {} - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const { + using SerializeIF::serialize; // we overload this function as well, so this is needed to uncofuse + // the compiler + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override { return serialize(adaptee, buffer, size, maxSize, streamEndianness); } @@ -26,7 +28,7 @@ class SerialArrayListAdapter : public SerializeIF { ReturnValue_t result = SerializeAdapter::serialize(&list->size, buffer, size, maxSize, streamEndianness); count_t i = 0; - while ((result == HasReturnvaluesIF::RETURN_OK) && (i < list->size)) { + while ((result == returnvalue::OK) && (i < list->size)) { result = SerializeAdapter::serialize(&list->entries[i], buffer, size, maxSize, streamEndianness); ++i; @@ -34,7 +36,7 @@ class SerialArrayListAdapter : public SerializeIF { return result; } - virtual size_t getSerializedSize() const { return getSerializedSize(adaptee); } + size_t getSerializedSize() const override { return getSerializedSize(adaptee); } static uint32_t getSerializedSize(const ArrayList* list) { uint32_t printSize = sizeof(count_t); @@ -47,8 +49,10 @@ class SerialArrayListAdapter : public SerializeIF { return printSize; } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) { + using SerializeIF::deSerialize; // we overload this function as well, so this is needed to + // uncofuse the compiler + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override { return deSerialize(adaptee, buffer, size, streamEndianness); } @@ -56,7 +60,7 @@ class SerialArrayListAdapter : public SerializeIF { size_t* size, Endianness streamEndianness) { count_t tempSize = 0; ReturnValue_t result = SerializeAdapter::deSerialize(&tempSize, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (tempSize > list->maxSize()) { @@ -65,7 +69,7 @@ class SerialArrayListAdapter : public SerializeIF { list->size = tempSize; count_t i = 0; - while ((result == HasReturnvaluesIF::RETURN_OK) && (i < list->size)) { + while ((result == returnvalue::OK) && (i < list->size)) { result = SerializeAdapter::deSerialize(&list->front()[i], buffer, size, streamEndianness); ++i; } diff --git a/src/fsfw/serialize/SerialBufferAdapter.cpp b/src/fsfw/serialize/SerialBufferAdapter.cpp index 83129982..01eb76f9 100644 --- a/src/fsfw/serialize/SerialBufferAdapter.cpp +++ b/src/fsfw/serialize/SerialBufferAdapter.cpp @@ -21,16 +21,16 @@ SerialBufferAdapter::SerialBufferAdapter(uint8_t* buffer, count_t buffe bufferLength(bufferLength) {} template -SerialBufferAdapter::~SerialBufferAdapter() {} +SerialBufferAdapter::~SerialBufferAdapter() = default; template -ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, size_t* size, +ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer_, size_t* size, size_t maxSize, Endianness streamEndianness) const { if (serializeLength) { ReturnValue_t result = - SerializeAdapter::serialize(&bufferLength, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + SerializeAdapter::serialize(&bufferLength, buffer_, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { return result; } } @@ -40,17 +40,17 @@ ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, size_t* } if (this->constBuffer != nullptr) { - std::memcpy(*buffer, this->constBuffer, bufferLength); + std::memcpy(*buffer_, this->constBuffer, bufferLength); } else if (this->buffer != nullptr) { // This will propably be never reached, constBuffer should always be // set if non-const buffer is set. - std::memcpy(*buffer, this->buffer, bufferLength); + std::memcpy(*buffer_, this->buffer, bufferLength); } else { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } *size += bufferLength; - (*buffer) += bufferLength; - return HasReturnvaluesIF::RETURN_OK; + (*buffer_) += bufferLength; + return returnvalue::OK; } template @@ -63,17 +63,17 @@ size_t SerialBufferAdapter::getSerializedSize() const { } template -ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, size_t* size, +ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer_, size_t* size, Endianness streamEndianness) { if (this->buffer == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (serializeLength) { count_t lengthField = 0; ReturnValue_t result = - SerializeAdapter::deSerialize(&lengthField, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + SerializeAdapter::deSerialize(&lengthField, buffer_, size, streamEndianness); + if (result != returnvalue::OK) { return result; } if (lengthField > bufferLength) { @@ -84,9 +84,9 @@ ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, if (bufferLength <= *size) { *size -= bufferLength; - std::memcpy(this->buffer, *buffer, bufferLength); - (*buffer) += bufferLength; - return HasReturnvaluesIF::RETURN_OK; + std::memcpy(this->buffer, *buffer_, bufferLength); + (*buffer_) += bufferLength; + return returnvalue::OK; } else { return STREAM_TOO_SHORT; } @@ -119,10 +119,10 @@ const uint8_t* SerialBufferAdapter::getConstBuffer() const { } template -void SerialBufferAdapter::setBuffer(uint8_t* buffer, count_t bufferLength) { - this->buffer = buffer; - this->constBuffer = buffer; - this->bufferLength = bufferLength; +void SerialBufferAdapter::setConstBuffer(const uint8_t* buf, count_t bufLen) { + this->buffer = nullptr; + this->bufferLength = bufLen; + this->constBuffer = buf; } // forward Template declaration for linker diff --git a/src/fsfw/serialize/SerialBufferAdapter.h b/src/fsfw/serialize/SerialBufferAdapter.h index 3b95fa20..9030d7cc 100644 --- a/src/fsfw/serialize/SerialBufferAdapter.h +++ b/src/fsfw/serialize/SerialBufferAdapter.h @@ -21,6 +21,7 @@ template class SerialBufferAdapter : public SerializeIF { public: + SerialBufferAdapter() = default; /** * Constructor for constant uint8_t buffer. Length field can be serialized optionally. * Type of length can be supplied as template type. @@ -40,12 +41,12 @@ class SerialBufferAdapter : public SerializeIF { */ SerialBufferAdapter(uint8_t* buffer, count_t bufferLength, bool serializeLength = false); - virtual ~SerialBufferAdapter(); + ~SerialBufferAdapter() override; - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const override; + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override; - virtual size_t getSerializedSize() const override; + [[nodiscard]] size_t getSerializedSize() const override; /** * @brief This function deserializes a buffer into the member buffer. @@ -53,18 +54,18 @@ class SerialBufferAdapter : public SerializeIF { * If a length field is present, it is ignored, as the size should have * been set in the constructor. If the size is not known beforehand, * consider using SerialFixedArrayListAdapter instead. - * @param buffer [out] Resulting buffer + * @param buffer_ [out] Resulting buffer * @param size remaining size to deserialize, should be larger than buffer * + size field size * @param bigEndian * @return */ - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) override; + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; uint8_t* getBuffer(); - const uint8_t* getConstBuffer() const; - void setBuffer(uint8_t* buffer, count_t bufferLength); + [[nodiscard]] const uint8_t* getConstBuffer() const; + void setConstBuffer(const uint8_t* buf, count_t bufLen); private: bool serializeLength = false; diff --git a/src/fsfw/serialize/SerialLinkedListAdapter.h b/src/fsfw/serialize/SerialLinkedListAdapter.h index 4975c0a5..b37320ff 100644 --- a/src/fsfw/serialize/SerialLinkedListAdapter.h +++ b/src/fsfw/serialize/SerialLinkedListAdapter.h @@ -45,13 +45,15 @@ class SerialLinkedListAdapter : public SinglyLinkedList, public SerializeIF { SerialLinkedListAdapter(bool printCount = false) : SinglyLinkedList(), printCount(printCount) {} - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const override { + using SerializeIF::serialize; // we overloaded this function, so this is needed to unconfuse the + // compiler + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override { if (printCount) { count_t mySize = SinglyLinkedList::getSize(); ReturnValue_t result = SerializeAdapter::serialize(&mySize, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } } @@ -60,15 +62,15 @@ class SerialLinkedListAdapter : public SinglyLinkedList, public SerializeIF { static ReturnValue_t serialize(const LinkedElement* element, uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - while ((result == HasReturnvaluesIF::RETURN_OK) and (element != nullptr)) { + ReturnValue_t result = returnvalue::OK; + while ((result == returnvalue::OK) and (element != nullptr)) { result = element->value->serialize(buffer, size, maxSize, streamEndianness); element = element->getNext(); } return result; } - virtual size_t getSerializedSize() const override { + size_t getSerializedSize() const override { if (printCount) { return SerialLinkedListAdapter::getSerializedSize() + sizeof(count_t); } else { @@ -76,6 +78,8 @@ class SerialLinkedListAdapter : public SinglyLinkedList, public SerializeIF { } } + using SerializeIF::deSerialize; // we overloaded this function, so this is needed to unconfuse + // the compiler static size_t getSerializedSize(const LinkedElement* element) { size_t size = 0; while (element != nullptr) { @@ -85,15 +89,15 @@ class SerialLinkedListAdapter : public SinglyLinkedList, public SerializeIF { return size; } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) override { + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override { return deSerialize(SinglyLinkedList::start, buffer, size, streamEndianness); } static ReturnValue_t deSerialize(LinkedElement* element, const uint8_t** buffer, size_t* size, Endianness streamEndianness) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - while ((result == HasReturnvaluesIF::RETURN_OK) and (element != nullptr)) { + ReturnValue_t result = returnvalue::OK; + while ((result == returnvalue::OK) and (element != nullptr)) { result = element->value->deSerialize(buffer, size, streamEndianness); element = element->getNext(); } diff --git a/src/fsfw/serialize/SerializeAdapter.h b/src/fsfw/serialize/SerializeAdapter.h index 5feda889..3c478271 100644 --- a/src/fsfw/serialize/SerializeAdapter.h +++ b/src/fsfw/serialize/SerializeAdapter.h @@ -4,7 +4,7 @@ #include #include -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "EndianConverter.h" #include "SerializeIF.h" @@ -39,8 +39,8 @@ class SerializeAdapter { * SerializeIF::Endianness * @return * - @c BUFFER_TOO_SHORT The given buffer in is too short - * - @c RETURN_FAILED Generic Error - * - @c RETURN_OK Successful serialization + * - @c returnvalue::FAILED Generic Error + * - @c returnvalue::OK Successful serialization */ template static ReturnValue_t serialize(const T *object, uint8_t **buffer, size_t *size, size_t maxSize, @@ -64,17 +64,17 @@ class SerializeAdapter { * SerializeIF::Endianness * @return * - @c BUFFER_TOO_SHORT The given buffer in is too short - * - @c RETURN_FAILED Generic Error - * - @c RETURN_OK Successful serialization + * - @c returnvalue::FAILED Generic Error + * - @c returnvalue::OK Successful serialization */ template static ReturnValue_t serialize(const T *object, uint8_t *const buffer, size_t *serSize, size_t maxSize, SerializeIF::Endianness streamEndianness) { if (object == nullptr or buffer == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } InternalSerializeAdapter::value> adapter; - uint8_t **tempPtr = const_cast(&buffer); + auto **tempPtr = const_cast(&buffer); size_t tmpSize = 0; ReturnValue_t result = adapter.serialize(object, tempPtr, &tmpSize, maxSize, streamEndianness); if (serSize != nullptr) { @@ -113,8 +113,8 @@ class SerializeAdapter { * @return * - @c STREAM_TOO_SHORT The input stream is too short to deSerialize the object * - @c TOO_MANY_ELEMENTS The buffer has more inputs than expected - * - @c RETURN_FAILED Generic Error - * - @c RETURN_OK Successful deserialization + * - @c returnvalue::FAILED Generic Error + * - @c returnvalue::OK Successful deserialization */ template static ReturnValue_t deSerialize(T *object, const uint8_t **buffer, size_t *size, @@ -136,14 +136,14 @@ class SerializeAdapter { * @return * - @c STREAM_TOO_SHORT The input stream is too short to deSerialize the object * - @c TOO_MANY_ELEMENTS The buffer has more inputs than expected - * - @c RETURN_FAILED Generic Error - * - @c RETURN_OK Successful deserialization + * - @c returnvalue::FAILED Generic Error + * - @c returnvalue::OK Successful deserialization */ template static ReturnValue_t deSerialize(T *object, const uint8_t *buffer, size_t *deserSize, SerializeIF::Endianness streamEndianness) { if (object == nullptr or buffer == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } InternalSerializeAdapter::value> adapter; const uint8_t **tempPtr = &buffer; @@ -200,7 +200,7 @@ class SerializeAdapter { std::memcpy(*buffer, &tmp, sizeof(T)); *size += sizeof(T); (*buffer) += sizeof(T); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { return SerializeIF::BUFFER_TOO_SHORT; } @@ -226,13 +226,13 @@ class SerializeAdapter { } *buffer += sizeof(T); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } else { return SerializeIF::STREAM_TOO_SHORT; } } - uint32_t getSerializedSize(const T *object) { return sizeof(T); } + uint32_t getSerializedSize(const T *) { return sizeof(T); } }; /** diff --git a/src/fsfw/serialize/SerializeElement.h b/src/fsfw/serialize/SerializeElement.h index 07f3fea9..01b339f7 100644 --- a/src/fsfw/serialize/SerializeElement.h +++ b/src/fsfw/serialize/SerializeElement.h @@ -32,8 +32,8 @@ class SerializeElement : public SerializeIF, public LinkedElement { size_t getSerializedSize() const override { return SerializeAdapter::getSerializedSize(&entry); } - virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, - Endianness streamEndianness) override { + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override { return SerializeAdapter::deSerialize(&entry, buffer, size, streamEndianness); } diff --git a/src/fsfw/serialize/SerializeIF.h b/src/fsfw/serialize/SerializeIF.h index d806c161..85c29827 100644 --- a/src/fsfw/serialize/SerializeIF.h +++ b/src/fsfw/serialize/SerializeIF.h @@ -3,7 +3,7 @@ #include -#include "../returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" /** * @defgroup serialize Serialization @@ -34,7 +34,7 @@ class SerializeIF { static const ReturnValue_t TOO_MANY_ELEMENTS = MAKE_RETURN_CODE(3); // !< There are too many elements to be deserialized - virtual ~SerializeIF() {} + virtual ~SerializeIF() = default; /** * @brief * Function to serialize the object into a buffer with maxSize. Size represents the written @@ -56,17 +56,24 @@ class SerializeIF { * SerializeIF::Endianness * @return * - @c BUFFER_TOO_SHORT The given buffer in is too short - * - @c RETURN_FAILED Generic error - * - @c RETURN_OK Successful serialization + * - @c returnvalue::FAILED Generic error + * - @c returnvalue::OK Successful serialization */ - virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const = 0; + [[nodiscard]] virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const = 0; + /** + * Forwards to regular @serialize call with big (network) endianness + */ + [[nodiscard]] virtual ReturnValue_t serializeBe(uint8_t **buffer, size_t *size, + size_t maxSize) const { + return serialize(buffer, size, maxSize, SerializeIF::Endianness::NETWORK); + } /** * Gets the size of a object if it would be serialized in a buffer * @return Size of serialized object */ - virtual size_t getSerializedSize() const = 0; + [[nodiscard]] virtual size_t getSerializedSize() const = 0; /** * @brief @@ -85,11 +92,62 @@ class SerializeIF { * @return * - @c STREAM_TOO_SHORT The input stream is too short to deSerialize the object * - @c TOO_MANY_ELEMENTS The buffer has more inputs than expected - * - @c RETURN_FAILED Generic Error - * - @c RETURN_OK Successful deserialization + * - @c returnvalue::FAILED Generic Error + * - @c returnvalue::OK Successful deserialization */ virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, Endianness streamEndianness) = 0; + /** + * Forwards to regular @deSerialize call with big (network) endianness + */ + virtual ReturnValue_t deSerializeBe(const uint8_t **buffer, size_t *size) { + return deSerialize(buffer, size, SerializeIF::Endianness::NETWORK); + } + + /** + * Helper method which can be used if serialization should be performed without any additional + * pointer arithmetic on a passed buffer pointer + * @param buffer + * @param maxSize + * @param streamEndianness + * @return + */ + [[nodiscard]] virtual ReturnValue_t serialize(uint8_t *buffer, size_t &serLen, size_t maxSize, + Endianness streamEndianness) const { + size_t tmpSize = 0; + ReturnValue_t result = serialize(&buffer, &tmpSize, maxSize, streamEndianness); + serLen = tmpSize; + return result; + } + /** + * Forwards to regular @serialize call with big (network) endianness + */ + [[nodiscard]] virtual ReturnValue_t serializeBe(uint8_t *buffer, size_t &serLen, + size_t maxSize) const { + return serialize(buffer, serLen, maxSize, SerializeIF::Endianness::NETWORK); + } + + /** + * Helper methods which can be used if deserialization should be performed without any additional + * pointer arithmetic on a passed buffer pointer + * @param buffer + * @param maxSize + * @param streamEndianness + * @return + */ + virtual ReturnValue_t deSerialize(const uint8_t *buffer, size_t &deserSize, size_t maxSize, + Endianness streamEndianness) { + size_t deserLen = maxSize; + ReturnValue_t result = deSerialize(&buffer, &deserLen, streamEndianness); + deserSize = maxSize - deserLen; + return result; + } + /** + * Forwards to regular @serialize call with big (network) endianness + */ + virtual ReturnValue_t deSerializeBe(const uint8_t *buffer, size_t &deserSize, size_t maxSize) { + return deSerialize(buffer, deserSize, maxSize, SerializeIF::Endianness::NETWORK); + } }; #endif /* FSFW_SERIALIZE_SERIALIZEIF_H_ */ diff --git a/src/fsfw/serviceinterface/CMakeLists.txt b/src/fsfw/serviceinterface/CMakeLists.txt index 84c79177..df3f074e 100644 --- a/src/fsfw/serviceinterface/CMakeLists.txt +++ b/src/fsfw/serviceinterface/CMakeLists.txt @@ -1,5 +1,4 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - ServiceInterfaceStream.cpp - ServiceInterfaceBuffer.cpp - ServiceInterfacePrinter.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE ServiceInterfaceStream.cpp ServiceInterfaceBuffer.cpp + ServiceInterfacePrinter.cpp) diff --git a/src/fsfw/serviceinterface/ServiceInterfaceBuffer.cpp b/src/fsfw/serviceinterface/ServiceInterfaceBuffer.cpp index dd928efe..0e73be83 100644 --- a/src/fsfw/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/src/fsfw/serviceinterface/ServiceInterfaceBuffer.cpp @@ -1,9 +1,8 @@ -#include "fsfw/serviceinterface/ServiceInterfaceBuffer.h" +#include "ServiceInterfaceBuffer.h" #if FSFW_CPP_OSTREAM_ENABLED == 1 -#include - +#include #include #include "fsfw/serviceinterface/serviceInterfaceDefintions.h" @@ -16,8 +15,6 @@ // to be implemented by bsp extern "C" void printChar(const char*, bool errStream); -#ifndef UT699 - ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, bool addCrToPreamble, bool buffered, bool errStream, uint16_t port) : isActive(true), @@ -58,6 +55,9 @@ ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, bool addC } void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { + if (not isActive) { + return; + } char array[BUF_SIZE]; uint32_t length = end - begin; if (length > sizeof(array)) { @@ -74,8 +74,6 @@ void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { } } -#endif - int ServiceInterfaceBuffer::overflow(int c) { if (not buffered and this->isActive) { if (c != Traits::eof()) { @@ -169,89 +167,4 @@ void ServiceInterfaceBuffer::setAsciiColorPrefix(std::string colorPrefix) { } #endif -#ifdef UT699 -#include "../osal/rtems/Interrupt.h" - -ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) { - this->log_message = set_message; - this->isActive = true; - setp(buf, buf + BUF_SIZE); -} - -void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { - char array[BUF_SIZE]; - uint32_t length = end - begin; - if (length > sizeof(array)) { - length = sizeof(array); - } - memcpy(array, begin, length); - - if (!Interrupt::isInterruptInProgress()) { - std::cout << array; - } else { - // Uncomment the following line if you need ISR debug output. - // printk(array); - } -} -#endif // UT699 - -#ifdef ML505 -#include -ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) - : isActive(true), - log_message(set_message), - udpSocket(0), - remoteAddressLength(sizeof(remoteAddress)) { - setp(buf, buf + BUF_SIZE); - memset((uint8_t*)&remoteAddress, 0, sizeof(remoteAddress)); - remoteAddress.sin_family = AF_INET; - remoteAddress.sin_port = htons(port); - remoteAddress.sin_addr.s_addr = htonl(inet_addr("192.168.250.100")); -} - -void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { - char array[BUF_SIZE]; - uint32_t length = end - begin; - if (length > sizeof(array)) { - length = sizeof(array); - } - memcpy(array, begin, length); - - if (udpSocket <= 0) { - initSocket(); - } - - if (udpSocket > 0) { - sendto(udpSocket, array, length, 0, (sockaddr*)&remoteAddress, sizeof(remoteAddress)); - } -} - -void ServiceInterfaceBuffer::initSocket() { - sockaddr_in address; - memset((uint8_t*)&address, 0, sizeof(address)); - address.sin_family = AF_INET; - address.sin_port = htons(0); - address.sin_addr.s_addr = htonl(INADDR_ANY); - - udpSocket = socket(PF_INET, SOCK_DGRAM, 0); - if (socket < 0) { - printf("Error opening socket!\n"); - return; - } - timeval timeout = {0, 20}; - if (setsockopt(udpSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) { - printf("Error setting SO_RCVTIMEO socket options!\n"); - return; - } - if (setsockopt(udpSocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) { - printf("Error setting SO_SNDTIMEO socket options!\n"); - return; - } - if (bind(udpSocket, (sockaddr*)&address, sizeof(address)) < 0) { - printf("Error binding socket!\n"); - } -} - -#endif // ML505 - -#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ +#endif diff --git a/src/fsfw/serviceinterface/ServiceInterfaceBuffer.h b/src/fsfw/serviceinterface/ServiceInterfaceBuffer.h index 9cda75c6..682332c9 100644 --- a/src/fsfw/serviceinterface/ServiceInterfaceBuffer.h +++ b/src/fsfw/serviceinterface/ServiceInterfaceBuffer.h @@ -1,9 +1,8 @@ #ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ #define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ -#include - -#include "../returnvalues/HasReturnvaluesIF.h" +#include "fsfw/FSFW.h" +#include "fsfw/returnvalues/returnvalue.h" #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -11,8 +10,6 @@ #include #include -#ifndef UT699 - /** * @brief This is the underlying stream buffer which implements the * streambuf class and overloads the overflow() and sync() methods @@ -77,85 +74,6 @@ class ServiceInterfaceBuffer : public std::streambuf { bool crAdditionEnabled() const; }; -#endif - -#ifdef UT699 -class ServiceInterfaceBuffer : public std::basic_streambuf > { - friend class ServiceInterfaceStream; - - public: - ServiceInterfaceBuffer(std::string set_message, uint16_t port); - - protected: - bool isActive; - // This is called when buffer becomes full. If - // buffer is not used, then this is called every - // time when characters are put to stream. - virtual int overflow(int c = Traits::eof()); - - // This function is called when stream is flushed, - // for example when std::endl is put to stream. - virtual int sync(void); - - private: - // For additional message information - std::string log_message; - // For EOF detection - typedef std::char_traits Traits; - - // Work in buffer mode. It is also possible to work without buffer. - static size_t const BUF_SIZE = 128; - char buf[BUF_SIZE]; - - // In this function, the characters are parsed. - void putChars(char const* begin, char const* end); -}; -#endif // UT699 - -#ifdef ML505 -#include -#include -#include -#include -#include - -class ServiceInterfaceBuffer : public std::basic_streambuf > { - friend class ServiceInterfaceStream; - - public: - ServiceInterfaceBuffer(std::string set_message, uint16_t port); - - protected: - bool isActive; - // This is called when buffer becomes full. If - // buffer is not used, then this is called every - // time when characters are put to stream. - virtual int overflow(int c = Traits::eof()); - - // This function is called when stream is flushed, - // for example when std::endl is put to stream. - virtual int sync(void); - - private: - // For additional message information - std::string log_message; - // For EOF detection - typedef std::char_traits Traits; - - // Work in buffer mode. It is also possible to work without buffer. - static size_t const BUF_SIZE = 128; - char buf[BUF_SIZE]; - - // In this function, the characters are parsed. - void putChars(char const* begin, char const* end); - - int udpSocket; - sockaddr_in remoteAddress; - socklen_t remoteAddressLength; - void initSocket(); -}; -#endif // ML505 - #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ */ diff --git a/src/fsfw/serviceinterface/ServiceInterfaceStream.h b/src/fsfw/serviceinterface/ServiceInterfaceStream.h index 0b3d6745..ca746e7d 100644 --- a/src/fsfw/serviceinterface/ServiceInterfaceStream.h +++ b/src/fsfw/serviceinterface/ServiceInterfaceStream.h @@ -1,9 +1,8 @@ #ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ #define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ -#include - #include "ServiceInterfaceBuffer.h" +#include "fsfw/FSFW.h" #if FSFW_CPP_OSTREAM_ENABLED == 1 diff --git a/src/fsfw/storagemanager/CMakeLists.txt b/src/fsfw/storagemanager/CMakeLists.txt index b8138cae..50ce50ed 100644 --- a/src/fsfw/storagemanager/CMakeLists.txt +++ b/src/fsfw/storagemanager/CMakeLists.txt @@ -1,7 +1,3 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - ConstStorageAccessor.cpp - StorageAccessor.cpp - LocalPool.cpp - PoolManager.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} PRIVATE ConstStorageAccessor.cpp StorageAccessor.cpp + LocalPool.cpp PoolManager.cpp) diff --git a/src/fsfw/storagemanager/ConstStorageAccessor.cpp b/src/fsfw/storagemanager/ConstStorageAccessor.cpp index df2fc750..e39fa36b 100644 --- a/src/fsfw/storagemanager/ConstStorageAccessor.cpp +++ b/src/fsfw/storagemanager/ConstStorageAccessor.cpp @@ -19,7 +19,7 @@ ConstStorageAccessor::~ConstStorageAccessor() { } } -ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other) +ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other) noexcept : constDataPointer(other.constDataPointer), storeId(other.storeId), size_(other.size_), @@ -30,7 +30,7 @@ ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other) other.store = nullptr; } -ConstStorageAccessor& ConstStorageAccessor::operator=(ConstStorageAccessor&& other) { +ConstStorageAccessor& ConstStorageAccessor::operator=(ConstStorageAccessor&& other) noexcept { constDataPointer = other.constDataPointer; storeId = other.storeId; store = other.store; @@ -58,16 +58,16 @@ ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t* pointer, size_t maxSize #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "StorageAccessor: Not initialized!" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (size_ > maxSize) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } std::copy(constDataPointer, constDataPointer + size_, pointer); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void ConstStorageAccessor::release() { deleteData = false; } @@ -84,7 +84,7 @@ void ConstStorageAccessor::print() const { arrayprinter::print(constDataPointer, size_); } -void ConstStorageAccessor::assignStore(StorageManagerIF* store) { +void ConstStorageAccessor::assignStore(StorageManagerIF* store_) { internalState = AccessState::ASSIGNED; - this->store = store; + store = store_; } diff --git a/src/fsfw/storagemanager/ConstStorageAccessor.h b/src/fsfw/storagemanager/ConstStorageAccessor.h index a2ddad6c..0911c6d9 100644 --- a/src/fsfw/storagemanager/ConstStorageAccessor.h +++ b/src/fsfw/storagemanager/ConstStorageAccessor.h @@ -3,7 +3,7 @@ #include -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "storeAddress.h" class StorageManagerIF; @@ -23,6 +23,7 @@ class ConstStorageAccessor { //! StorageManager classes have exclusive access to private variables. friend class PoolManager; friend class LocalPool; + friend class StorageManagerIF; public: /** @@ -30,7 +31,7 @@ class ConstStorageAccessor { * entry to access. * @param storeId */ - ConstStorageAccessor(store_address_t storeId); + explicit ConstStorageAccessor(store_address_t storeId); ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); /** @@ -43,7 +44,7 @@ class ConstStorageAccessor { * @brief Returns a pointer to the read-only data * @return */ - const uint8_t* data() const; + [[nodiscard]] const uint8_t* data() const; /** * @brief Copies the read-only data to the supplied pointer @@ -61,13 +62,13 @@ class ConstStorageAccessor { * Get the size of the data * @return */ - size_t size() const; + [[nodiscard]] size_t size() const; /** * Get the storage ID. * @return */ - store_address_t getId() const; + [[nodiscard]] store_address_t getId() const; void print() const; @@ -79,8 +80,8 @@ class ConstStorageAccessor { * @param * @return */ - ConstStorageAccessor& operator=(ConstStorageAccessor&&); - ConstStorageAccessor(ConstStorageAccessor&&); + ConstStorageAccessor& operator=(ConstStorageAccessor&&) noexcept; + ConstStorageAccessor(ConstStorageAccessor&&) noexcept; //! The copy ctor and copy assignemnt should be deleted implicitely //! according to https://foonathan.net/2019/02/special-member-functions/ diff --git a/src/fsfw/storagemanager/LocalPool.cpp b/src/fsfw/storagemanager/LocalPool.cpp index cee1d407..b62c19b6 100644 --- a/src/fsfw/storagemanager/LocalPool.cpp +++ b/src/fsfw/storagemanager/LocalPool.cpp @@ -29,12 +29,11 @@ LocalPool::LocalPool(object_id_t setObjectId, const LocalPoolConfig& poolConfig, } } -LocalPool::~LocalPool(void) {} +LocalPool::~LocalPool() = default; -ReturnValue_t LocalPool::addData(store_address_t* storageId, const uint8_t* data, size_t size, - bool ignoreFault) { - ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); - if (status == RETURN_OK) { +ReturnValue_t LocalPool::addData(store_address_t* storageId, const uint8_t* data, size_t size) { + ReturnValue_t status = reserveSpace(size, storageId); + if (status == returnvalue::OK) { write(*storageId, data, size); } return status; @@ -48,26 +47,10 @@ ReturnValue_t LocalPool::getData(store_address_t packetId, const uint8_t** packe return status; } -ReturnValue_t LocalPool::getData(store_address_t storeId, ConstStorageAccessor& storeAccessor) { - uint8_t* tempData = nullptr; - ReturnValue_t status = modifyData(storeId, &tempData, &storeAccessor.size_); - storeAccessor.assignStore(this); - storeAccessor.constDataPointer = tempData; - return status; -} - -ConstAccessorPair LocalPool::getData(store_address_t storeId) { - uint8_t* tempData = nullptr; - ConstStorageAccessor constAccessor(storeId, this); - ReturnValue_t status = modifyData(storeId, &tempData, &constAccessor.size_); - constAccessor.constDataPointer = tempData; - return ConstAccessorPair(status, std::move(constAccessor)); -} - ReturnValue_t LocalPool::getFreeElement(store_address_t* storageId, const size_t size, - uint8_t** pData, bool ignoreFault) { - ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); - if (status == RETURN_OK) { + uint8_t** pData) { + ReturnValue_t status = reserveSpace(size, storageId); + if (status == returnvalue::OK) { *pData = &store[storageId->poolIndex][getRawPosition(*storageId)]; } else { *pData = nullptr; @@ -75,22 +58,8 @@ ReturnValue_t LocalPool::getFreeElement(store_address_t* storageId, const size_t return status; } -AccessorPair LocalPool::modifyData(store_address_t storeId) { - StorageAccessor accessor(storeId, this); - ReturnValue_t status = modifyData(storeId, &accessor.dataPointer, &accessor.size_); - accessor.assignConstPointer(); - return AccessorPair(status, std::move(accessor)); -} - -ReturnValue_t LocalPool::modifyData(store_address_t storeId, StorageAccessor& storeAccessor) { - storeAccessor.assignStore(this); - ReturnValue_t status = modifyData(storeId, &storeAccessor.dataPointer, &storeAccessor.size_); - storeAccessor.assignConstPointer(); - return status; -} - ReturnValue_t LocalPool::modifyData(store_address_t storeId, uint8_t** packetPtr, size_t* size) { - ReturnValue_t status = RETURN_FAILED; + ReturnValue_t status = returnvalue::FAILED; if (storeId.poolIndex >= NUMBER_OF_SUBPOOLS) { return ILLEGAL_STORAGE_ID; } @@ -102,7 +71,7 @@ ReturnValue_t LocalPool::modifyData(store_address_t storeId, uint8_t** packetPtr size_type packetPosition = getRawPosition(storeId); *packetPtr = &store[storeId.poolIndex][packetPosition]; *size = sizeLists[storeId.poolIndex][storeId.packetIndex]; - status = RETURN_OK; + status = returnvalue::OK; } else { status = DATA_DOES_NOT_EXIST; } @@ -117,7 +86,7 @@ ReturnValue_t LocalPool::deleteData(store_address_t storeId) { #endif #endif - ReturnValue_t status = RETURN_OK; + ReturnValue_t status = returnvalue::OK; size_type pageSize = getSubpoolElementSize(storeId.poolIndex); if ((pageSize != 0) and (storeId.packetIndex < numberOfElements[storeId.poolIndex])) { uint16_t packetPosition = getRawPosition(storeId); @@ -166,7 +135,7 @@ ReturnValue_t LocalPool::deleteData(uint8_t* ptr, size_t size, store_address_t* ReturnValue_t LocalPool::initialize() { ReturnValue_t result = SystemObject::initialize(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } internalErrorReporter = @@ -186,7 +155,7 @@ ReturnValue_t LocalPool::initialize() { return StorageManagerIF::POOL_TOO_LARGE; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void LocalPool::clearStore() { @@ -194,15 +163,12 @@ void LocalPool::clearStore() { for (auto& size : sizeList) { size = STORAGE_FREE; } - // std::memset(sizeList[index], 0xff, - // numberOfElements[index] * sizeof(size_type)); } } -ReturnValue_t LocalPool::reserveSpace(const size_t size, store_address_t* storeId, - bool ignoreFault) { +ReturnValue_t LocalPool::reserveSpace(size_t size, store_address_t* storeId) { ReturnValue_t status = getSubPoolIndex(size, &storeId->poolIndex); - if (status != RETURN_OK) { + if (status != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "LocalPool( " << std::hex << getObjectId() << std::dec << " )::reserveSpace: Packet too large." << std::endl; @@ -210,15 +176,15 @@ ReturnValue_t LocalPool::reserveSpace(const size_t size, store_address_t* storeI return status; } status = findEmpty(storeId->poolIndex, &storeId->packetIndex); - while (status != RETURN_OK && spillsToHigherPools) { + while (status != returnvalue::OK && spillsToHigherPools) { status = getSubPoolIndex(size, &storeId->poolIndex, storeId->poolIndex + 1); - if (status != RETURN_OK) { + if (status != returnvalue::OK) { // We don't find any fitting pool anymore. break; } status = findEmpty(storeId->poolIndex, &storeId->packetIndex); } - if (status == RETURN_OK) { + if (status == returnvalue::OK) { #if FSFW_VERBOSE_LEVEL >= 2 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::debug << "Reserve: Pool: " << std::dec << storeId->poolIndex @@ -265,7 +231,7 @@ ReturnValue_t LocalPool::getSubPoolIndex(size_t packetSize, uint16_t* subpoolInd #endif if (elementSizes[n] >= packetSize) { *subpoolIndex = n; - return RETURN_OK; + return returnvalue::OK; } } return DATA_TOO_LARGE; @@ -280,7 +246,7 @@ ReturnValue_t LocalPool::findEmpty(n_pool_elem_t poolIndex, uint16_t* element) { for (uint16_t foundElement = 0; foundElement < numberOfElements[poolIndex]; foundElement++) { if (sizeLists[poolIndex][foundElement] == STORAGE_FREE) { *element = foundElement; - status = RETURN_OK; + status = returnvalue::OK; break; } } @@ -338,3 +304,16 @@ void LocalPool::clearSubPool(max_subpools_t subpoolIndex) { } LocalPool::max_subpools_t LocalPool::getNumberOfSubPools() const { return NUMBER_OF_SUBPOOLS; } + +bool LocalPool::hasDataAtId(store_address_t storeId) const { + if (storeId.poolIndex >= NUMBER_OF_SUBPOOLS) { + return false; + } + if ((storeId.packetIndex >= numberOfElements[storeId.poolIndex])) { + return false; + } + if (sizeLists[storeId.poolIndex][storeId.packetIndex] != STORAGE_FREE) { + return true; + } + return false; +} diff --git a/src/fsfw/storagemanager/LocalPool.h b/src/fsfw/storagemanager/LocalPool.h index 01706e9c..f82acd54 100644 --- a/src/fsfw/storagemanager/LocalPool.h +++ b/src/fsfw/storagemanager/LocalPool.h @@ -81,27 +81,21 @@ class LocalPool : public SystemObject, public StorageManagerIF { /** * @brief In the LocalPool's destructor all allocated memory is freed. */ - virtual ~LocalPool(void); + ~LocalPool() override; /** * Documentation: See StorageManagerIF.h */ - ReturnValue_t addData(store_address_t* storeId, const uint8_t* data, size_t size, - bool ignoreFault = false) override; - ReturnValue_t getFreeElement(store_address_t* storeId, const size_t size, uint8_t** pData, - bool ignoreFault = false) override; + ReturnValue_t addData(store_address_t* storeId, const uint8_t* data, size_t size) override; + + ReturnValue_t getFreeElement(store_address_t* storeId, size_t size, uint8_t** pData) override; - ConstAccessorPair getData(store_address_t storeId) override; - ReturnValue_t getData(store_address_t storeId, ConstStorageAccessor& constAccessor) override; ReturnValue_t getData(store_address_t storeId, const uint8_t** packet_ptr, size_t* size) override; - AccessorPair modifyData(store_address_t storeId) override; - ReturnValue_t modifyData(store_address_t storeId, StorageAccessor& storeAccessor) override; ReturnValue_t modifyData(store_address_t storeId, uint8_t** packet_ptr, size_t* size) override; - virtual ReturnValue_t deleteData(store_address_t storeId) override; - virtual ReturnValue_t deleteData(uint8_t* ptr, size_t size, - store_address_t* storeId = nullptr) override; + ReturnValue_t deleteData(store_address_t storeId) override; + ReturnValue_t deleteData(uint8_t* ptr, size_t size, store_address_t* storeId) override; /** * Get the total size of allocated memory for pool data. @@ -131,17 +125,24 @@ class LocalPool : public SystemObject, public StorageManagerIF { * Get number sub pools. Each pool has pages with a specific bucket size. * @return */ - max_subpools_t getNumberOfSubPools() const override; + [[nodiscard]] max_subpools_t getNumberOfSubPools() const override; + [[nodiscard]] bool hasDataAtId(store_address_t storeId) const override; + + // Using functions provided by StorageManagerIF requires either a fully qualified path + // like for example localPool.StorageManagerIF::getFreeElement(...) or re-exporting + // the fully qualified path with the using directive. + using StorageManagerIF::getData; + using StorageManagerIF::modifyData; protected: /** * With this helper method, a free element of @c size is reserved. * @param size The minimum packet size that shall be reserved. * @param[out] address Storage ID of the reserved data. - * @return - #RETURN_OK on success, + * @return - returnvalue::OK on success, * - the return codes of #getPoolIndex or #findEmpty otherwise. */ - virtual ReturnValue_t reserveSpace(const size_t size, store_address_t* address, bool ignoreFault); + virtual ReturnValue_t reserveSpace(size_t size, store_address_t* address); private: /** @@ -185,6 +186,8 @@ class LocalPool : public SystemObject, public StorageManagerIF { std::vector> sizeLists = std::vector>(NUMBER_OF_SUBPOOLS); + bool ignoreFault = false; + //! A variable to determine whether higher n pools are used if //! the store is full. bool spillsToHigherPools = false; @@ -210,7 +213,7 @@ class LocalPool : public SystemObject, public StorageManagerIF { * fits is used. * @param packet_size The size of the data to be stored. * @param[out] poolIndex The fitting pool index found. - * @return - @c RETURN_OK on success, + * @return - @c returnvalue::OK on success, * - @c DATA_TOO_LARGE otherwise. */ ReturnValue_t getSubPoolIndex(size_t packetSize, uint16_t* subpoolIndex, @@ -230,7 +233,7 @@ class LocalPool : public SystemObject, public StorageManagerIF { * duration grows with the fill level of the pool. * @param pool_index The pool in which the search is performed. * @param[out] element The first found element in the pool. - * @return - #RETURN_OK on success, + * @return - returnvalue::OK on success, * - #DATA_STORAGE_FULL if the store is full */ ReturnValue_t findEmpty(n_pool_elem_t poolIndex, uint16_t* element); diff --git a/src/fsfw/storagemanager/PoolManager.cpp b/src/fsfw/storagemanager/PoolManager.cpp index 92de1dfe..840a7dcc 100644 --- a/src/fsfw/storagemanager/PoolManager.cpp +++ b/src/fsfw/storagemanager/PoolManager.cpp @@ -7,17 +7,16 @@ PoolManager::PoolManager(object_id_t setObjectId, const LocalPoolConfig& localPo mutex = MutexFactory::instance()->createMutex(); } -PoolManager::~PoolManager(void) { MutexFactory::instance()->deleteMutex(mutex); } +PoolManager::~PoolManager() { MutexFactory::instance()->deleteMutex(mutex); } -ReturnValue_t PoolManager::reserveSpace(const size_t size, store_address_t* address, - bool ignoreFault) { +ReturnValue_t PoolManager::reserveSpace(const size_t size, store_address_t* address) { MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs); - ReturnValue_t status = LocalPool::reserveSpace(size, address, ignoreFault); + ReturnValue_t status = LocalPool::reserveSpace(size, address); return status; } ReturnValue_t PoolManager::deleteData(store_address_t storeId) { -#if FSFW_VERBOSE_LEVEL >= 2 +#if FSFW_VERBOSE_LEVEL >= 2 && FSFW_OBJ_EVENT_TRANSLATION == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::debug << "PoolManager( " << translateObject(getObjectId()) << " )::deleteData from store " << storeId.poolIndex << ". id is " << storeId.packetIndex << std::endl; diff --git a/src/fsfw/storagemanager/PoolManager.h b/src/fsfw/storagemanager/PoolManager.h index 0951a518..aa8c93dd 100644 --- a/src/fsfw/storagemanager/PoolManager.h +++ b/src/fsfw/storagemanager/PoolManager.h @@ -27,7 +27,7 @@ class PoolManager : public LocalPool { * @brief In the PoolManager's destructor all allocated memory * is freed. */ - virtual ~PoolManager(); + ~PoolManager() override; /** * Set the default mutex timeout for internal calls. @@ -40,8 +40,7 @@ class PoolManager : public LocalPool { * which wraps LocalPool calls with a mutex protection. */ ReturnValue_t deleteData(store_address_t) override; - ReturnValue_t deleteData(uint8_t* buffer, size_t size, - store_address_t* storeId = nullptr) override; + ReturnValue_t deleteData(uint8_t* buffer, size_t size, store_address_t* storeId) override; /** * The developer is allowed to lock the mutex in case the lock needs @@ -58,8 +57,7 @@ class PoolManager : public LocalPool { //! Default mutex timeout value to prevent permanent blocking. uint32_t mutexTimeoutMs = 20; - ReturnValue_t reserveSpace(const size_t size, store_address_t* address, - bool ignoreFault) override; + ReturnValue_t reserveSpace(size_t size, store_address_t* address) override; /** * @brief The mutex is created in the constructor and makes diff --git a/src/fsfw/storagemanager/StorageAccessor.cpp b/src/fsfw/storagemanager/StorageAccessor.cpp index e2b083b2..b576a113 100644 --- a/src/fsfw/storagemanager/StorageAccessor.cpp +++ b/src/fsfw/storagemanager/StorageAccessor.cpp @@ -10,15 +10,15 @@ StorageAccessor::StorageAccessor(store_address_t storeId) : ConstStorageAccessor StorageAccessor::StorageAccessor(store_address_t storeId, StorageManagerIF* store) : ConstStorageAccessor(storeId, store) {} -StorageAccessor& StorageAccessor::operator=(StorageAccessor&& other) { +StorageAccessor& StorageAccessor::operator=(StorageAccessor&& other) noexcept { // Call the parent move assignment and also assign own member. dataPointer = other.dataPointer; - StorageAccessor::operator=(std::move(other)); + ConstStorageAccessor::operator=(std::move(other)); return *this; } // Call the parent move ctor and also transfer own member. -StorageAccessor::StorageAccessor(StorageAccessor&& other) +StorageAccessor::StorageAccessor(StorageAccessor&& other) noexcept : ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) {} ReturnValue_t StorageAccessor::getDataCopy(uint8_t* pointer, size_t maxSize) { @@ -26,7 +26,7 @@ ReturnValue_t StorageAccessor::getDataCopy(uint8_t* pointer, size_t maxSize) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "StorageAccessor: Not initialized!" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (size_ > maxSize) { #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -34,10 +34,10 @@ ReturnValue_t StorageAccessor::getDataCopy(uint8_t* pointer, size_t maxSize) { "enough" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } std::copy(dataPointer, dataPointer + size_, pointer); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } uint8_t* StorageAccessor::data() { @@ -54,7 +54,7 @@ ReturnValue_t StorageAccessor::write(uint8_t* data, size_t size, uint16_t offset #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "StorageAccessor: Not initialized!" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (offset + size > size_) { #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -62,10 +62,10 @@ ReturnValue_t StorageAccessor::write(uint8_t* data, size_t size, uint16_t offset "entry!" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } std::copy(data, data + size, dataPointer + offset); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void StorageAccessor::assignConstPointer() { constDataPointer = dataPointer; } diff --git a/src/fsfw/storagemanager/StorageAccessor.h b/src/fsfw/storagemanager/StorageAccessor.h index 5e8b25e4..b6c5dc14 100644 --- a/src/fsfw/storagemanager/StorageAccessor.h +++ b/src/fsfw/storagemanager/StorageAccessor.h @@ -12,9 +12,10 @@ class StorageAccessor : public ConstStorageAccessor { //! StorageManager classes have exclusive access to private variables. friend class PoolManager; friend class LocalPool; + friend class StorageManagerIF; public: - StorageAccessor(store_address_t storeId); + explicit StorageAccessor(store_address_t storeId); StorageAccessor(store_address_t storeId, StorageManagerIF* store); /** @@ -25,8 +26,8 @@ class StorageAccessor : public ConstStorageAccessor { * @param * @return */ - StorageAccessor& operator=(StorageAccessor&&); - StorageAccessor(StorageAccessor&&); + StorageAccessor& operator=(StorageAccessor&&) noexcept; + StorageAccessor(StorageAccessor&&) noexcept; ReturnValue_t write(uint8_t* data, size_t size, uint16_t offset = 0); uint8_t* data(); diff --git a/src/fsfw/storagemanager/StorageManagerIF.h b/src/fsfw/storagemanager/StorageManagerIF.h index 375fc7cc..e48e19db 100644 --- a/src/fsfw/storagemanager/StorageManagerIF.h +++ b/src/fsfw/storagemanager/StorageManagerIF.h @@ -5,7 +5,7 @@ #include #include "../events/Event.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "StorageAccessor.h" #include "storeAddress.h" @@ -25,7 +25,7 @@ using ConstAccessorPair = std::pair; * @author Bastian Baetz * @date 18.09.2012 */ -class StorageManagerIF : public HasReturnvaluesIF { +class StorageManagerIF { public: using size_type = size_t; using max_subpools_t = uint8_t; @@ -55,7 +55,7 @@ class StorageManagerIF : public HasReturnvaluesIF { /** * @brief This is the empty virtual destructor as required for C++ interfaces. */ - virtual ~StorageManagerIF(){}; + virtual ~StorageManagerIF() = default; /** * @brief With addData, a free storage position is allocated and data * stored there. @@ -63,18 +63,17 @@ class StorageManagerIF : public HasReturnvaluesIF { * @param storageId A pointer to the storageId to retrieve. * @param data The data to be stored in the StorageManager. * @param size The amount of data to be stored. - * @return Returns @li RETURN_OK if data was added. - * @li RETURN_FAILED if data could not be added. - * storageId is unchanged then. + * @return Returns @returnvalue::OK if data was added. + * @returnvalue::FAILED if data could not be added, storageId is unchanged then. */ - virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t* data, size_t size, - bool ignoreFault = false) = 0; + virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t* data, size_t size) = 0; + /** * @brief With deleteData, the storageManager frees the memory region * identified by packet_id. * @param packet_id The identifier of the memory region to be freed. - * @return @li RETURN_OK on success. - * @li RETURN_FAILED if deletion did not work + * @return @li returnvalue::OK on success. + * @li returnvalue::FAILED if deletion did not work * (e.g. an illegal packet_id was passed). */ virtual ReturnValue_t deleteData(store_address_t packet_id) = 0; @@ -84,12 +83,13 @@ class StorageManagerIF : public HasReturnvaluesIF { * @param buffer Pointer to the data. * @param size Size of data to be stored. * @param storeId Store id of the deleted element (optional) - * @return @li RETURN_OK on success. + * @return @li returnvalue::OK on success. * @li failure code if deletion did not work */ - virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size, - store_address_t* storeId = nullptr) = 0; - + virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size, store_address_t* storeId) = 0; + virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size) { + return deleteData(buffer, size, nullptr); + } /** * @brief Access the data by supplying a store ID. * @details @@ -98,7 +98,13 @@ class StorageManagerIF : public HasReturnvaluesIF { * @param storeId * @return Pair of return value and a ConstStorageAccessor instance */ - virtual ConstAccessorPair getData(store_address_t storeId) = 0; + virtual ConstAccessorPair getData(store_address_t storeId) { + uint8_t* tempData = nullptr; + ConstStorageAccessor constAccessor(storeId, this); + ReturnValue_t status = modifyData(storeId, &tempData, &constAccessor.size_); + constAccessor.constDataPointer = tempData; + return {status, std::move(constAccessor)}; + } /** * @brief Access the data by supplying a store ID and a helper @@ -107,7 +113,13 @@ class StorageManagerIF : public HasReturnvaluesIF { * @param constAccessor Wrapper function to access store data. * @return */ - virtual ReturnValue_t getData(store_address_t storeId, ConstStorageAccessor& constAccessor) = 0; + virtual ReturnValue_t getData(store_address_t storeId, ConstStorageAccessor& accessor) { + uint8_t* tempData = nullptr; + ReturnValue_t status = modifyData(storeId, &tempData, &accessor.size_); + accessor.assignStore(this); + accessor.constDataPointer = tempData; + return status; + } /** * @brief getData returns an address to data and the size of the data @@ -116,8 +128,8 @@ class StorageManagerIF : public HasReturnvaluesIF { * @param packet_ptr The passed pointer address is set to the the memory * position * @param size The exact size of the stored data is returned here. - * @return @li RETURN_OK on success. - * @li RETURN_FAILED if fetching data did not work + * @return @returnvalue::OK on success. + * @returnvalue::FAILED if fetching data did not work * (e.g. an illegal packet_id was passed). */ virtual ReturnValue_t getData(store_address_t packet_id, const uint8_t** packet_ptr, @@ -128,7 +140,12 @@ class StorageManagerIF : public HasReturnvaluesIF { * @param storeId * @return Pair of return value and StorageAccessor helper */ - virtual AccessorPair modifyData(store_address_t storeId) = 0; + virtual AccessorPair modifyData(store_address_t storeId) { + StorageAccessor accessor(storeId, this); + ReturnValue_t status = modifyData(storeId, &accessor.dataPointer, &accessor.size_); + accessor.assignConstPointer(); + return {status, std::move(accessor)}; + } /** * Modify data by supplying a store ID and a StorageAccessor helper instance. @@ -136,7 +153,12 @@ class StorageManagerIF : public HasReturnvaluesIF { * @param accessor Helper class to access the modifiable data. * @return */ - virtual ReturnValue_t modifyData(store_address_t storeId, StorageAccessor& accessor) = 0; + virtual ReturnValue_t modifyData(store_address_t storeId, StorageAccessor& accessor) { + accessor.assignStore(this); + ReturnValue_t status = modifyData(storeId, &accessor.dataPointer, &accessor.size_); + accessor.assignConstPointer(); + return status; + } /** * Get pointer and size of modifiable data by supplying the storeId @@ -155,13 +177,14 @@ class StorageManagerIF : public HasReturnvaluesIF { * written to p_data! * @param storageId A pointer to the storageId to retrieve. * @param size The size of the space to be reserved. - * @param p_data A pointer to the element data is returned here. - * @return Returns @li RETURN_OK if data was added. - * @li RETURN_FAILED if data could not be added. - * storageId is unchanged then. + * @param dataPtr A pointer to the element data is returned here. + * @return Returns @returnvalue::OK if data was added. + * @returnvalue::FAILED if data could not be added, storageId is unchanged then. */ - virtual ReturnValue_t getFreeElement(store_address_t* storageId, const size_t size, - uint8_t** p_data, bool ignoreFault = false) = 0; + virtual ReturnValue_t getFreeElement(store_address_t* storageId, size_t size, + uint8_t** dataPtr) = 0; + + [[nodiscard]] virtual bool hasDataAtId(store_address_t storeId) const = 0; /** * Clears the whole store. @@ -192,7 +215,7 @@ class StorageManagerIF : public HasReturnvaluesIF { * Get number of pools. * @return */ - virtual max_subpools_t getNumberOfSubPools() const = 0; + [[nodiscard]] virtual max_subpools_t getNumberOfSubPools() const = 0; }; #endif /* FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_ */ diff --git a/src/fsfw/storagemanager/storeAddress.h b/src/fsfw/storagemanager/storeAddress.h index 41f70573..a656cfe1 100644 --- a/src/fsfw/storagemanager/storeAddress.h +++ b/src/fsfw/storagemanager/storeAddress.h @@ -3,26 +3,26 @@ #include -namespace storeId { -static constexpr uint32_t INVALID_STORE_ADDRESS = 0xffffffff; -} - /** * This union defines the type that identifies where a data packet is * stored in the store. It comprises of a raw part to read it as raw value and * a structured part to use it in pool-like stores. */ union store_address_t { + public: + static constexpr uint32_t INVALID_RAW = 0xffffffff; /** * Default Constructor, initializing to INVALID_ADDRESS */ - store_address_t() : raw(storeId::INVALID_STORE_ADDRESS) {} + store_address_t() : raw(INVALID_RAW) {} /** * Constructor to create an address object using the raw address * * @param rawAddress */ - store_address_t(uint32_t rawAddress) : raw(rawAddress) {} + explicit store_address_t(uint32_t rawAddress) : raw(rawAddress) {} + + static store_address_t invalid() { return {}; }; /** * Constructor to create an address object using pool @@ -52,6 +52,12 @@ union store_address_t { uint32_t raw; bool operator==(const store_address_t& other) const { return raw == other.raw; } + bool operator!=(const store_address_t& other) const { return raw != other.raw; } + + store_address_t& operator=(const uint32_t rawAddr) { + raw = rawAddr; + return *this; + } }; #endif /* FSFW_STORAGEMANAGER_STOREADDRESS_H_ */ diff --git a/src/fsfw/subsystem/CMakeLists.txt b/src/fsfw/subsystem/CMakeLists.txt index 5c98ee70..164c90f7 100644 --- a/src/fsfw/subsystem/CMakeLists.txt +++ b/src/fsfw/subsystem/CMakeLists.txt @@ -1,7 +1,3 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - Subsystem.cpp - SubsystemBase.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE Subsystem.cpp SubsystemBase.cpp) -add_subdirectory(modes) \ No newline at end of file +add_subdirectory(modes) diff --git a/src/fsfw/subsystem/Subsystem.cpp b/src/fsfw/subsystem/Subsystem.cpp index a837bf83..b2af5ac3 100644 --- a/src/fsfw/subsystem/Subsystem.cpp +++ b/src/fsfw/subsystem/Subsystem.cpp @@ -30,21 +30,21 @@ ReturnValue_t Subsystem::checkSequence(HybridIterator iter, return FALLBACK_SEQUENCE_DOES_NOT_EXIST; } - if (iter.value == NULL) { + if (iter.value == nullptr) { return NO_TARGET_TABLE; } - for (; iter.value != NULL; ++iter) { + for (; iter.value != nullptr; ++iter) { if (!existsModeTable(iter->getTableId())) { return TABLE_DOES_NOT_EXIST; } else { ReturnValue_t result = checkTable(getTable(iter->getTableId())); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } } } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t Subsystem::checkSequence(Mode_t sequence) { @@ -55,9 +55,11 @@ ReturnValue_t Subsystem::checkSequence(Mode_t sequence) { return checkSequence(iter, getFallbackSequence(sequence)); } -bool Subsystem::existsModeSequence(Mode_t id) { return modeSequences.exists(id) == RETURN_OK; } +bool Subsystem::existsModeSequence(Mode_t id) { + return modeSequences.exists(id) == returnvalue::OK; +} -bool Subsystem::existsModeTable(Mode_t id) { return modeTables.exists(id) == RETURN_OK; } +bool Subsystem::existsModeTable(Mode_t id) { return modeTables.exists(id) == returnvalue::OK; } HybridIterator Subsystem::getCurrentTable() { return getTable(currentSequenceIterator->getTableId()); @@ -66,18 +68,23 @@ HybridIterator Subsystem::getCurrentTable() { void Subsystem::performChildOperation() { if (isInTransition) { if (commandsOutstanding <= 0) { // all children of the current table were commanded and replied - if (currentSequenceIterator.value == NULL) { // we're through with this sequence - if (checkStateAgainstTable(currentTargetTable, targetSubmode) == RETURN_OK) { + if (currentSequenceIterator.value == nullptr) { // we're through with this sequence + if (checkStateAgainstTable(currentTargetTable, targetSubmode) == returnvalue::OK) { setMode(targetMode, targetSubmode); isInTransition = false; return; } else { - transitionFailed(TARGET_TABLE_NOT_REACHED, getSequence(targetMode)->getTableId()); + Mode_t tableId = 0; + auto seq = getSequence(targetMode); + if (seq.value != nullptr) { + tableId = seq->getTableId(); + } + transitionFailed(TARGET_TABLE_NOT_REACHED, tableId); return; } } if (currentSequenceIterator->checkSuccess()) { - if (checkStateAgainstTable(getCurrentTable(), targetSubmode) != RETURN_OK) { + if (checkStateAgainstTable(getCurrentTable(), targetSubmode) != returnvalue::OK) { transitionFailed(TABLE_CHECK_FAILED, currentSequenceIterator->getTableId()); return; } @@ -106,7 +113,7 @@ void Subsystem::performChildOperation() { childrenChangedHealth = false; startTransition(mode, submode); } else if (childrenChangedMode) { - if (checkStateAgainstTable(currentTargetTable, submode) != RETURN_OK) { + if (checkStateAgainstTable(currentTargetTable, submode) != returnvalue::OK) { triggerEvent(CANT_KEEP_MODE, mode, submode); cantKeepMode(); } @@ -149,15 +156,15 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage *message) { size_t sizeRead; ReturnValue_t result = IPCStore->getData(ModeSequenceMessage::getStoreAddress(message), &pointer, &sizeRead); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { Mode_t fallbackId; size_t size = sizeRead; result = SerializeAdapter::deSerialize(&fallbackId, &pointer, &size, SerializeIF::Endianness::BIG); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { result = SerialArrayListAdapter::deSerialize(&sequence, &pointer, &size, SerializeIF::Endianness::BIG); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { result = addSequence(&sequence, ModeSequenceMessage::getSequenceId(message), fallbackId); } @@ -172,11 +179,11 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage *message) { size_t sizeRead; ReturnValue_t result = IPCStore->getData(ModeSequenceMessage::getStoreAddress(message), &pointer, &sizeRead); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { size_t size = sizeRead; result = SerialArrayListAdapter::deSerialize(&table, &pointer, &size, SerializeIF::Endianness::BIG); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { result = addTable(&table, ModeSequenceMessage::getSequenceId(message)); } IPCStore->deleteData(ModeSequenceMessage::getStoreAddress(message)); @@ -223,7 +230,7 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage *message) { Mode_t sequence = ModeSequenceMessage::getSequenceId(message); SequenceInfo *sequenceInfo = NULL; result = modeSequences.find(sequence, &sequenceInfo); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { replyToCommand(result, 0); } @@ -248,10 +255,13 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage *message) { case ModeSequenceMessage::READ_TABLE: { ReturnValue_t result; Mode_t table = ModeSequenceMessage::getSequenceId(message); - EntryPointer *entry = NULL; + EntryPointer *entry = nullptr; result = modeTables.find(table, &entry); - if (result != RETURN_OK) { + if (result != returnvalue::OK or entry == nullptr) { replyToCommand(result, 0); + if (entry == nullptr) { + return result; + } } SerializeIF *elements[2]; @@ -284,13 +294,13 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage *message) { commandQueue->reply(&reply); } break; default: - return RETURN_FAILED; + return returnvalue::FAILED; } - return RETURN_OK; + return returnvalue::OK; } void Subsystem::replyToCommand(ReturnValue_t status, uint32_t parameter) { - if (status == RETURN_OK) { + if (status == returnvalue::OK) { CommandMessage reply(CommandMessage::REPLY_COMMAND_OK, 0, 0); commandQueue->reply(&reply); } else { @@ -299,6 +309,11 @@ void Subsystem::replyToCommand(ReturnValue_t status, uint32_t parameter) { } } +ReturnValue_t Subsystem::addSequence(SequenceEntry sequence) { + return addSequence(sequence.table, sequence.mode, sequence.fallbackMode, sequence.inStore, + sequence.preInit); +} + ReturnValue_t Subsystem::addSequence(ArrayList *sequence, Mode_t id, Mode_t fallbackSequence, bool inStore, bool preInit) { ReturnValue_t result; @@ -309,7 +324,7 @@ ReturnValue_t Subsystem::addSequence(ArrayList *sequence, Mode_t if (!preInit) { result = checkSequence(HybridIterator(sequence->front(), sequence->back()), fallbackSequence); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } } @@ -323,25 +338,29 @@ ReturnValue_t Subsystem::addSequence(ArrayList *sequence, Mode_t result = modeSequences.insert(id, info); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (inStore) { #if FSFW_USE_MODESTORE == 1 result = modeStore->storeArray(sequence, &(modeSequences.find(id)->entries.firstLinkedElement)); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { modeSequences.erase(id); } #else modeSequences.erase(id); - return RETURN_FAILED; + return returnvalue::FAILED; #endif } return result; } +ReturnValue_t Subsystem::addTable(TableEntry table) { + return addTable(table.table, table.mode, table.inStore, table.preInit); +} + ReturnValue_t Subsystem::addTable(ArrayList *table, Mode_t id, bool inStore, bool preInit) { ReturnValue_t result; @@ -350,7 +369,7 @@ ReturnValue_t Subsystem::addTable(ArrayList *table, Mode_t id, bo // are not added yet. Tables added before are checked by initialize() if (!preInit) { result = checkTable(HybridIterator(table->front(), table->back())); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } } @@ -362,19 +381,19 @@ ReturnValue_t Subsystem::addTable(ArrayList *table, Mode_t id, bo result = modeTables.insert(id, pointer); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (inStore) { #if FSFW_USE_MODESTORE == 1 result = modeStore->storeArray(table, &(modeTables.find(id)->firstLinkedElement)); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { modeTables.erase(id); } #else modeTables.erase(id); - return RETURN_FAILED; + return returnvalue::FAILED; #endif } return result; @@ -388,7 +407,7 @@ ReturnValue_t Subsystem::deleteSequence(Mode_t id) { SequenceInfo *sequenceInfo; ReturnValue_t result; result = modeSequences.find(id, &sequenceInfo); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (!sequenceInfo->entries.islinked) { @@ -399,7 +418,7 @@ ReturnValue_t Subsystem::deleteSequence(Mode_t id) { modeStore->deleteList(sequenceInfo->entries.firstLinkedElement); #endif modeSequences.erase(id); - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t Subsystem::deleteTable(Mode_t id) { @@ -410,7 +429,7 @@ ReturnValue_t Subsystem::deleteTable(Mode_t id) { EntryPointer *pointer; ReturnValue_t result; result = modeTables.find(id, &pointer); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (!pointer->islinked) { @@ -421,26 +440,26 @@ ReturnValue_t Subsystem::deleteTable(Mode_t id) { modeStore->deleteList(pointer->firstLinkedElement); #endif modeSequences.erase(id); - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t Subsystem::initialize() { ReturnValue_t result = SubsystemBase::initialize(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } IPCStore = ObjectManager::instance()->get(objects::IPC_STORE); if (IPCStore == NULL) { - return RETURN_FAILED; + return returnvalue::FAILED; } #if FSFW_USE_MODESTORE == 1 modeStore = ObjectManager::instance()->get(objects::MODE_STORE); if (modeStore == nullptr) { - return RETURN_FAILED; + return returnvalue::FAILED; } #endif @@ -450,8 +469,9 @@ ReturnValue_t Subsystem::initialize() { } mode = initialMode; + submode = initSubmode; - return RETURN_OK; + return returnvalue::OK; } MessageQueueId_t Subsystem::getSequenceCommandQueue() const { @@ -535,7 +555,7 @@ void Subsystem::transitionFailed(ReturnValue_t failureCode, uint32_t parameter) // so we come here at the next fail modeHelper.setForced(true); ReturnValue_t result; - if ((result = checkSequence(getFallbackSequence(mode))) != RETURN_OK) { + if ((result = checkSequence(getFallbackSequence(mode))) != returnvalue::OK) { triggerEvent(FALLBACK_FAILED, result, getFallbackSequence(mode)); // keep still and allow arbitrary mode commands to recover isInTransition = false; @@ -561,7 +581,7 @@ void Subsystem::sendSerializablesAsCommandMessage(Command_t command, SerializeIF size_t size = 0; result = IPCStore->getFreeElement(&address, maxSize, &storeBuffer); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { replyToCommand(result, 0); return; } @@ -570,28 +590,31 @@ void Subsystem::sendSerializablesAsCommandMessage(Command_t command, SerializeIF } CommandMessage reply; ModeSequenceMessage::setModeSequenceMessage(&reply, command, address); - if (commandQueue->reply(&reply) != RETURN_OK) { + if (commandQueue->reply(&reply) != returnvalue::OK) { IPCStore->deleteData(address); } } ReturnValue_t Subsystem::checkObjectConnections() { - ReturnValue_t result = RETURN_OK; + ReturnValue_t result = returnvalue::OK; for (FixedMap::Iterator iter = modeSequences.begin(); iter != modeSequences.end(); iter++) { result = checkSequence(iter.value->first); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } } - return RETURN_OK; + return returnvalue::OK; } -void Subsystem::setInitialMode(Mode_t mode) { initialMode = mode; } +void Subsystem::setInitialMode(Mode_t mode, Submode_t submode) { + this->initialMode = mode; + this->initSubmode = submode; +} void Subsystem::cantKeepMode() { ReturnValue_t result; - if ((result = checkSequence(getFallbackSequence(mode))) != RETURN_OK) { + if ((result = checkSequence(getFallbackSequence(mode))) != returnvalue::OK) { triggerEvent(FALLBACK_FAILED, result, getFallbackSequence(mode)); return; } diff --git a/src/fsfw/subsystem/Subsystem.h b/src/fsfw/subsystem/Subsystem.h index 2c78c8cd..855c8f7a 100644 --- a/src/fsfw/subsystem/Subsystem.h +++ b/src/fsfw/subsystem/Subsystem.h @@ -1,16 +1,37 @@ #ifndef FSFW_SUBSYSTEM_SUBSYSTEM_H_ #define FSFW_SUBSYSTEM_SUBSYSTEM_H_ -#include - #include "../container/FixedArrayList.h" #include "../container/FixedMap.h" #include "../container/HybridIterator.h" #include "../container/SinglyLinkedList.h" #include "../serialize/SerialArrayListAdapter.h" #include "SubsystemBase.h" +#include "fsfw/FSFW.h" #include "modes/ModeDefinitions.h" +struct TableSequenceBase { + public: + TableSequenceBase(Mode_t mode, ArrayList *table) : mode(mode), table(table){}; + Mode_t mode; + ArrayList *table; + bool inStore = false; + bool preInit = true; +}; + +struct TableEntry : public TableSequenceBase { + public: + TableEntry(Mode_t mode, ArrayList *table) : TableSequenceBase(mode, table){}; +}; + +struct SequenceEntry : public TableSequenceBase { + public: + SequenceEntry(Mode_t mode, ArrayList *table, Mode_t fallbackMode) + : TableSequenceBase(mode, table), fallbackMode(fallbackMode) {} + + Mode_t fallbackMode; +}; + /** * @brief TODO: documentation missing * @details @@ -45,13 +66,15 @@ class Subsystem : public SubsystemBase, public HasModeSequenceIF { uint32_t maxNumberOfTables); virtual ~Subsystem(); + ReturnValue_t addSequence(SequenceEntry sequence); ReturnValue_t addSequence(ArrayList *sequence, Mode_t id, Mode_t fallbackSequence, bool inStore = true, bool preInit = true); + ReturnValue_t addTable(TableEntry table); ReturnValue_t addTable(ArrayList *table, Mode_t id, bool inStore = true, bool preInit = true); - void setInitialMode(Mode_t mode); + void setInitialMode(Mode_t mode, Submode_t submode = SUBMODE_NONE); virtual ReturnValue_t initialize() override; @@ -90,6 +113,7 @@ class Subsystem : public SubsystemBase, public HasModeSequenceIF { Submode_t targetSubmode; Mode_t initialMode = 0; + Submode_t initSubmode = SUBMODE_NONE; HybridIterator currentSequenceIterator; @@ -127,18 +151,18 @@ class Subsystem : public SubsystemBase, public HasModeSequenceIF { ReturnValue_t deleteTable(Mode_t id); - virtual void performChildOperation(); + virtual void performChildOperation() override; - virtual ReturnValue_t handleCommandMessage(CommandMessage *message); + virtual ReturnValue_t handleCommandMessage(CommandMessage *message) override; bool isFallbackSequence(Mode_t SequenceId); bool isTableUsed(Mode_t tableId); virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, - uint32_t *msToReachTheMode); + uint32_t *msToReachTheMode) override; - virtual void startTransition(Mode_t mode, Submode_t submode); + virtual void startTransition(Mode_t mode, Submode_t submode) override; void sendSerializablesAsCommandMessage(Command_t command, SerializeIF **elements, uint8_t count); diff --git a/src/fsfw/subsystem/SubsystemBase.cpp b/src/fsfw/subsystem/SubsystemBase.cpp index 104db3c3..86ee251a 100644 --- a/src/fsfw/subsystem/SubsystemBase.cpp +++ b/src/fsfw/subsystem/SubsystemBase.cpp @@ -42,7 +42,7 @@ ReturnValue_t SubsystemBase::registerChild(object_id_t objectId) { if (not resultPair.second) { return COULD_NOT_INSERT_CHILD; } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator tableIter, @@ -53,11 +53,11 @@ ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIteratorgetObject(); if ((childIter = childrenMap.find(object)) == childrenMap.end()) { - return RETURN_FAILED; + return returnvalue::FAILED; } if (childIter->second.mode != tableIter.value->getMode()) { - return RETURN_FAILED; + return returnvalue::FAILED; } Submode_t submodeToCheckAgainst = tableIter.value->getSubmode(); @@ -66,10 +66,10 @@ ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIteratorsecond.submode != submodeToCheckAgainst) { - return RETURN_FAILED; + return returnvalue::FAILED; } } - return RETURN_OK; + return returnvalue::OK; } void SubsystemBase::executeTable(HybridIterator tableIter, Submode_t targetSubmode) { @@ -122,7 +122,7 @@ void SubsystemBase::executeTable(HybridIterator tableIter, Submod // mode is forced to reach lower levels } ReturnValue_t result = commandQueue->sendMessage(iter->second.commandQueue, &command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { ++commandsOutstanding; } } @@ -136,7 +136,7 @@ ReturnValue_t SubsystemBase::updateChildMode(MessageQueueId_t queue, Mode_t mode if (iter->second.commandQueue == queue) { iter->second.mode = mode; iter->second.submode = submode; - return RETURN_OK; + return returnvalue::OK; } } return CHILD_NOT_FOUND; @@ -146,7 +146,7 @@ ReturnValue_t SubsystemBase::updateChildChangedHealth(MessageQueueId_t queue, bo for (auto iter = childrenMap.begin(); iter != childrenMap.end(); iter++) { if (iter->second.commandQueue == queue) { iter->second.healthChanged = changedHealth; - return RETURN_OK; + return returnvalue::OK; } } return CHILD_NOT_FOUND; @@ -158,14 +158,14 @@ ReturnValue_t SubsystemBase::initialize() { MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE; ReturnValue_t result = SystemObject::initialize(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (parentId != objects::NO_OBJECT) { SubsystemBase* parent = ObjectManager::instance()->get(parentId); if (parent == nullptr) { - return RETURN_FAILED; + return returnvalue::FAILED; } parentQueue = parent->getCommandQueue(); @@ -174,17 +174,17 @@ ReturnValue_t SubsystemBase::initialize() { result = healthHelper.initialize(parentQueue); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = modeHelper.initialize(parentQueue); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t SubsystemBase::performOperation(uint8_t opCode) { @@ -194,7 +194,7 @@ ReturnValue_t SubsystemBase::performOperation(uint8_t opCode) { performChildOperation(); - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t SubsystemBase::handleModeReply(CommandMessage* message) { @@ -203,14 +203,14 @@ ReturnValue_t SubsystemBase::handleModeReply(CommandMessage* message) { updateChildMode(message->getSender(), ModeMessage::getMode(message), ModeMessage::getSubmode(message)); childrenChangedMode = true; - return RETURN_OK; + return returnvalue::OK; case ModeMessage::REPLY_MODE_REPLY: case ModeMessage::REPLY_WRONG_MODE_REPLY: updateChildMode(message->getSender(), ModeMessage::getMode(message), ModeMessage::getSubmode(message)); childrenChangedMode = true; commandsOutstanding--; - return RETURN_OK; + return returnvalue::OK; case ModeMessage::REPLY_CANT_REACH_MODE: commandsOutstanding--; { @@ -220,19 +220,19 @@ ReturnValue_t SubsystemBase::handleModeReply(CommandMessage* message) { } } } - return RETURN_OK; + return returnvalue::OK; // case ModeMessage::CMD_MODE_COMMAND: // handleCommandedMode(message); - // return RETURN_OK; + // return returnvalue::OK; // case ModeMessage::CMD_MODE_ANNOUNCE: // triggerEvent(MODE_INFO, mode, submode); - // return RETURN_OK; + // return returnvalue::OK; // case ModeMessage::CMD_MODE_ANNOUNCE_RECURSIVELY: // triggerEvent(MODE_INFO, mode, submode); // commandAllChildren(message); - // return RETURN_OK; + // return returnvalue::OK; default: - return RETURN_FAILED; + return returnvalue::FAILED; } } @@ -242,7 +242,7 @@ ReturnValue_t SubsystemBase::checkTable(HybridIterator tableIter) return TABLE_CONTAINS_INVALID_OBJECT_ID; } } - return RETURN_OK; + return returnvalue::OK; } void SubsystemBase::replyToCommand(CommandMessage* message) { commandQueue->reply(message); } @@ -284,25 +284,25 @@ void SubsystemBase::checkCommandQueue() { ReturnValue_t result; CommandMessage command; - for (result = commandQueue->receiveMessage(&command); result == RETURN_OK; + for (result = commandQueue->receiveMessage(&command); result == returnvalue::OK; result = commandQueue->receiveMessage(&command)) { result = healthHelper.handleHealthCommand(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { continue; } result = modeHelper.handleModeCommand(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { continue; } result = handleModeReply(&command); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { continue; } result = handleCommandMessage(&command); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { CommandMessage reply; reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, command.getCommand()); replyToCommand(&reply); @@ -315,7 +315,7 @@ ReturnValue_t SubsystemBase::setHealth(HealthState health) { case HEALTHY: case EXTERNAL_CONTROL: healthHelper.setHealth(health); - return RETURN_OK; + return returnvalue::OK; default: return INVALID_HEALTH_STATE; } diff --git a/src/fsfw/subsystem/SubsystemBase.h b/src/fsfw/subsystem/SubsystemBase.h index 8cfd5be0..6db9efa5 100644 --- a/src/fsfw/subsystem/SubsystemBase.h +++ b/src/fsfw/subsystem/SubsystemBase.h @@ -9,7 +9,7 @@ #include "../ipc/MessageQueueIF.h" #include "../modes/HasModesIF.h" #include "../objectmanager/SystemObject.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" #include "../tasks/ExecutableObjectIF.h" #include "modes/HasModeSequenceIF.h" @@ -20,7 +20,6 @@ class SubsystemBase : public SystemObject, public HasModesIF, public HasHealthIF, - public HasReturnvaluesIF, public ExecutableObjectIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::SUBSYSTEM_BASE; @@ -43,7 +42,7 @@ class SubsystemBase : public SystemObject, * Also adds them to the internal childrenMap. * * @param objectId - * @return RETURN_OK if successful + * @return returnvalue::OK if successful * CHILD_DOESNT_HAVE_MODES if Child is no HasHealthIF and no HasModesIF * COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap */ @@ -123,15 +122,15 @@ class SubsystemBase : public SystemObject, virtual void performChildOperation() = 0; virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, - uint32_t *msToReachTheMode) = 0; + uint32_t *msToReachTheMode) override = 0; - virtual void startTransition(Mode_t mode, Submode_t submode) = 0; + virtual void startTransition(Mode_t mode, Submode_t submode) override = 0; - virtual void getMode(Mode_t *mode, Submode_t *submode); + virtual void getMode(Mode_t *mode, Submode_t *submode) override; - virtual void setToExternalControl(); + virtual void setToExternalControl() override; - virtual void announceMode(bool recursive); + virtual void announceMode(bool recursive) override; virtual void modeChanged(); }; diff --git a/src/fsfw/subsystem/modes/CMakeLists.txt b/src/fsfw/subsystem/modes/CMakeLists.txt index 6ac6a293..ba57de2c 100644 --- a/src/fsfw/subsystem/modes/CMakeLists.txt +++ b/src/fsfw/subsystem/modes/CMakeLists.txt @@ -1,5 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - ModeSequenceMessage.cpp - ModeStore.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE ModeSequenceMessage.cpp ModeStore.cpp) diff --git a/src/fsfw/subsystem/modes/ModeDefinitions.h b/src/fsfw/subsystem/modes/ModeDefinitions.h index 9a6b8e31..d37baa3b 100644 --- a/src/fsfw/subsystem/modes/ModeDefinitions.h +++ b/src/fsfw/subsystem/modes/ModeDefinitions.h @@ -15,23 +15,23 @@ class ModeListEntry : public SerializeIF, public LinkedElement { uint8_t value3 = 0; uint8_t value4 = 0; - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const { + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override { ReturnValue_t result; result = SerializeAdapter::serialize(&value1, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&value2, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&value3, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -40,27 +40,27 @@ class ModeListEntry : public SerializeIF, public LinkedElement { return result; } - virtual size_t getSerializedSize() const { + size_t getSerializedSize() const override { return sizeof(value1) + sizeof(value2) + sizeof(value3) + sizeof(value4); } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) { + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override { ReturnValue_t result; result = SerializeAdapter::deSerialize(&value1, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::deSerialize(&value2, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::deSerialize(&value3, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::deSerialize(&value4, buffer, size, streamEndianness); diff --git a/src/fsfw/subsystem/modes/ModeStore.cpp b/src/fsfw/subsystem/modes/ModeStore.cpp index c70b5e21..2fb16d31 100644 --- a/src/fsfw/subsystem/modes/ModeStore.cpp +++ b/src/fsfw/subsystem/modes/ModeStore.cpp @@ -54,28 +54,28 @@ ReturnValue_t ModeStore::storeArray(ArrayList* sequence, } pointer->setNext(NULL); OSAL::unlockMutex(mutex); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t ModeStore::deleteList(ModeListEntry* sequence) { ReturnValue_t result = isValidEntry(sequence); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } OSAL::lockMutex(mutex, OSAL::NO_TIMEOUT); deleteListNoLock(sequence); OSAL::unlockMutex(mutex); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t ModeStore::readList(ModeListEntry* sequence, ArrayList* into) { ReturnValue_t result = isValidEntry(sequence); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } OSAL::lockMutex(mutex, OSAL::NO_TIMEOUT); result = into->insert(*sequence->value); - while ((result == HasReturnvaluesIF::RETURN_OK) && (sequence->getNext() != NULL)) { + while ((result == returnvalue::OK) && (sequence->getNext() != NULL)) { result = into->insert(*sequence->value); sequence = sequence->getNext()->value; } @@ -117,7 +117,7 @@ ReturnValue_t ModeStore::isValidEntry(ModeListEntry* sequence) { if ((sequence < store.front()) || (sequence > store.back()) || sequence->getNext() == emptySlot) { return INVALID_ENTRY; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } #endif diff --git a/src/fsfw/subsystem/modes/ModeStoreIF.h b/src/fsfw/subsystem/modes/ModeStoreIF.h index 79215971..3d56f992 100644 --- a/src/fsfw/subsystem/modes/ModeStoreIF.h +++ b/src/fsfw/subsystem/modes/ModeStoreIF.h @@ -7,7 +7,7 @@ #include "../../container/ArrayList.h" #include "../../container/SinglyLinkedList.h" -#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../returnvalues/returnvalue.h" #include "ModeDefinitions.h" class ModeStoreIF { diff --git a/src/fsfw/tasks/CMakeLists.txt b/src/fsfw/tasks/CMakeLists.txt index 1964bb4e..1d4ab4e1 100644 --- a/src/fsfw/tasks/CMakeLists.txt +++ b/src/fsfw/tasks/CMakeLists.txt @@ -1,5 +1,3 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - FixedSequenceSlot.cpp - FixedSlotSequence.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} PRIVATE FixedSequenceSlot.cpp FixedSlotSequence.cpp + PeriodicTaskBase.cpp FixedTimeslotTaskBase.cpp) diff --git a/src/fsfw/tasks/ExecutableObjectIF.h b/src/fsfw/tasks/ExecutableObjectIF.h index 753a124f..1e3f19e4 100644 --- a/src/fsfw/tasks/ExecutableObjectIF.h +++ b/src/fsfw/tasks/ExecutableObjectIF.h @@ -5,7 +5,7 @@ class PeriodicTaskIF; #include -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" /** * @brief The interface provides a method to execute objects within a task. * @details The performOperation method, that is required by the interface is @@ -45,7 +45,7 @@ class ExecutableObjectIF { * called so the execution frequency can't be cached in initialize() * @return */ - virtual ReturnValue_t initializeAfterTaskCreation() { return HasReturnvaluesIF::RETURN_OK; } + virtual ReturnValue_t initializeAfterTaskCreation() { return returnvalue::OK; } }; #endif /* FRAMEWORK_TASKS_EXECUTABLEOBJECTIF_H_ */ diff --git a/src/fsfw/tasks/FixedSlotSequence.cpp b/src/fsfw/tasks/FixedSlotSequence.cpp index d4c67b4d..cba7a87a 100644 --- a/src/fsfw/tasks/FixedSlotSequence.cpp +++ b/src/fsfw/tasks/FixedSlotSequence.cpp @@ -16,7 +16,7 @@ FixedSlotSequence::~FixedSlotSequence() { void FixedSlotSequence::executeAndAdvance() { current->executableObject->performOperation(current->opcode); - // if (returnValue != RETURN_OK) { + // if (returnValue != returnvalue::OK) { // this->sendErrorMessage( returnValue ); // } // Increment the polling Sequence iterator @@ -29,7 +29,7 @@ void FixedSlotSequence::executeAndAdvance() { uint32_t FixedSlotSequence::getIntervalToNextSlotMs() { uint32_t oldTime; - SlotListIter slotListIter = current; + auto slotListIter = current; // Get the pollingTimeMs of the current slot object. oldTime = slotListIter->pollingTimeMs; // Advance to the next object. @@ -51,7 +51,7 @@ uint32_t FixedSlotSequence::getIntervalToNextSlotMs() { uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() { uint32_t currentTime; - SlotListIter slotListIter = current; + auto slotListIter = current; // Get the pollingTimeMs of the current slot object. currentTime = slotListIter->pollingTimeMs; @@ -67,7 +67,7 @@ uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() { bool FixedSlotSequence::slotFollowsImmediately() { uint32_t currentTime = current->pollingTimeMs; - SlotListIter fixedSequenceIter = this->current; + auto fixedSequenceIter = this->current; // Get the pollingTimeMs of the current slot object. if (fixedSequenceIter == slotList.begin()) return false; fixedSequenceIter--; @@ -96,9 +96,9 @@ ReturnValue_t FixedSlotSequence::checkSequence() const { return FixedTimeslotTaskIF::SLOT_LIST_EMPTY; } - if (customCheckFunction != nullptr) { - ReturnValue_t result = customCheckFunction(slotList); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (customChecker != nullptr) { + ReturnValue_t result = customChecker(slotList, customCheckArgs); + if (result != returnvalue::OK) { // Continue for now but print error output. #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "FixedSlotSequence::checkSequence:" @@ -132,9 +132,9 @@ ReturnValue_t FixedSlotSequence::checkSequence() const { // << slotList.size() << std::endl; #endif if (errorCount > 0) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const { @@ -144,7 +144,7 @@ ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const { // Ensure that each unique object is initialized once. if (uniqueObjects.find(slot.executableObject) == uniqueObjects.end()) { ReturnValue_t result = slot.executableObject->initializeAfterTaskCreation(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { count++; } uniqueObjects.emplace(slot.executableObject); @@ -156,11 +156,14 @@ ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const { "Counted " << count << " failed initializations!" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } -void FixedSlotSequence::addCustomCheck(ReturnValue_t (*customCheckFunction)(const SlotList&)) { - this->customCheckFunction = customCheckFunction; +void FixedSlotSequence::addCustomCheck(CustomCheckFunc customChecker_, void* checkerArgs_) { + customChecker = customChecker_; + customCheckArgs = checkerArgs_; } + +bool FixedSlotSequence::isEmpty() const { return slotList.empty(); } diff --git a/src/fsfw/tasks/FixedSlotSequence.h b/src/fsfw/tasks/FixedSlotSequence.h index a287c5b2..2e38ee4b 100644 --- a/src/fsfw/tasks/FixedSlotSequence.h +++ b/src/fsfw/tasks/FixedSlotSequence.h @@ -30,12 +30,12 @@ class FixedSlotSequence { public: using SlotList = std::multiset; using SlotListIter = std::multiset::iterator; - + using CustomCheckFunc = ReturnValue_t (*)(const SlotList&, void* args); /** * @brief The constructor of the FixedSlotSequence object. * @param setLength The period length, expressed in ms. */ - FixedSlotSequence(uint32_t setLengthMs); + explicit FixedSlotSequence(uint32_t setLengthMs); /** * @brief The destructor of the FixedSlotSequence object. @@ -106,7 +106,7 @@ class FixedSlotSequence { /** * @brief This method returns the length of this FixedSlotSequence instance. */ - uint32_t getLengthMs() const; + [[nodiscard]] uint32_t getLengthMs() const; /** * @brief The method to execute the device handler entered in the current @@ -137,7 +137,7 @@ class FixedSlotSequence { * @return * - SLOT_LIST_EMPTY if the slot list is empty */ - ReturnValue_t checkSequence() const; + [[nodiscard]] ReturnValue_t checkSequence() const; /** * @brief A custom check can be injected for the respective slot list. @@ -149,7 +149,7 @@ class FixedSlotSequence { * @param customCheckFunction * */ - void addCustomCheck(ReturnValue_t (*customCheckFunction)(const SlotList&)); + void addCustomCheck(CustomCheckFunc func, void* userArgs); /** * @brief Perform any initialization steps required after the executing @@ -157,7 +157,9 @@ class FixedSlotSequence { * executing task! * @return */ - ReturnValue_t intializeSequenceAfterTaskCreation() const; + [[nodiscard]] ReturnValue_t intializeSequenceAfterTaskCreation() const; + + [[nodiscard]] bool isEmpty() const; protected: /** @@ -173,7 +175,8 @@ class FixedSlotSequence { */ SlotList slotList; - ReturnValue_t (*customCheckFunction)(const SlotList&) = nullptr; + CustomCheckFunc customChecker = nullptr; + void* customCheckArgs = nullptr; uint32_t lengthMs; }; diff --git a/src/fsfw/tasks/FixedTimeslotTaskBase.cpp b/src/fsfw/tasks/FixedTimeslotTaskBase.cpp new file mode 100644 index 00000000..3327deae --- /dev/null +++ b/src/fsfw/tasks/FixedTimeslotTaskBase.cpp @@ -0,0 +1,27 @@ +#include "FixedTimeslotTaskBase.h" + +#include "fsfw/objectmanager/ObjectManager.h" + +FixedTimeslotTaskBase::FixedTimeslotTaskBase(TaskPeriod period_, + TaskDeadlineMissedFunction dlmFunc_) + : period(period_), pollingSeqTable(getPeriodMs()), dlmFunc(dlmFunc_) {} +uint32_t FixedTimeslotTaskBase::getPeriodMs() const { return static_cast(period * 1000); } + +bool FixedTimeslotTaskBase::isEmpty() const { return pollingSeqTable.isEmpty(); } + +ReturnValue_t FixedTimeslotTaskBase::checkSequence() { return pollingSeqTable.checkSequence(); } + +ReturnValue_t FixedTimeslotTaskBase::addSlot(object_id_t execId, ExecutableObjectIF* execObj, + uint32_t slotTimeMs, int8_t executionStep) { + if (execObj == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "Component 0x" << std::hex << std::setw(8) << std::setfill('0') << execObj + << std::setfill(' ') << " not found, not adding it to PST" << std::dec << std::endl; +#else + sif::printError("Component 0x%08x not found, not adding it to PST\n"); +#endif + return returnvalue::FAILED; + } + pollingSeqTable.addSlot(execId, slotTimeMs, executionStep, execObj, this); + return returnvalue::OK; +} diff --git a/src/fsfw/tasks/FixedTimeslotTaskBase.h b/src/fsfw/tasks/FixedTimeslotTaskBase.h new file mode 100644 index 00000000..b88b393c --- /dev/null +++ b/src/fsfw/tasks/FixedTimeslotTaskBase.h @@ -0,0 +1,44 @@ +#ifndef FSFW_EXAMPLE_HOSTED_FIXEDTIMESLOTTASKBASE_H +#define FSFW_EXAMPLE_HOSTED_FIXEDTIMESLOTTASKBASE_H + +#include "FixedSlotSequence.h" +#include "FixedTimeslotTaskIF.h" +#include "definitions.h" + +class FixedTimeslotTaskBase : public FixedTimeslotTaskIF { + public: + explicit FixedTimeslotTaskBase(TaskPeriod period, TaskDeadlineMissedFunction dlmFunc = nullptr); + ~FixedTimeslotTaskBase() override = default; + ; + + protected: + /** + * @brief Period of task in floating point seconds + */ + TaskPeriod period; + + //! Polling sequence table which contains the object to execute + //! and information like the timeslots and the passed execution step. + FixedSlotSequence pollingSeqTable; + + /** + * @brief The pointer to the deadline-missed function. + * @details + * This pointer stores the function that is executed if the task's deadline + * is missed. So, each may react individually on a timing failure. + * The pointer may be NULL, then nothing happens on missing the deadline. + * The deadline is equal to the next execution of the periodic task. + */ + TaskDeadlineMissedFunction dlmFunc = nullptr; + + ReturnValue_t checkSequence() override; + + [[nodiscard]] uint32_t getPeriodMs() const override; + + [[nodiscard]] bool isEmpty() const override; + + ReturnValue_t addSlot(object_id_t execId, ExecutableObjectIF* componentId, uint32_t slotTimeMs, + int8_t executionStep) override; +}; + +#endif // FSFW_EXAMPLE_HOSTED_FIXEDTIMESLOTTASKBASE_H diff --git a/src/fsfw/tasks/FixedTimeslotTaskIF.h b/src/fsfw/tasks/FixedTimeslotTaskIF.h index 497db245..916af639 100644 --- a/src/fsfw/tasks/FixedTimeslotTaskIF.h +++ b/src/fsfw/tasks/FixedTimeslotTaskIF.h @@ -2,6 +2,7 @@ #define FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_ #include "PeriodicTaskIF.h" +#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/objectmanager/ObjectManagerIF.h" #include "fsfw/returnvalues/FwClassIds.h" @@ -11,10 +12,23 @@ */ class FixedTimeslotTaskIF : public PeriodicTaskIF { public: - virtual ~FixedTimeslotTaskIF() {} + ~FixedTimeslotTaskIF() override = default; static constexpr ReturnValue_t SLOT_LIST_EMPTY = - HasReturnvaluesIF::makeReturnCode(CLASS_ID::FIXED_SLOT_TASK_IF, 0); + returnvalue::makeCode(CLASS_ID::FIXED_SLOT_TASK_IF, 0); + + /** + * Add an object with a slot time and the execution step to the task. + * The execution step will be passed to the object (e.g. as an operation + * code in #performOperation) + * @param componentId + * @param slotTimeMs + * @param executionStep + * @return + */ + virtual ReturnValue_t addSlot(object_id_t execId, ExecutableObjectIF* obj, uint32_t slotTimeMs, + int8_t executionStep) = 0; + /** * Add an object with a slot time and the execution step to the task. * The execution step will be passed to the object (e.g. as an operation @@ -25,12 +39,24 @@ class FixedTimeslotTaskIF : public PeriodicTaskIF { * @return */ virtual ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep) = 0; + int8_t executionStep) { + auto* execObj = ObjectManager::instance()->get(componentId); + return addSlot(componentId, execObj, slotTimeMs, executionStep); + } + /** * Check whether the sequence is valid and perform all other required * initialization steps which are needed after task creation */ - virtual ReturnValue_t checkSequence() const = 0; + virtual ReturnValue_t checkSequence() = 0; + + ReturnValue_t addComponent(object_id_t object, uint8_t opCode) override { + return returnvalue::FAILED; + } + + ReturnValue_t addComponent(ExecutableObjectIF* object, uint8_t opCode) override { + return returnvalue::FAILED; + } }; #endif /* FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_ */ diff --git a/src/fsfw/tasks/PeriodicTaskBase.cpp b/src/fsfw/tasks/PeriodicTaskBase.cpp new file mode 100644 index 00000000..3ae8afe7 --- /dev/null +++ b/src/fsfw/tasks/PeriodicTaskBase.cpp @@ -0,0 +1,71 @@ +#include "PeriodicTaskBase.h" + +#include + +#include "fsfw/objectmanager/ObjectManager.h" +#include "fsfw/serviceinterface.h" + +PeriodicTaskBase::PeriodicTaskBase(TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_) + : period(period_), dlmFunc(dlmFunc_) { + // Hints at configuration error + if (PeriodicTaskBase::getPeriodMs() <= 1) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "Passed task period 0 or smaller than 1 ms" << std::endl; +#else + sif::printWarning("Passed task period 0 or smaller than 1ms\n"); +#endif + } +} + +uint32_t PeriodicTaskBase::getPeriodMs() const { return static_cast(period * 1000); } + +bool PeriodicTaskBase::isEmpty() const { return objectList.empty(); } + +ReturnValue_t PeriodicTaskBase::addComponent(object_id_t object) { return addComponent(object, 0); } + +ReturnValue_t PeriodicTaskBase::addComponent(ExecutableObjectIF* object) { + return addComponent(object, 0); +} + +ReturnValue_t PeriodicTaskBase::initObjsAfterTaskCreation() { + std::set uniqueObjects; + ReturnValue_t status = returnvalue::OK; + uint32_t count = 0; + for (const auto& obj : objectList) { + // Ensure that each unique object is initialized once. + if (uniqueObjects.find(obj.first) == uniqueObjects.end()) { + ReturnValue_t result = obj.first->initializeAfterTaskCreation(); + if (result != returnvalue::OK) { + count++; + status = result; + } + uniqueObjects.emplace(obj.first); + } + } + if (count > 0) { + } + return status; +} + +ReturnValue_t PeriodicTaskBase::addComponent(object_id_t object, uint8_t opCode) { + auto* newObject = ObjectManager::instance()->get(object); + return addComponent(newObject, opCode); +} + +ReturnValue_t PeriodicTaskBase::addComponent(ExecutableObjectIF* object, uint8_t opCode) { + if (object == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "PeriodicTask::addComponent: Invalid object. Make sure" + << " it implements ExecutableObjectIF!" << std::endl; +#else + sif::printError( + "PeriodicTask::addComponent: Invalid object. Make sure it " + "implements ExecutableObjectIF!\n"); +#endif + return returnvalue::FAILED; + } + objectList.push_back({object, opCode}); + object->setTaskIF(this); + + return returnvalue::OK; +} diff --git a/src/fsfw/tasks/PeriodicTaskBase.h b/src/fsfw/tasks/PeriodicTaskBase.h new file mode 100644 index 00000000..9023f104 --- /dev/null +++ b/src/fsfw/tasks/PeriodicTaskBase.h @@ -0,0 +1,54 @@ +#ifndef FSFW_SRC_FSFW_TASKS_PERIODICTASKBASE_H_ +#define FSFW_SRC_FSFW_TASKS_PERIODICTASKBASE_H_ + +#include +#include + +#include "fsfw/tasks/PeriodicTaskIF.h" +#include "fsfw/tasks/definitions.h" + +class ExecutableObjectIF; + +class PeriodicTaskBase : public PeriodicTaskIF { + public: + explicit PeriodicTaskBase(TaskPeriod period, + TaskDeadlineMissedFunction deadlineMissedFunc = nullptr); + + ReturnValue_t addComponent(object_id_t object, uint8_t opCode) override; + ReturnValue_t addComponent(ExecutableObjectIF* object, uint8_t opCode) override; + + ReturnValue_t addComponent(object_id_t object) override; + ReturnValue_t addComponent(ExecutableObjectIF* object) override; + + [[nodiscard]] uint32_t getPeriodMs() const override; + + [[nodiscard]] bool isEmpty() const override; + + ReturnValue_t initObjsAfterTaskCreation(); + + protected: + //! Typedef for the List of objects. Will contain the objects to execute and their respective + //! operation codes + using ObjectList = std::vector>; + /** + * @brief This attribute holds a list of objects to be executed. + */ + ObjectList objectList; + + /** + * @brief Period of task in floating point seconds + */ + TaskPeriod period; + + /** + * @brief The pointer to the deadline-missed function. + * @details + * This pointer stores the function that is executed if the task's deadline + * is missed. So, each may react individually on a timing failure. + * The pointer may be NULL, then nothing happens on missing the deadline. + * The deadline is equal to the next execution of the periodic task. + */ + TaskDeadlineMissedFunction dlmFunc = nullptr; +}; + +#endif /* FSFW_SRC_FSFW_TASKS_PERIODICTASKBASE_H_ */ diff --git a/src/fsfw/tasks/PeriodicTaskIF.h b/src/fsfw/tasks/PeriodicTaskIF.h index c78a32de..d1bbf456 100644 --- a/src/fsfw/tasks/PeriodicTaskIF.h +++ b/src/fsfw/tasks/PeriodicTaskIF.h @@ -3,9 +3,8 @@ #include -#include "../objectmanager/SystemObjectIF.h" -#include "../timemanager/Clock.h" -class ExecutableObjectIF; +#include "fsfw/objectmanager/SystemObjectIF.h" +#include "fsfw/tasks/ExecutableObjectIF.h" /** * New version of TaskIF @@ -18,7 +17,7 @@ class PeriodicTaskIF { /** * @brief A virtual destructor as it is mandatory for interfaces. */ - virtual ~PeriodicTaskIF() {} + virtual ~PeriodicTaskIF() = default; /** * @brief With the startTask method, a created task can be started * for the first time. @@ -26,28 +25,29 @@ class PeriodicTaskIF { virtual ReturnValue_t startTask() = 0; /** - * Add a component (object) to a periodic task. - * @param object - * Add an object to the task. The object needs to implement ExecutableObjectIF - * @return + * Adds an object to the list of objects to be executed. + * The objects are executed in the order added. The object needs to implement + * ExecutableObjectIF + * @param object Id of the object to add. + * @return returnvalue::OK on success, returnvalue::FAILED if the object could not be added. */ - virtual ReturnValue_t addComponent(object_id_t object) { - return HasReturnvaluesIF::RETURN_FAILED; - }; + virtual ReturnValue_t addComponent(object_id_t object, uint8_t opCode) = 0; + virtual ReturnValue_t addComponent(object_id_t object) { return addComponent(object, 0); }; /** - * Add an object to a periodic task. - * @param object - * Add an object to the task. - * @return + * Adds an object to the list of objects to be executed. + * The objects are executed in the order added. + * @param object pointer to the object to add. + * @return returnvalue::OK on success, returnvalue::FAILED if the object could not be added. */ - virtual ReturnValue_t addComponent(ExecutableObjectIF* object) { - return HasReturnvaluesIF::RETURN_FAILED; - }; + virtual ReturnValue_t addComponent(ExecutableObjectIF* object, uint8_t opCode) = 0; + virtual ReturnValue_t addComponent(ExecutableObjectIF* object) { return addComponent(object, 0); } virtual ReturnValue_t sleepFor(uint32_t ms) = 0; - virtual uint32_t getPeriodMs() const = 0; + [[nodiscard]] virtual uint32_t getPeriodMs() const = 0; + + [[nodiscard]] virtual bool isEmpty() const = 0; }; -#endif /* PERIODICTASKIF_H_ */ +#endif /* FRAMEWORK_TASK_PERIODICTASKIF_H_ */ diff --git a/src/fsfw/tasks/SemaphoreIF.h b/src/fsfw/tasks/SemaphoreIF.h index 3f544de8..9a692e9b 100644 --- a/src/fsfw/tasks/SemaphoreIF.h +++ b/src/fsfw/tasks/SemaphoreIF.h @@ -3,7 +3,7 @@ #include #include "../returnvalues/FwClassIds.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" /** * @brief Generic interface for semaphores, which can be used to achieve @@ -46,14 +46,14 @@ class SemaphoreIF { * for a maximum of timeoutMs while trying to acquire the semaphore. * This can be used to achieve task synchrnization. * @param timeoutMs - * @return - c RETURN_OK for successfull acquisition + * @return - c returnvalue::OK for successfull acquisition */ virtual ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, uint32_t timeoutMs = 0) = 0; /** * Corrensponding call to release a semaphore. - * @return -@c RETURN_OK for successfull release + * @return -@c returnvalue::OK for successfull release */ virtual ReturnValue_t release() = 0; diff --git a/src/fsfw/tasks/TaskFactory.h b/src/fsfw/tasks/TaskFactory.h index fcd62678..828c533e 100644 --- a/src/fsfw/tasks/TaskFactory.h +++ b/src/fsfw/tasks/TaskFactory.h @@ -4,7 +4,7 @@ #include #include "FixedTimeslotTaskIF.h" -#include "Typedef.h" +#include "definitions.h" /** * Singleton Class that produces Tasks. diff --git a/src/fsfw/tasks/Typedef.h b/src/fsfw/tasks/Typedef.h deleted file mode 100644 index 1bb75131..00000000 --- a/src/fsfw/tasks/Typedef.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef FSFW_TASKS_TYPEDEF_H_ -#define FSFW_TASKS_TYPEDEF_H_ - -#include -#include - -typedef const char* TaskName; -typedef uint32_t TaskPriority; -typedef size_t TaskStackSize; -typedef double TaskPeriod; -typedef void (*TaskDeadlineMissedFunction)(); - -#endif /* FSFW_TASKS_TYPEDEF_H_ */ diff --git a/src/fsfw/tasks/definitions.h b/src/fsfw/tasks/definitions.h new file mode 100644 index 00000000..586884b6 --- /dev/null +++ b/src/fsfw/tasks/definitions.h @@ -0,0 +1,13 @@ +#ifndef FSFW_TASKS_TYPEDEF_H_ +#define FSFW_TASKS_TYPEDEF_H_ + +#include +#include + +using TaskName = const char*; +using TaskPriority = int; +using TaskStackSize = size_t; +using TaskPeriod = double; +using TaskDeadlineMissedFunction = void (*)(); + +#endif /* FSFW_TASKS_TYPEDEF_H_ */ diff --git a/src/fsfw/tcdistribution/CCSDSDistributor.cpp b/src/fsfw/tcdistribution/CCSDSDistributor.cpp deleted file mode 100644 index 3f4bbee3..00000000 --- a/src/fsfw/tcdistribution/CCSDSDistributor.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include "fsfw/tcdistribution/CCSDSDistributor.h" - -#include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tmtcpacket/SpacePacketBase.h" - -#define CCSDS_DISTRIBUTOR_DEBUGGING 0 - -CCSDSDistributor::CCSDSDistributor(uint16_t setDefaultApid, object_id_t setObjectId) - : TcDistributor(setObjectId), defaultApid(setDefaultApid) {} - -CCSDSDistributor::~CCSDSDistributor() {} - -TcDistributor::TcMqMapIter CCSDSDistributor::selectDestination() { -#if CCSDS_DISTRIBUTOR_DEBUGGING == 1 -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "CCSDSDistributor::selectDestination received: " - << this->currentMessage.getStorageId().poolIndex << ", " - << this->currentMessage.getStorageId().packetIndex << std::endl; -#else - sif::printDebug("CCSDSDistributor::selectDestination received: %d, %d\n", - currentMessage.getStorageId().poolIndex, - currentMessage.getStorageId().packetIndex); -#endif -#endif - const uint8_t* packet = nullptr; - size_t size = 0; - ReturnValue_t result = this->tcStore->getData(currentMessage.getStorageId(), &packet, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { -#if FSFW_VERBOSE_LEVEL >= 1 -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "CCSDSDistributor::selectDestination: Getting data from" - " store failed!" - << std::endl; -#else - sif::printError( - "CCSDSDistributor::selectDestination: Getting data from" - " store failed!\n"); -#endif -#endif - } - SpacePacketBase currentPacket(packet); - -#if FSFW_CPP_OSTREAM_ENABLED == 1 && CCSDS_DISTRIBUTOR_DEBUGGING == 1 - sif::info << "CCSDSDistributor::selectDestination has packet with APID " << std::hex - << currentPacket.getAPID() << std::dec << std::endl; -#endif - TcMqMapIter position = this->queueMap.find(currentPacket.getAPID()); - if (position != this->queueMap.end()) { - return position; - } else { - // The APID was not found. Forward packet to main SW-APID anyway to - // create acceptance failure report. - return this->queueMap.find(this->defaultApid); - } -} - -MessageQueueId_t CCSDSDistributor::getRequestQueue() { return tcQueue->getId(); } - -ReturnValue_t CCSDSDistributor::registerApplication(AcceptsTelecommandsIF* application) { - ReturnValue_t returnValue = RETURN_OK; - auto insertPair = - this->queueMap.emplace(application->getIdentifier(), application->getRequestQueue()); - if (not insertPair.second) { - returnValue = RETURN_FAILED; - } - return returnValue; -} - -ReturnValue_t CCSDSDistributor::registerApplication(uint16_t apid, MessageQueueId_t id) { - ReturnValue_t returnValue = RETURN_OK; - auto insertPair = this->queueMap.emplace(apid, id); - if (not insertPair.second) { - returnValue = RETURN_FAILED; - } - return returnValue; -} - -uint16_t CCSDSDistributor::getIdentifier() { return 0; } - -ReturnValue_t CCSDSDistributor::initialize() { - ReturnValue_t status = this->TcDistributor::initialize(); - this->tcStore = ObjectManager::instance()->get(objects::TC_STORE); - if (this->tcStore == nullptr) { -#if FSFW_VERBOSE_LEVEL >= 1 -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "CCSDSDistributor::initialize: Could not initialize" - " TC store!" - << std::endl; -#else - sif::printError( - "CCSDSDistributor::initialize: Could not initialize" - " TC store!\n"); -#endif -#endif - status = RETURN_FAILED; - } - return status; -} - -ReturnValue_t CCSDSDistributor::callbackAfterSending(ReturnValue_t queueStatus) { - if (queueStatus != RETURN_OK) { - tcStore->deleteData(currentMessage.getStorageId()); - } - return RETURN_OK; -} diff --git a/src/fsfw/tcdistribution/CCSDSDistributor.h b/src/fsfw/tcdistribution/CCSDSDistributor.h deleted file mode 100644 index 2d9b1fbd..00000000 --- a/src/fsfw/tcdistribution/CCSDSDistributor.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_ -#define FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_ - -#include "../objectmanager/ObjectManagerIF.h" -#include "../storagemanager/StorageManagerIF.h" -#include "../tcdistribution/CCSDSDistributorIF.h" -#include "../tcdistribution/TcDistributor.h" -#include "../tmtcservices/AcceptsTelecommandsIF.h" - -/** - * @brief An instantiation of the CCSDSDistributorIF. - * @details - * It receives Space Packets, and selects a destination depending on the - * APID of the telecommands. - * The Secondary Header (with Service/Subservice) is ignored. - * @ingroup tc_distribution - */ -class CCSDSDistributor : public TcDistributor, - public CCSDSDistributorIF, - public AcceptsTelecommandsIF { - public: - /** - * @brief The constructor sets the default APID and calls the - * TcDistributor ctor with a certain object id. - * @details - * @c tcStore is set in the @c initialize method. - * @param setDefaultApid The default APID, where packets with unknown - * destination are sent to. - */ - CCSDSDistributor(uint16_t setDefaultApid, object_id_t setObjectId); - /** - * The destructor is empty. - */ - virtual ~CCSDSDistributor(); - - MessageQueueId_t getRequestQueue() override; - ReturnValue_t registerApplication(uint16_t apid, MessageQueueId_t id) override; - ReturnValue_t registerApplication(AcceptsTelecommandsIF* application) override; - uint16_t getIdentifier() override; - ReturnValue_t initialize() override; - - protected: - /** - * This implementation checks if an application with fitting APID has - * registered and forwards the packet to the according message queue. - * If the packet is not found, it returns the queue to @c defaultApid, - * where a Acceptance Failure message should be generated. - * @return Iterator to map entry of found APID or iterator to default APID. - */ - TcMqMapIter selectDestination() override; - /** - * The callback here handles the generation of acceptance - * success/failure messages. - */ - ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus) override; - - /** - * The default APID, where packets with unknown APID are sent to. - */ - uint16_t defaultApid; - /** - * A reference to the TC storage must be maintained, as this class handles - * pure Space Packets and there exists no SpacePacketStored class. - */ - StorageManagerIF* tcStore = nullptr; -}; - -#endif /* FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_ */ diff --git a/src/fsfw/tcdistribution/CCSDSDistributorIF.h b/src/fsfw/tcdistribution/CCSDSDistributorIF.h deleted file mode 100644 index d1c88118..00000000 --- a/src/fsfw/tcdistribution/CCSDSDistributorIF.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_ -#define FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_ - -#include "../ipc/MessageQueueSenderIF.h" -#include "../tmtcservices/AcceptsTelecommandsIF.h" -/** - * This is the Interface to a CCSDS Distributor. - * On a CCSDS Distributor, Applications (in terms of CCSDS) may register - * themselves, either by passing a pointer to themselves (and implementing the - * CCSDSApplicationIF), or by explicitly passing an APID and a MessageQueueId - * to route the TC's to. - * @ingroup tc_distribution - */ -class CCSDSDistributorIF { - public: - /** - * With this call, a class implementing the CCSDSApplicationIF can register - * at the distributor. - * @param application A pointer to the Application to register. - * @return - @c RETURN_OK on success, - * - @c RETURN_FAILED on failure. - */ - virtual ReturnValue_t registerApplication(AcceptsTelecommandsIF* application) = 0; - /** - * With this call, other Applications can register to the CCSDS distributor. - * This is done by passing an APID and a MessageQueueId to the method. - * @param apid The APID to register. - * @param id The MessageQueueId of the message queue to send the - * TC Packets to. - * @return - @c RETURN_OK on success, - * - @c RETURN_FAILED on failure. - */ - virtual ReturnValue_t registerApplication(uint16_t apid, MessageQueueId_t id) = 0; - /** - * The empty virtual destructor. - */ - virtual ~CCSDSDistributorIF() {} -}; - -#endif /* FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_ */ diff --git a/src/fsfw/tcdistribution/CFDPDistributor.cpp b/src/fsfw/tcdistribution/CFDPDistributor.cpp deleted file mode 100644 index d8be1543..00000000 --- a/src/fsfw/tcdistribution/CFDPDistributor.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "fsfw/tcdistribution/CFDPDistributor.h" - -#include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/tcdistribution/CCSDSDistributorIF.h" -#include "fsfw/tmtcpacket/cfdp/CFDPPacketStored.h" - -#ifndef FSFW_CFDP_DISTRIBUTOR_DEBUGGING -#define FSFW_CFDP_DISTRIBUTOR_DEBUGGING 1 -#endif - -CFDPDistributor::CFDPDistributor(uint16_t setApid, object_id_t setObjectId, - object_id_t setPacketSource) - : TcDistributor(setObjectId), - apid(setApid), - checker(setApid), - tcStatus(RETURN_FAILED), - packetSource(setPacketSource) {} - -CFDPDistributor::~CFDPDistributor() {} - -CFDPDistributor::TcMqMapIter CFDPDistributor::selectDestination() { -#if FSFW_CFDP_DISTRIBUTOR_DEBUGGING == 1 - store_address_t storeId = this->currentMessage.getStorageId(); -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "CFDPDistributor::handlePacket received: " << storeId.poolIndex << ", " - << storeId.packetIndex << std::endl; -#else - sif::printDebug("CFDPDistributor::handlePacket received: %d, %d\n", storeId.poolIndex, - storeId.packetIndex); -#endif -#endif - TcMqMapIter queueMapIt = this->queueMap.end(); - if (this->currentPacket == nullptr) { - return queueMapIt; - } - this->currentPacket->setStoreAddress(this->currentMessage.getStorageId()); - if (currentPacket->getWholeData() != nullptr) { - tcStatus = checker.checkPacket(currentPacket); - if (tcStatus != HasReturnvaluesIF::RETURN_OK) { -#if FSFW_VERBOSE_LEVEL >= 1 -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "CFDPDistributor::handlePacket: Packet format invalid, code " - << static_cast(tcStatus) << std::endl; -#else - sif::printDebug("CFDPDistributor::handlePacket: Packet format invalid, code %d\n", - static_cast(tcStatus)); -#endif -#endif - } - queueMapIt = this->queueMap.find(0); - } else { - tcStatus = PACKET_LOST; - } - - if (queueMapIt == this->queueMap.end()) { - tcStatus = DESTINATION_NOT_FOUND; -#if FSFW_VERBOSE_LEVEL >= 1 -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "CFDPDistributor::handlePacket: Destination not found" << std::endl; -#else - sif::printDebug("CFDPDistributor::handlePacket: Destination not found\n"); -#endif /* !FSFW_CPP_OSTREAM_ENABLED == 1 */ -#endif - } - - if (tcStatus != RETURN_OK) { - return this->queueMap.end(); - } else { - return queueMapIt; - } -} - -ReturnValue_t CFDPDistributor::registerHandler(AcceptsTelecommandsIF* handler) { - uint16_t handlerId = - handler->getIdentifier(); // should be 0, because CFDPHandler does not set a set a service-ID -#if FSFW_CFDP_DISTRIBUTOR_DEBUGGING == 1 -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::info << "CFDPDistributor::registerHandler: Handler ID: " << static_cast(handlerId) - << std::endl; -#else - sif::printInfo("CFDPDistributor::registerHandler: Handler ID: %d\n", static_cast(handlerId)); -#endif -#endif - MessageQueueId_t queue = handler->getRequestQueue(); - auto returnPair = queueMap.emplace(handlerId, queue); - if (not returnPair.second) { -#if FSFW_VERBOSE_LEVEL >= 1 -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "CFDPDistributor::registerHandler: Service ID already" - " exists in map" - << std::endl; -#else - sif::printError("CFDPDistributor::registerHandler: Service ID already exists in map\n"); -#endif -#endif - return SERVICE_ID_ALREADY_EXISTS; - } - return HasReturnvaluesIF::RETURN_OK; -} - -MessageQueueId_t CFDPDistributor::getRequestQueue() { return tcQueue->getId(); } - -// ReturnValue_t CFDPDistributor::callbackAfterSending(ReturnValue_t queueStatus) { -// if (queueStatus != RETURN_OK) { -// tcStatus = queueStatus; -// } -// if (tcStatus != RETURN_OK) { -// this->verifyChannel.sendFailureReport(tc_verification::ACCEPTANCE_FAILURE, -// currentPacket, tcStatus); -// // A failed packet is deleted immediately after reporting, -// // otherwise it will block memory. -// currentPacket->deletePacket(); -// return RETURN_FAILED; -// } else { -// this->verifyChannel.sendSuccessReport(tc_verification::ACCEPTANCE_SUCCESS, -// currentPacket); -// return RETURN_OK; -// } -// } - -uint16_t CFDPDistributor::getIdentifier() { return this->apid; } - -ReturnValue_t CFDPDistributor::initialize() { - currentPacket = new CFDPPacketStored(); - if (currentPacket == nullptr) { - // Should not happen, memory allocation failed! - return ObjectManagerIF::CHILD_INIT_FAILED; - } - - CCSDSDistributorIF* ccsdsDistributor = - ObjectManager::instance()->get(packetSource); - if (ccsdsDistributor == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "CFDPDistributor::initialize: Packet source invalid" << std::endl; - sif::error << " Make sure it exists and implements CCSDSDistributorIF!" << std::endl; -#else - sif::printError("CFDPDistributor::initialize: Packet source invalid\n"); - sif::printError("Make sure it exists and implements CCSDSDistributorIF\n"); -#endif - return RETURN_FAILED; - } - return ccsdsDistributor->registerApplication(this); -} diff --git a/src/fsfw/tcdistribution/CFDPDistributor.h b/src/fsfw/tcdistribution/CFDPDistributor.h deleted file mode 100644 index 2a901021..00000000 --- a/src/fsfw/tcdistribution/CFDPDistributor.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef FSFW_TCDISTRIBUTION_CFDPDISTRIBUTOR_H_ -#define FSFW_TCDISTRIBUTION_CFDPDISTRIBUTOR_H_ - -#include - -#include "../returnvalues/HasReturnvaluesIF.h" -#include "../tmtcpacket/cfdp/CFDPPacketStored.h" -#include "../tmtcservices/AcceptsTelecommandsIF.h" -#include "../tmtcservices/VerificationReporter.h" -#include "CFDPDistributorIF.h" -#include "TcDistributor.h" - -/** - * This class accepts CFDP Telecommands and forwards them to Application - * services. - * @ingroup tc_distribution - */ -class CFDPDistributor : public TcDistributor, - public CFDPDistributorIF, - public AcceptsTelecommandsIF { - public: - /** - * The ctor passes @c set_apid to the checker class and calls the - * TcDistribution ctor with a certain object id. - * @param setApid The APID of this receiving Application. - * @param setObjectId Object ID of the distributor itself - * @param setPacketSource Object ID of the source of TC packets. - * Must implement CCSDSDistributorIF. - */ - CFDPDistributor(uint16_t setApid, object_id_t setObjectId, object_id_t setPacketSource); - /** - * The destructor is empty. - */ - virtual ~CFDPDistributor(); - ReturnValue_t registerHandler(AcceptsTelecommandsIF* handler) override; - MessageQueueId_t getRequestQueue() override; - ReturnValue_t initialize() override; - uint16_t getIdentifier() override; - - protected: - uint16_t apid; - /** - * The currently handled packet is stored here. - */ - CFDPPacketStored* currentPacket = nullptr; - TcPacketCheckCFDP checker; - /** - * With this variable, the current check status is stored to generate - * acceptance messages later. - */ - ReturnValue_t tcStatus; - - const object_id_t packetSource; - - /** - * This method reads the packet service, checks if such a service is - * registered and forwards the packet to the destination. - * It also initiates the formal packet check and sending of verification - * messages. - * @return Iterator to map entry of found service id - * or iterator to @c map.end(). - */ - TcMqMapIter selectDestination() override; - /** - * The callback here handles the generation of acceptance - * success/failure messages. - */ - // ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus) override; -}; - -#endif /* FSFW_TCDISTRIBUTION_CFDPDISTRIBUTOR_H_ */ diff --git a/src/fsfw/tcdistribution/CFDPDistributorIF.h b/src/fsfw/tcdistribution/CFDPDistributorIF.h deleted file mode 100644 index 3c1836f1..00000000 --- a/src/fsfw/tcdistribution/CFDPDistributorIF.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef FSFW_TCDISTRIBUTION_CFDPDISTRIBUTORIF_H_ -#define FSFW_TCDISTRIBUTION_CFDPDISTRIBUTORIF_H_ - -#include "../ipc/MessageQueueSenderIF.h" -#include "../tmtcservices/AcceptsTelecommandsIF.h" - -/** - * This interface allows CFDP Services to register themselves at a CFDP Distributor. - * @ingroup tc_distribution - */ -class CFDPDistributorIF { - public: - /** - * The empty virtual destructor. - */ - virtual ~CFDPDistributorIF() {} - /** - * With this method, Handlers can register themselves at the CFDP Distributor. - * @param handler A pointer to the registering Handler. - * @return - @c RETURN_OK on success, - * - @c RETURN_FAILED on failure. - */ - virtual ReturnValue_t registerHandler(AcceptsTelecommandsIF* handler) = 0; -}; - -#endif /* FSFW_TCDISTRIBUTION_CFDPDISTRIBUTORIF_H_ */ diff --git a/src/fsfw/tcdistribution/CMakeLists.txt b/src/fsfw/tcdistribution/CMakeLists.txt index 7118c38c..bcad563a 100644 --- a/src/fsfw/tcdistribution/CMakeLists.txt +++ b/src/fsfw/tcdistribution/CMakeLists.txt @@ -1,9 +1,4 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - CCSDSDistributor.cpp - PUSDistributor.cpp - TcDistributor.cpp - TcPacketCheckPUS.cpp - TcPacketCheckCFDP.cpp - CFDPDistributor.cpp -) - +target_sources( + ${LIB_FSFW_NAME} + PRIVATE CcsdsDistributor.cpp PusDistributor.cpp TcDistributorBase.cpp + PusPacketChecker.cpp TcPacketCheckCFDP.cpp CcsdsPacketChecker.cpp) diff --git a/src/fsfw/tcdistribution/CcsdsDistributor.cpp b/src/fsfw/tcdistribution/CcsdsDistributor.cpp new file mode 100644 index 00000000..4668a3bc --- /dev/null +++ b/src/fsfw/tcdistribution/CcsdsDistributor.cpp @@ -0,0 +1,194 @@ +#include "fsfw/tcdistribution/CcsdsDistributor.h" + +#include "definitions.h" +#include "fsfw/FSFW.h" +#include "fsfw/objectmanager/ObjectManager.h" +#include "fsfw/serviceinterface/ServiceInterface.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" + +#define CCSDS_DISTRIBUTOR_DEBUGGING 0 + +CcsdsDistributor::CcsdsDistributor(uint16_t setDefaultApid, object_id_t setObjectId, + StorageManagerIF* tcStore, MessageQueueIF* queue, + CcsdsPacketCheckIF* packetChecker) + : TcDistributorBase(setObjectId, queue), + defaultApid(setDefaultApid), + tcStore(tcStore), + packetChecker(packetChecker) {} + +CcsdsDistributor::~CcsdsDistributor() { + if (ownedPacketChecker) { + delete packetChecker; + } +} + +ReturnValue_t CcsdsDistributor::selectDestination(MessageQueueId_t& destId) { +#if CCSDS_DISTRIBUTOR_DEBUGGING == 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::debug << "CCSDSDistributor::selectDestination received: " + << this->currentMessage.getStorageId().poolIndex << ", " + << this->currentMessage.getStorageId().packetIndex << std::endl; +#else + sif::printDebug("CCSDSDistributor::selectDestination received: %d, %d\n", + currentMessage.getStorageId().poolIndex, + currentMessage.getStorageId().packetIndex); +#endif +#endif + auto accessorPair = tcStore->getData(currentMessage.getStorageId()); + ReturnValue_t result = accessorPair.first; + if (result != returnvalue::OK) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "CCSDSDistributor::selectDestination: Getting data from" + " store failed!" + << std::endl; +#else + sif::printError( + "CCSDSDistributor::selectDestination: Getting data from" + " store failed!\n"); +#endif +#endif + return result; + } + // Minimum length of a space packet + if (accessorPair.second.size() < ccsds::HEADER_LEN + 1) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << __func__ << ": SP with length" << accessorPair.second.size() << " too short" + << std::endl; +#else + sif::printError("%s: SP with length %d too short\n", __func__, accessorPair.second.size()); +#endif +#endif + return SerializeIF::STREAM_TOO_SHORT; + } + SpacePacketReader currentPacket(accessorPair.second.data(), accessorPair.second.size()); + result = packetChecker->checkPacket(currentPacket, accessorPair.second.size()); + if (result != returnvalue::OK) { + handlePacketCheckFailure(result); + return result; + } +#if FSFW_CPP_OSTREAM_ENABLED == 1 && CCSDS_DISTRIBUTOR_DEBUGGING == 1 + sif::info << "CCSDSDistributor::selectDestination has packet with APID 0x" << std::hex + << currentPacket.getApid() << std::dec << std::endl; +#endif + auto iter = receiverMap.find(currentPacket.getApid()); + if (iter != receiverMap.end()) { + destId = iter->second.destId; + } else if (iter == receiverMap.end()) { + // The APID was not found. Forward packet to main SW-APID anyway to + // create acceptance failure report. + iter = receiverMap.find(defaultApid); + if (iter != receiverMap.end()) { + destId = iter->second.destId; + } else { + return DESTINATION_NOT_FOUND; + } + } + if (iter->second.removeHeader) { + // Do not call accessor release method here to ensure the old packet gets deleted. + return handleCcsdsHeaderRemoval(accessorPair.second); + } + accessorPair.second.release(); + return returnvalue::OK; +} + +void CcsdsDistributor::handlePacketCheckFailure(ReturnValue_t result) { +#if FSFW_VERBOSE_LEVEL >= 1 + const char* reason = "Unknown reason"; + if (result == tmtcdistrib::INVALID_CCSDS_VERSION) { + reason = "Invalid CCSDS version"; + } else if (result == tmtcdistrib::INCOMPLETE_PACKET) { + reason = "Size missmatch between CCSDS data length and packet length"; + } else if (result == tmtcdistrib::INVALID_APID) { + reason = "No valid handler APID found"; + } else if (result == tmtcdistrib::INVALID_PACKET_TYPE) { + reason = "Invalid Packet Type TM detected"; + } +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "CCSDS packet check failed: " << reason << std::endl; +#else + sif::printWarning("CCSDS packet check failed: %s\n", reason); +#endif +#endif +} + +MessageQueueId_t CcsdsDistributor::getRequestQueue() const { return tcQueue->getId(); } + +ReturnValue_t CcsdsDistributor::registerApplication(DestInfo info) { + ReturnValue_t returnValue = returnvalue::OK; + auto insertPair = receiverMap.emplace(info.apid, info); + if (not insertPair.second) { + returnValue = returnvalue::FAILED; + } + return returnValue; +} + +uint32_t CcsdsDistributor::getIdentifier() const { return 0; } + +ReturnValue_t CcsdsDistributor::initialize() { + ReturnValue_t result = TcDistributorBase::initialize(); + if (result != returnvalue::OK) { + return result; + } + if (packetChecker == nullptr) { + ownedPacketChecker = true; + packetChecker = new CcsdsPacketChecker(ccsds::PacketType::TC); + } + if (tcStore == nullptr) { + tcStore = ObjectManager::instance()->get(objects::TC_STORE); + if (tcStore == nullptr) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "CCSDSDistributor::initialize: Could not initialize" + " TC store!" + << std::endl; +#else + sif::printError( + "CCSDSDistributor::initialize: Could not initialize" + " TC store!\n"); +#endif +#endif + return ObjectManagerIF::CHILD_INIT_FAILED; + } + } + return result; +} + +ReturnValue_t CcsdsDistributor::callbackAfterSending(ReturnValue_t queueStatus) { + if (queueStatus != returnvalue::OK) { + tcStore->deleteData(currentMessage.getStorageId()); + } + return returnvalue::OK; +} + +void CcsdsDistributor::print() { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::debug << "Distributor content is: " << std::endl << "ID\t| Message Queue ID" << std::endl; + sif::debug << std::setfill('0') << std::setw(8) << std::hex; + for (const auto& iter : receiverMap) { + sif::debug << iter.first << "\t| 0x" << iter.second.destId + << ", Header Removed: " << std::boolalpha << iter.second.removeHeader << std::endl; + } + sif::debug << std::setfill(' ') << std::dec; +#endif +} + +const char* CcsdsDistributor::getName() const { return "CCSDS Distributor"; } + +ReturnValue_t CcsdsDistributor::handleCcsdsHeaderRemoval(ConstStorageAccessor& accessor) { + store_address_t newStoreId; + ReturnValue_t result = tcStore->addData(&newStoreId, accessor.data() + ccsds::HEADER_LEN, + accessor.size() - ccsds::HEADER_LEN); + if (result != returnvalue::OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << __func__ << ": TC store full" << std::endl; +#else + sif::printError("%s: TC store full\n", __func__); +#endif + return result; + } + currentMessage.setStorageId(newStoreId); + // The const accessor will delete the old data automatically + return returnvalue::OK; +} diff --git a/src/fsfw/tcdistribution/CcsdsDistributor.h b/src/fsfw/tcdistribution/CcsdsDistributor.h new file mode 100644 index 00000000..83199646 --- /dev/null +++ b/src/fsfw/tcdistribution/CcsdsDistributor.h @@ -0,0 +1,85 @@ +#ifndef FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_ +#define FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_ + +#include + +#include "fsfw/objectmanager/ObjectManagerIF.h" +#include "fsfw/storagemanager/StorageManagerIF.h" +#include "fsfw/tcdistribution/CcsdsDistributorIF.h" +#include "fsfw/tcdistribution/CcsdsPacketChecker.h" +#include "fsfw/tcdistribution/TcDistributorBase.h" +#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h" + +/** + * @brief An instantiation of the CcsdsDistributorIF. + * @details + * It receives Space Packets, and selects a destination depending on the + * APID of the telecommands. + * The Secondary Header (with Service/Subservice) is ignored. + * @ingroup tc_distribution + */ +class CcsdsDistributor : public TcDistributorBase, + public CcsdsDistributorIF, + public AcceptsTelecommandsIF { + public: + /** + * @brief The constructor sets the default APID and calls the + * TcDistributor ctor with a certain object id. + * @details + * @c tcStore is set in the @c initialize method. + * @param unknownApid The default APID, where packets with unknown + * destination are sent to. + */ + CcsdsDistributor(uint16_t unknownApid, object_id_t setObjectId, + StorageManagerIF* tcStore = nullptr, MessageQueueIF* msgQueue = nullptr, + CcsdsPacketCheckIF* packetChecker = nullptr); + /** + * The destructor is empty. + */ + ~CcsdsDistributor() override; + + [[nodiscard]] MessageQueueId_t getRequestQueue() const override; + ReturnValue_t registerApplication(DestInfo info) override; + [[nodiscard]] uint32_t getIdentifier() const override; + ReturnValue_t initialize() override; + [[nodiscard]] const char* getName() const override; + + protected: + using CcsdsReceiverMap = std::map; + CcsdsReceiverMap receiverMap; + + /** + * This implementation checks if an application with fitting APID has + * registered and forwards the packet to the according message queue. + * If the packet is not found, it returns the queue to @c defaultApid, + * where a Acceptance Failure message should be generated. + * @return + * - @c RETURN_OK if a valid desintation was found, error code otherwise + * - @c SerializeIF::STREAM_TOO_SHORT: Packet too short to be a space packet + */ + ReturnValue_t selectDestination(MessageQueueId_t& destId) override; + /** + * The callback here handles the generation of acceptance + * success/failure messages. + */ + ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus) override; + + static void handlePacketCheckFailure(ReturnValue_t result); + + ReturnValue_t handleCcsdsHeaderRemoval(ConstStorageAccessor& accessor); + void print(); + /** + * The default APID, where packets with unknown APID are sent to. + */ + uint16_t defaultApid; + /** + * A reference to the TC storage must be maintained, as this class handles + * pure Space Packets and there exists no SpacePacketStored class. + */ + StorageManagerIF* tcStore = nullptr; + + bool ownedPacketChecker = false; + CcsdsPacketCheckIF* packetChecker = nullptr; +}; + +#endif /* FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_ */ diff --git a/src/fsfw/tcdistribution/CcsdsDistributorIF.h b/src/fsfw/tcdistribution/CcsdsDistributorIF.h new file mode 100644 index 00000000..f70a2ef9 --- /dev/null +++ b/src/fsfw/tcdistribution/CcsdsDistributorIF.h @@ -0,0 +1,54 @@ +#ifndef FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_ +#define FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_ + +#include "fsfw/ipc/MessageQueueSenderIF.h" +#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h" + +/** + * This is the Interface to a CCSDS Distributor. + * On a CCSDS Distributor, Applications (in terms of CCSDS) may register + * themselves, either by passing a pointer to themselves (and implementing the + * CCSDSApplicationIF), or by explicitly passing an APID and a MessageQueueId + * to route the TC's to. + * @ingroup tc_distribution + */ +class CcsdsDistributorIF { + public: + struct DestInfo { + DestInfo(const char* name, uint16_t apid, MessageQueueId_t destId, bool removeHeader) + : name(name), apid(apid), destId(destId), removeHeader(removeHeader) {} + DestInfo(const AcceptsTelecommandsIF& ccsdsReceiver, bool removeHeader_) + : name(ccsdsReceiver.getName()) { + apid = ccsdsReceiver.getIdentifier(); + destId = ccsdsReceiver.getRequestQueue(); + removeHeader = removeHeader_; + } + const char* name; + uint16_t apid; + MessageQueueId_t destId; + bool removeHeader; + }; + + /** + * With this call, other Applications can register to the CCSDS distributor. + * This is done by passing an APID and a MessageQueueId to the method. + * @param info Contains all necessary info to register an application. + * @return + * - @c RETURN_OK on success, + * - @c RETURN_FAILED or tmtcdistrib error code on failure. + * - @c tmtcdistrib::INVALID_CCSDS_VERSION + * - @c tmtcdistrib::INVALID_APID No APID available to handle this packet + * - @c tmtcdistrib::INVALID_PACKET_TYPE Packet type TM detected + * - @c tmtcdistrib::INCORRECT_PRIMARY_HEADER Something other wrong with primary header + * - @c tmtcdistrib::INCOMPLETE_PACKET Size missmatch between data length field and actual + * length + */ + virtual ReturnValue_t registerApplication(DestInfo info) = 0; + + /** + * The empty virtual destructor. + */ + virtual ~CcsdsDistributorIF() = default; +}; + +#endif /* FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_ */ diff --git a/src/fsfw/tcdistribution/TcPacketCheckIF.h b/src/fsfw/tcdistribution/CcsdsPacketCheckIF.h similarity index 55% rename from src/fsfw/tcdistribution/TcPacketCheckIF.h rename to src/fsfw/tcdistribution/CcsdsPacketCheckIF.h index 858c3093..251203d4 100644 --- a/src/fsfw/tcdistribution/TcPacketCheckIF.h +++ b/src/fsfw/tcdistribution/CcsdsPacketCheckIF.h @@ -1,30 +1,32 @@ #ifndef FSFW_TCDISTRIBUTION_TCPACKETCHECKIF_H_ #define FSFW_TCDISTRIBUTION_TCPACKETCHECKIF_H_ -#include "../returnvalues/HasReturnvaluesIF.h" +#include -class SpacePacketBase; +#include "fsfw/returnvalues/returnvalue.h" + +class SpacePacketReader; /** * This interface is used by PacketCheckers for PUS packets and CFDP packets . * @ingroup tc_distribution */ -class TcPacketCheckIF { +class CcsdsPacketCheckIF { public: /** * The empty virtual destructor. */ - virtual ~TcPacketCheckIF() {} + virtual ~CcsdsPacketCheckIF() = default; /** * This is the actual method to formally check a certain Packet. * The packet's Application Data can not be checked here. * @param current_packet The packet to check - * @return - @c RETURN_OK on success. - * - @c INCORRECT_CHECKSUM if checksum is invalid. - * - @c ILLEGAL_APID if APID does not match. + * @return - @c returnvalue::OK on success. + * - @c INCORRECT_CHECKSUM if checksum is invalid. + * - @c ILLEGAL_APID if APID does not match. */ - virtual ReturnValue_t checkPacket(SpacePacketBase* currentPacket) = 0; + virtual ReturnValue_t checkPacket(const SpacePacketReader& currentPacket, size_t packetLen) = 0; }; #endif /* FSFW_TCDISTRIBUTION_TCPACKETCHECKIF_H_ */ diff --git a/src/fsfw/tcdistribution/CcsdsPacketChecker.cpp b/src/fsfw/tcdistribution/CcsdsPacketChecker.cpp new file mode 100644 index 00000000..977a90a2 --- /dev/null +++ b/src/fsfw/tcdistribution/CcsdsPacketChecker.cpp @@ -0,0 +1,33 @@ +#include "CcsdsPacketChecker.h" + +#include "fsfw/tcdistribution/definitions.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" + +CcsdsPacketChecker::CcsdsPacketChecker(ccsds::PacketType packetType_, uint8_t ccsdsVersion_) + : packetType(packetType_), ccsdsVersion(ccsdsVersion_) {} + +ReturnValue_t CcsdsPacketChecker::checkPacket(const SpacePacketReader& currentPacket, + size_t packetLen) { + if (checkApid) { + if (currentPacket.getApid() != apid) { + return tmtcdistrib::INVALID_APID; + } + } + + if (currentPacket.getVersion() != ccsdsVersion) { + return tmtcdistrib::INVALID_CCSDS_VERSION; + } + if (currentPacket.getPacketType() != packetType) { + return tmtcdistrib::INVALID_PACKET_TYPE; + } + // This assumes that the getFullPacketLen version uses the space packet data length field + if (currentPacket.getFullPacketLen() != packetLen) { + return tmtcdistrib::INCOMPLETE_PACKET; + } + return returnvalue::OK; +} + +void CcsdsPacketChecker::setApidToCheck(uint16_t apid_) { + apid = apid_; + checkApid = true; +} diff --git a/src/fsfw/tcdistribution/CcsdsPacketChecker.h b/src/fsfw/tcdistribution/CcsdsPacketChecker.h new file mode 100644 index 00000000..7def030d --- /dev/null +++ b/src/fsfw/tcdistribution/CcsdsPacketChecker.h @@ -0,0 +1,20 @@ +#ifndef FSFW_TESTS_CCSDSPACKETCHECKERBASE_H +#define FSFW_TESTS_CCSDSPACKETCHECKERBASE_H + +#include "CcsdsPacketCheckIF.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketIF.h" + +class CcsdsPacketChecker : public CcsdsPacketCheckIF { + public: + CcsdsPacketChecker(ccsds::PacketType packetType, uint8_t ccsdsVersion = 0b000); + + void setApidToCheck(uint16_t apid); + ReturnValue_t checkPacket(const SpacePacketReader& currentPacket, size_t packetLen) override; + + protected: + bool checkApid = false; + uint16_t apid = 0; + ccsds::PacketType packetType; + uint8_t ccsdsVersion; +}; +#endif // FSFW_TESTS_CCSDSPACKETCHECKERBASE_H diff --git a/src/fsfw/tcdistribution/TcPacketCheckCFDP.h b/src/fsfw/tcdistribution/CfdpPacketChecker.h similarity index 65% rename from src/fsfw/tcdistribution/TcPacketCheckCFDP.h rename to src/fsfw/tcdistribution/CfdpPacketChecker.h index 3fe281d1..b1d46ae4 100644 --- a/src/fsfw/tcdistribution/TcPacketCheckCFDP.h +++ b/src/fsfw/tcdistribution/CfdpPacketChecker.h @@ -1,16 +1,16 @@ #ifndef FSFW_TCDISTRIBUTION_TCPACKETCHECKCFDP_H_ #define FSFW_TCDISTRIBUTION_TCPACKETCHECKCFDP_H_ -#include "TcPacketCheckIF.h" +#include "CcsdsPacketCheckIF.h" #include "fsfw/FSFW.h" -class CFDPPacketStored; +class CfdpPacketStored; /** * This class performs a formal packet check for incoming CFDP Packets. * @ingroup tc_distribution */ -class TcPacketCheckCFDP : public TcPacketCheckIF, public HasReturnvaluesIF { +class CfdpPacketChecker : public CcsdsPacketCheckIF { protected: /** * The packet id each correct packet should have. @@ -23,11 +23,11 @@ class TcPacketCheckCFDP : public TcPacketCheckIF, public HasReturnvaluesIF { * The constructor only sets the APID attribute. * @param set_apid The APID to set. */ - TcPacketCheckCFDP(uint16_t setApid); + explicit CfdpPacketChecker(uint16_t setApid); - ReturnValue_t checkPacket(SpacePacketBase* currentPacket) override; + ReturnValue_t checkPacket(const SpacePacketReader& currentPacket, size_t packetLen) override; - uint16_t getApid() const; + [[nodiscard]] uint16_t getApid() const; }; #endif /* FSFW_TCDISTRIBUTION_TCPACKETCHECKCFDP_H_ */ diff --git a/src/fsfw/tcdistribution/PUSDistributor.cpp b/src/fsfw/tcdistribution/PUSDistributor.cpp deleted file mode 100644 index aadecd69..00000000 --- a/src/fsfw/tcdistribution/PUSDistributor.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#include "fsfw/tcdistribution/PUSDistributor.h" - -#include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tcdistribution/CCSDSDistributorIF.h" -#include "fsfw/tmtcservices/PusVerificationReport.h" - -#define PUS_DISTRIBUTOR_DEBUGGING 0 - -PUSDistributor::PUSDistributor(uint16_t setApid, object_id_t setObjectId, - object_id_t setPacketSource) - : TcDistributor(setObjectId), - checker(setApid), - verifyChannel(), - tcStatus(RETURN_FAILED), - packetSource(setPacketSource) {} - -PUSDistributor::~PUSDistributor() {} - -PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() { -#if FSFW_CPP_OSTREAM_ENABLED == 1 && PUS_DISTRIBUTOR_DEBUGGING == 1 - store_address_t storeId = this->currentMessage.getStorageId()); - sif::debug << "PUSDistributor::handlePacket received: " << storeId.poolIndex << ", " - << storeId.packetIndex << std::endl; -#endif - TcMqMapIter queueMapIt = this->queueMap.end(); - if (this->currentPacket == nullptr) { - return queueMapIt; - } - this->currentPacket->setStoreAddress(this->currentMessage.getStorageId(), currentPacket); - if (currentPacket->getWholeData() != nullptr) { - tcStatus = checker.checkPacket(currentPacket); - if (tcStatus != HasReturnvaluesIF::RETURN_OK) { -#if FSFW_VERBOSE_LEVEL >= 1 - const char* keyword = "unnamed error"; - if (tcStatus == TcPacketCheckPUS::INCORRECT_CHECKSUM) { - keyword = "checksum"; - } else if (tcStatus == TcPacketCheckPUS::INCORRECT_PRIMARY_HEADER) { - keyword = "incorrect primary header"; - } else if (tcStatus == TcPacketCheckPUS::ILLEGAL_APID) { - keyword = "illegal APID"; - } else if (tcStatus == TcPacketCheckPUS::INCORRECT_SECONDARY_HEADER) { - keyword = "incorrect secondary header"; - } else if (tcStatus == TcPacketCheckPUS::INCOMPLETE_PACKET) { - keyword = "incomplete packet"; - } -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "PUSDistributor::handlePacket: Packet format invalid, " << keyword - << " error" << std::endl; -#else - sif::printWarning( - "PUSDistributor::handlePacket: Packet format invalid, " - "%s error\n", - keyword); -#endif -#endif - } - uint32_t queue_id = currentPacket->getService(); - queueMapIt = this->queueMap.find(queue_id); - } else { - tcStatus = PACKET_LOST; - } - - if (queueMapIt == this->queueMap.end()) { - tcStatus = DESTINATION_NOT_FOUND; -#if FSFW_VERBOSE_LEVEL >= 1 -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "PUSDistributor::handlePacket: Destination not found" << std::endl; -#else - sif::printDebug("PUSDistributor::handlePacket: Destination not found\n"); -#endif /* !FSFW_CPP_OSTREAM_ENABLED == 1 */ -#endif - } - - if (tcStatus != RETURN_OK) { - return this->queueMap.end(); - } else { - return queueMapIt; - } -} - -ReturnValue_t PUSDistributor::registerService(AcceptsTelecommandsIF* service) { - uint16_t serviceId = service->getIdentifier(); -#if PUS_DISTRIBUTOR_DEBUGGING == 1 -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::info << "Service ID: " << static_cast(serviceId) << std::endl; -#else - sif::printInfo("Service ID: %d\n", static_cast(serviceId)); -#endif -#endif - MessageQueueId_t queue = service->getRequestQueue(); - auto returnPair = queueMap.emplace(serviceId, queue); - if (not returnPair.second) { -#if FSFW_VERBOSE_LEVEL >= 1 -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PUSDistributor::registerService: Service ID already" - " exists in map" - << std::endl; -#else - sif::printError("PUSDistributor::registerService: Service ID already exists in map\n"); -#endif -#endif - return SERVICE_ID_ALREADY_EXISTS; - } - return HasReturnvaluesIF::RETURN_OK; -} - -MessageQueueId_t PUSDistributor::getRequestQueue() { return tcQueue->getId(); } - -ReturnValue_t PUSDistributor::callbackAfterSending(ReturnValue_t queueStatus) { - if (queueStatus != RETURN_OK) { - tcStatus = queueStatus; - } - if (tcStatus != RETURN_OK) { - this->verifyChannel.sendFailureReport(tc_verification::ACCEPTANCE_FAILURE, currentPacket, - tcStatus); - // A failed packet is deleted immediately after reporting, - // otherwise it will block memory. - currentPacket->deletePacket(); - return RETURN_FAILED; - } else { - this->verifyChannel.sendSuccessReport(tc_verification::ACCEPTANCE_SUCCESS, currentPacket); - return RETURN_OK; - } -} - -uint16_t PUSDistributor::getIdentifier() { return checker.getApid(); } - -ReturnValue_t PUSDistributor::initialize() { - currentPacket = new TcPacketStoredPus(); - if (currentPacket == nullptr) { - // Should not happen, memory allocation failed! - return ObjectManagerIF::CHILD_INIT_FAILED; - } - - CCSDSDistributorIF* ccsdsDistributor = - ObjectManager::instance()->get(packetSource); - if (ccsdsDistributor == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PUSDistributor::initialize: Packet source invalid" << std::endl; - sif::error << " Make sure it exists and implements CCSDSDistributorIF!" << std::endl; -#else - sif::printError("PUSDistributor::initialize: Packet source invalid\n"); - sif::printError("Make sure it exists and implements CCSDSDistributorIF\n"); -#endif - return RETURN_FAILED; - } - return ccsdsDistributor->registerApplication(this); -} diff --git a/src/fsfw/tcdistribution/PusDistributor.cpp b/src/fsfw/tcdistribution/PusDistributor.cpp new file mode 100644 index 00000000..7599114b --- /dev/null +++ b/src/fsfw/tcdistribution/PusDistributor.cpp @@ -0,0 +1,167 @@ +#include "fsfw/tcdistribution/PusDistributor.h" + +#include "definitions.h" +#include "fsfw/objectmanager/ObjectManager.h" +#include "fsfw/serviceinterface/ServiceInterface.h" +#include "fsfw/tcdistribution/CcsdsDistributorIF.h" +#include "fsfw/tmtcservices/PusVerificationReport.h" + +#define PUS_DISTRIBUTOR_DEBUGGING 0 + +PusDistributor::PusDistributor(uint16_t setApid, object_id_t setObjectId, + CcsdsDistributorIF* distributor, StorageManagerIF* store_) + : TcDistributorBase(setObjectId), + store(store_), + checker(setApid, ccsds::PacketType::TC), + ccsdsDistributor(distributor), + tcStatus(returnvalue::FAILED) {} + +PusDistributor::~PusDistributor() = default; + +ReturnValue_t PusDistributor::selectDestination(MessageQueueId_t& destId) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 && PUS_DISTRIBUTOR_DEBUGGING == 1 + store_address_t storeId = currentMessage.getStorageId(); + sif::debug << "PUSDistributor::handlePacket received: " << storeId.poolIndex << ", " + << storeId.packetIndex << std::endl; +#endif + // TODO: Need to set the data + const uint8_t* packetPtr = nullptr; + size_t packetLen = 0; + ReturnValue_t result = + store->getData(currentMessage.getStorageId(), &packetPtr, &packetLen) != returnvalue::OK; + if (result != returnvalue::OK) { + tcStatus = PACKET_LOST; + return result; + } + result = reader.setReadOnlyData(packetPtr, packetLen); + if (result != returnvalue::OK) { + tcStatus = PACKET_LOST; + return result; + } + // CRC check done by checker + result = reader.parseDataWithoutCrcCheck(); + if (result != returnvalue::OK) { + tcStatus = PACKET_LOST; + return result; + } + + if (reader.getFullData() != nullptr) { + tcStatus = checker.checkPacket(reader, reader.getFullPacketLen()); + if (tcStatus != returnvalue::OK) { + checkerFailurePrinter(); + } + uint8_t pusId = reader.getService(); + auto iter = receiverMap.find(pusId); + if (iter == receiverMap.end()) { + tcStatus = DESTINATION_NOT_FOUND; +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::debug << "PUSDistributor::handlePacket: Destination not found" << std::endl; +#else + sif::printDebug("PUSDistributor::handlePacket: Destination not found\n"); +#endif /* !FSFW_CPP_OSTREAM_ENABLED == 1 */ +#endif + } + destId = iter->second.destId; + } else { + tcStatus = PACKET_LOST; + } + return tcStatus; +} + +ReturnValue_t PusDistributor::registerService(const AcceptsTelecommandsIF& service) { + uint16_t serviceId = service.getIdentifier(); +#if PUS_DISTRIBUTOR_DEBUGGING == 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "Service ID: " << static_cast(serviceId) << std::endl; +#else + sif::printInfo("Service ID: %d\n", static_cast(serviceId)); +#endif +#endif + MessageQueueId_t queue = service.getRequestQueue(); + auto returnPair = receiverMap.emplace(serviceId, ServiceInfo(service.getName(), queue)); + if (not returnPair.second) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "PUSDistributor::registerService: Service ID already" + " exists in map" + << std::endl; +#else + sif::printError("PUSDistributor::registerService: Service ID already exists in map\n"); +#endif +#endif + return SERVICE_ID_ALREADY_EXISTS; + } + return returnvalue::OK; +} + +MessageQueueId_t PusDistributor::getRequestQueue() const { return tcQueue->getId(); } + +ReturnValue_t PusDistributor::callbackAfterSending(ReturnValue_t queueStatus) { + if (queueStatus != returnvalue::OK) { + tcStatus = queueStatus; + } + if (tcStatus != returnvalue::OK) { + verifyChannel->sendFailureReport({tcverif::ACCEPTANCE_FAILURE, reader, tcStatus}); + // A failed packet is deleted immediately after reporting, + // otherwise it will block memory. + store->deleteData(currentMessage.getStorageId()); + return returnvalue::FAILED; + } else { + verifyChannel->sendSuccessReport({tcverif::ACCEPTANCE_SUCCESS, reader}); + return returnvalue::OK; + } +} + +uint32_t PusDistributor::getIdentifier() const { return checker.getApid(); } + +ReturnValue_t PusDistributor::initialize() { + if (store == nullptr) { + store = ObjectManager::instance()->get(objects::TC_STORE); + if (store == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + } + if (ccsdsDistributor == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "PUSDistributor::initialize: Packet source invalid" << std::endl; + sif::error << " Make sure it exists and implements CCSDSDistributorIF!" << std::endl; +#else + sif::printError("PusDistributor::initialize: Packet source invalid\n"); + sif::printError("Make sure it exists and implements CcsdsDistributorIF\n"); +#endif + return ObjectManagerIF::CHILD_INIT_FAILED; + } + if (verifyChannel == nullptr) { + verifyChannel = + ObjectManager::instance()->get(objects::VERIFICATION_REPORTER); + if (verifyChannel == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + } + return ccsdsDistributor->registerApplication(CcsdsDistributorIF::DestInfo(*this, false)); +} + +void PusDistributor::checkerFailurePrinter() const { +#if FSFW_VERBOSE_LEVEL >= 1 + const char* reason = "Unknown reason"; + if (tcStatus == tmtcdistrib::INCORRECT_CHECKSUM) { + reason = "Checksum Error"; + } else if (tcStatus == tmtcdistrib::INCORRECT_PRIMARY_HEADER) { + reason = "Incorrect Primary Header"; + } else if (tcStatus == tmtcdistrib::INVALID_APID) { + reason = "Illegal APID"; + } else if (tcStatus == tmtcdistrib::INCORRECT_SECONDARY_HEADER) { + reason = "Incorrect Secondary Header"; + } else if (tcStatus == tmtcdistrib::INCOMPLETE_PACKET) { + reason = "Incomplete packet"; + } +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "PUSDistributor::handlePacket: Check failed: " << reason << std::endl; +#else + sif::printWarning("PUSDistributor::handlePacket: Check failed: %s\n", reason); +#endif +#endif +} + +const char* PusDistributor::getName() const { return "PUS Distributor"; } diff --git a/src/fsfw/tcdistribution/PUSDistributor.h b/src/fsfw/tcdistribution/PusDistributor.h similarity index 54% rename from src/fsfw/tcdistribution/PUSDistributor.h rename to src/fsfw/tcdistribution/PusDistributor.h index c069c81b..206f112a 100644 --- a/src/fsfw/tcdistribution/PUSDistributor.h +++ b/src/fsfw/tcdistribution/PusDistributor.h @@ -1,21 +1,27 @@ #ifndef FSFW_TCDISTRIBUTION_PUSDISTRIBUTOR_H_ #define FSFW_TCDISTRIBUTION_PUSDISTRIBUTOR_H_ -#include "PUSDistributorIF.h" -#include "TcDistributor.h" -#include "TcPacketCheckPUS.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include + +#include "PusDistributorIF.h" +#include "PusPacketChecker.h" +#include "TcDistributorBase.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/tmtcpacket/pus/tc.h" #include "fsfw/tmtcservices/AcceptsTelecommandsIF.h" #include "fsfw/tmtcservices/VerificationReporter.h" +class CcsdsDistributorIF; + /** * This class accepts PUS Telecommands and forwards them to Application * services. In addition, the class performs a formal packet check and * sends acceptance success or failure messages. * @ingroup tc_distribution */ -class PUSDistributor : public TcDistributor, public PUSDistributorIF, public AcceptsTelecommandsIF { +class PusDistributor : public TcDistributorBase, + public PusDistributorIF, + public AcceptsTelecommandsIF { public: /** * The ctor passes @c set_apid to the checker class and calls the @@ -23,32 +29,44 @@ class PUSDistributor : public TcDistributor, public PUSDistributorIF, public Acc * @param setApid The APID of this receiving Application. * @param setObjectId Object ID of the distributor itself * @param setPacketSource Object ID of the source of TC packets. - * Must implement CCSDSDistributorIF. + * Must implement CcsdsDistributorIF. */ - PUSDistributor(uint16_t setApid, object_id_t setObjectId, object_id_t setPacketSource); + PusDistributor(uint16_t setApid, object_id_t setObjectId, CcsdsDistributorIF* packetSource, + StorageManagerIF* store = nullptr); + [[nodiscard]] const char* getName() const override; /** * The destructor is empty. */ - virtual ~PUSDistributor(); - ReturnValue_t registerService(AcceptsTelecommandsIF* service) override; - MessageQueueId_t getRequestQueue() override; + ~PusDistributor() override; + ReturnValue_t registerService(const AcceptsTelecommandsIF& service) override; + [[nodiscard]] MessageQueueId_t getRequestQueue() const override; ReturnValue_t initialize() override; - uint16_t getIdentifier() override; + [[nodiscard]] uint32_t getIdentifier() const override; protected: + struct ServiceInfo { + ServiceInfo(const char* name, MessageQueueId_t destId) : name(name), destId(destId) {} + + const char* name; + MessageQueueId_t destId; + }; + /// PUS recipient map. The key value will generally be the PUS Service + using PusReceiverMap = std::map; + + PusReceiverMap receiverMap; + StorageManagerIF* store; /** * This attribute contains the class, that performs a formal packet check. */ - TcPacketCheckPUS checker; + PusPacketChecker checker; /** * With this class, verification messages are sent to the * TC Verification service. */ - VerificationReporter verifyChannel; - /** - * The currently handled packet is stored here. - */ - TcPacketStoredPus* currentPacket = nullptr; + VerificationReporterIF* verifyChannel = nullptr; + //! Cached for initialization + CcsdsDistributorIF* ccsdsDistributor = nullptr; + PusTcReader reader; /** * With this variable, the current check status is stored to generate @@ -56,8 +74,6 @@ class PUSDistributor : public TcDistributor, public PUSDistributorIF, public Acc */ ReturnValue_t tcStatus; - const object_id_t packetSource; - /** * This method reads the packet service, checks if such a service is * registered and forwards the packet to the destination. @@ -66,12 +82,14 @@ class PUSDistributor : public TcDistributor, public PUSDistributorIF, public Acc * @return Iterator to map entry of found service id * or iterator to @c map.end(). */ - TcMqMapIter selectDestination() override; + ReturnValue_t selectDestination(MessageQueueId_t& destId) override; /** * The callback here handles the generation of acceptance * success/failure messages. */ ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus) override; + + void checkerFailurePrinter() const; }; #endif /* FSFW_TCDISTRIBUTION_PUSDISTRIBUTOR_H_ */ diff --git a/src/fsfw/tcdistribution/PUSDistributorIF.h b/src/fsfw/tcdistribution/PusDistributorIF.h similarity index 70% rename from src/fsfw/tcdistribution/PUSDistributorIF.h rename to src/fsfw/tcdistribution/PusDistributorIF.h index da6db283..99981939 100644 --- a/src/fsfw/tcdistribution/PUSDistributorIF.h +++ b/src/fsfw/tcdistribution/PusDistributorIF.h @@ -8,19 +8,19 @@ * This interface allows PUS Services to register themselves at a PUS Distributor. * @ingroup tc_distribution */ -class PUSDistributorIF { +class PusDistributorIF { public: /** * The empty virtual destructor. */ - virtual ~PUSDistributorIF() {} + virtual ~PusDistributorIF() = default; /** * With this method, Services can register themselves at the PUS Distributor. * @param service A pointer to the registering Service. - * @return - @c RETURN_OK on success, - * - @c RETURN_FAILED on failure. + * @return - @c returnvalue::OK on success, + * - @c returnvalue::FAILED on failure. */ - virtual ReturnValue_t registerService(AcceptsTelecommandsIF* service) = 0; + virtual ReturnValue_t registerService(const AcceptsTelecommandsIF& service) = 0; }; #endif /* FSFW_TCDISTRIBUTION_PUSDISTRIBUTORIF_H_ */ diff --git a/src/fsfw/tcdistribution/PusPacketChecker.cpp b/src/fsfw/tcdistribution/PusPacketChecker.cpp new file mode 100644 index 00000000..55a7934c --- /dev/null +++ b/src/fsfw/tcdistribution/PusPacketChecker.cpp @@ -0,0 +1,30 @@ +#include "fsfw/tcdistribution/PusPacketChecker.h" + +#include "fsfw/globalfunctions/CRC.h" +#include "fsfw/serviceinterface/ServiceInterface.h" +#include "fsfw/tcdistribution/definitions.h" +#include "fsfw/tmtcpacket/pus/tc/PusTcReader.h" + +PusPacketChecker::PusPacketChecker(uint16_t apid, ccsds::PacketType packetType_, + ecss::PusVersion pusVersion_) + : pusVersion(pusVersion_), apid(apid) {} + +ReturnValue_t PusPacketChecker::checkPacket(const PusTcReader& pusPacket, size_t packetLen) { + // Other primary header fields are checked by base class + if (not pusPacket.hasSecHeader()) { + return tmtcdistrib::INVALID_SEC_HEADER_FIELD; + } + uint16_t calculated_crc = CRC::crc16ccitt(pusPacket.getFullData(), pusPacket.getFullPacketLen()); + if (calculated_crc != 0) { + return tmtcdistrib::INCORRECT_CHECKSUM; + } + if (pusPacket.getApid() != apid) { + return tmtcdistrib::INVALID_APID; + } + if (pusPacket.getPusVersion() != pusVersion) { + return tmtcdistrib::INVALID_PUS_VERSION; + } + return returnvalue::OK; +} + +uint16_t PusPacketChecker::getApid() const { return apid; } diff --git a/src/fsfw/tcdistribution/PusPacketChecker.h b/src/fsfw/tcdistribution/PusPacketChecker.h new file mode 100644 index 00000000..249221bb --- /dev/null +++ b/src/fsfw/tcdistribution/PusPacketChecker.h @@ -0,0 +1,34 @@ +#ifndef FSFW_TCDISTRIBUTION_TCPACKETCHECKPUS_H_ +#define FSFW_TCDISTRIBUTION_TCPACKETCHECKPUS_H_ + +#include "fsfw/FSFW.h" +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/tmtcpacket/pus/defs.h" +#include "fsfw/tmtcservices/PusVerificationReport.h" + +/** + * This class performs a formal packet check for incoming PUS Telecommand Packets. + * Currently, it only checks if the APID and CRC are correct. + * @ingroup tc_distribution + */ +class PusPacketChecker { + public: + /** + * The constructor only sets the APID attribute. + * @param set_apid The APID to set. + */ + explicit PusPacketChecker(uint16_t apid, ccsds::PacketType packetType, + ecss::PusVersion = ecss::PusVersion::PUS_C); + + ReturnValue_t checkPacket(const PusTcReader& currentPacket, size_t packetLen); + + [[nodiscard]] uint16_t getApid() const; + + protected: + ecss::PusVersion pusVersion; + uint16_t apid; + + private: +}; + +#endif /* FSFW_TCDISTRIBUTION_TCPACKETCHECKPUS_H_ */ diff --git a/src/fsfw/tcdistribution/TcDistributor.cpp b/src/fsfw/tcdistribution/TcDistributor.cpp deleted file mode 100644 index a650546c..00000000 --- a/src/fsfw/tcdistribution/TcDistributor.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "fsfw/tcdistribution/TcDistributor.h" - -#include "fsfw/ipc/QueueFactory.h" -#include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tmtcservices/TmTcMessage.h" - -TcDistributor::TcDistributor(object_id_t objectId) : SystemObject(objectId) { - tcQueue = QueueFactory::instance()->createMessageQueue(DISTRIBUTER_MAX_PACKETS); -} - -TcDistributor::~TcDistributor() { QueueFactory::instance()->deleteMessageQueue(tcQueue); } - -ReturnValue_t TcDistributor::performOperation(uint8_t opCode) { - ReturnValue_t status = RETURN_OK; - for (status = tcQueue->receiveMessage(¤tMessage); status == RETURN_OK; - status = tcQueue->receiveMessage(¤tMessage)) { - status = handlePacket(); - } - if (status == MessageQueueIF::EMPTY) { - return RETURN_OK; - } else { - return status; - } -} - -ReturnValue_t TcDistributor::handlePacket() { - TcMqMapIter queueMapIt = this->selectDestination(); - ReturnValue_t returnValue = RETURN_FAILED; - if (queueMapIt != this->queueMap.end()) { - returnValue = this->tcQueue->sendMessage(queueMapIt->second, &this->currentMessage); - } - return this->callbackAfterSending(returnValue); -} - -void TcDistributor::print() { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "Distributor content is: " << std::endl << "ID\t| Message Queue ID" << std::endl; - sif::debug << std::setfill('0') << std::setw(8) << std::hex; - for (const auto& queueMapIter : queueMap) { - sif::debug << queueMapIter.first << "\t| 0x" << queueMapIter.second << std::endl; - } - sif::debug << std::setfill(' ') << std::dec; -#endif -} - -ReturnValue_t TcDistributor::callbackAfterSending(ReturnValue_t queueStatus) { return RETURN_OK; } diff --git a/src/fsfw/tcdistribution/TcDistributorBase.cpp b/src/fsfw/tcdistribution/TcDistributorBase.cpp new file mode 100644 index 00000000..a561b465 --- /dev/null +++ b/src/fsfw/tcdistribution/TcDistributorBase.cpp @@ -0,0 +1,49 @@ +#include "TcDistributorBase.h" + +#include "definitions.h" +#include "fsfw/ipc/QueueFactory.h" +#include "fsfw/tmtcservices/TmTcMessage.h" + +TcDistributorBase::TcDistributorBase(object_id_t objectId, MessageQueueIF* tcQueue_) + : SystemObject(objectId), tcQueue(tcQueue_) { + if (tcQueue == nullptr) { + ownedQueue = true; + tcQueue = QueueFactory::instance()->createMessageQueue(DISTRIBUTER_MAX_PACKETS); + } +} + +TcDistributorBase::~TcDistributorBase() { + if (ownedQueue) { + QueueFactory::instance()->deleteMessageQueue(tcQueue); + } +} + +ReturnValue_t TcDistributorBase::performOperation(uint8_t opCode) { + ReturnValue_t status; + ReturnValue_t result = returnvalue::OK; + for (status = tcQueue->receiveMessage(¤tMessage); status == returnvalue::OK; + status = tcQueue->receiveMessage(¤tMessage)) { + ReturnValue_t packetResult = handlePacket(); + if (packetResult != returnvalue::OK) { + result = packetResult; + triggerEvent(tmtcdistrib::HANDLE_PACKET_FAILED, packetResult, 1); + } + } + if (status == MessageQueueIF::EMPTY) { + return result; + } + return result; +} + +ReturnValue_t TcDistributorBase::handlePacket() { + MessageQueueId_t destId; + ReturnValue_t result = selectDestination(destId); + if (result != returnvalue::OK) { + return result; + } + return callbackAfterSending(tcQueue->sendMessage(destId, ¤tMessage)); +} + +ReturnValue_t TcDistributorBase::callbackAfterSending(ReturnValue_t queueStatus) { + return returnvalue::OK; +} diff --git a/src/fsfw/tcdistribution/TcDistributor.h b/src/fsfw/tcdistribution/TcDistributorBase.h similarity index 67% rename from src/fsfw/tcdistribution/TcDistributor.h rename to src/fsfw/tcdistribution/TcDistributorBase.h index 1b783ff4..be4c15ab 100644 --- a/src/fsfw/tcdistribution/TcDistributor.h +++ b/src/fsfw/tcdistribution/TcDistributorBase.h @@ -3,10 +3,11 @@ #include +#include "fsfw/events/Event.h" #include "fsfw/ipc/MessageQueueIF.h" #include "fsfw/objectmanager/ObjectManagerIF.h" #include "fsfw/objectmanager/SystemObject.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/storagemanager/StorageManagerIF.h" #include "fsfw/tasks/ExecutableObjectIF.h" #include "fsfw/tmtcservices/TmTcMessage.h" @@ -18,20 +19,17 @@ */ /** - * This is the base class to implement distributors for Space Packets. - * Typically, the distribution is required to forward Telecommand packets + * This is the base class to implement distributors for telecommands. + * Typically, the distribution is required to forward telecommand packets * over the satellite applications and services. The class receives - * Space Packets over a message queue and holds a map that links other - * message queue ids to some identifier. The process of unpacking the + * TC packets over a message queue and holds a map that links other + * message queue IDs to some identifier. The process of unpacking the * destination information from the packet is handled by the child class * implementations. * @ingroup tc_distribution */ -class TcDistributor : public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF { +class TcDistributorBase : public SystemObject, public ExecutableObjectIF { public: - using TcMessageQueueMap = std::map; - using TcMqMapIter = std::map::iterator; - static constexpr uint8_t INTERFACE_ID = CLASS_ID::PACKET_DISTRIBUTION; static constexpr ReturnValue_t PACKET_LOST = MAKE_RETURN_CODE(1); static constexpr ReturnValue_t DESTINATION_NOT_FOUND = MAKE_RETURN_CODE(2); @@ -43,12 +41,12 @@ class TcDistributor : public SystemObject, public ExecutableObjectIF, public Has * @param set_object_id This id is assigned to the distributor * implementation. */ - TcDistributor(object_id_t objectId); + explicit TcDistributorBase(object_id_t objectId, MessageQueueIF* tcQueue = nullptr); /** * The destructor is empty, the message queues are not in the vicinity of * this class. */ - virtual ~TcDistributor(); + ~TcDistributorBase() override; /** * The method is called cyclically and fetches new incoming packets from * the message queue. @@ -56,14 +54,10 @@ class TcDistributor : public SystemObject, public ExecutableObjectIF, public Has * with distribution. * @return The error code of the message queue call. */ - ReturnValue_t performOperation(uint8_t opCode); - /** - * A simple debug print, that prints all distribution information stored in - * queueMap. - */ - void print(); + ReturnValue_t performOperation(uint8_t opCode) override; protected: + bool ownedQueue = false; /** * This is the receiving queue for incoming Telecommands. * The child classes must make its queue id public. @@ -73,27 +67,22 @@ class TcDistributor : public SystemObject, public ExecutableObjectIF, public Has * The last received incoming packet information is stored in this * member. * As different child classes unpack the incoming packet differently - * (i.e. as a CCSDS Space Packet or as a PUS Telecommand Packet), it - * is not tried to unpack the packet information within this class. + * (i.e. as a CCSDS Space Packet or as a PUS Telecommand Packet), no unpacking will be + * done in this class. */ TmTcMessage currentMessage; - /** - * The map that links certain packet information to a destination. - * The packet information may be the APID of the packet or the service - * identifier. Filling of the map is under control of the different child - * classes. - */ - TcMessageQueueMap queueMap; + /** * This method shall unpack the routing information from the incoming * packet and select the map entry which represents the packet's target. - * @return An iterator to the map element to forward to or queuMap.end(). + * @return + * - @c RETURN_OK if a desitnation was selected successfully */ - virtual TcMqMapIter selectDestination() = 0; + virtual ReturnValue_t selectDestination(MessageQueueId_t& destId) = 0; /** * The handlePacket method calls the child class's selectDestination method * and forwards the packet to its destination, if found. - * @return The message queue return value or @c RETURN_FAILED, in case no + * @return The message queue return value or @c returnvalue::FAILED, in case no * destination was found. */ ReturnValue_t handlePacket(); @@ -101,11 +90,11 @@ class TcDistributor : public SystemObject, public ExecutableObjectIF, public Has * This method gives the child class a chance to perform some kind of * operation after the parent tried to forward the message. * A typically application would be sending success/failure messages. - * The default implementation just returns @c RETURN_OK. + * The default implementation just returns @c returnvalue::OK. * @param queueStatus The status of the message queue after an attempt * to send the TC. - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure + * @return - @c returnvalue::OK on success + * - @c returnvalue::FAILED on failure */ virtual ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus); diff --git a/src/fsfw/tcdistribution/TcPacketCheckCFDP.cpp b/src/fsfw/tcdistribution/TcPacketCheckCFDP.cpp index d1eb43bc..8171a392 100644 --- a/src/fsfw/tcdistribution/TcPacketCheckCFDP.cpp +++ b/src/fsfw/tcdistribution/TcPacketCheckCFDP.cpp @@ -1,9 +1,11 @@ -#include "fsfw/tcdistribution/TcPacketCheckCFDP.h" +#include "fsfw/tcdistribution/CfdpPacketChecker.h" +#include "fsfw/tmtcpacket/cfdp/CfdpPacketStored.h" -#include "fsfw/tmtcpacket/cfdp/CFDPPacketStored.h" +CfdpPacketChecker::CfdpPacketChecker(uint16_t setApid) : apid(setApid) {} -TcPacketCheckCFDP::TcPacketCheckCFDP(uint16_t setApid) : apid(setApid) {} +ReturnValue_t CfdpPacketChecker::checkPacket(const SpacePacketReader& currentPacket, + size_t packetLen) { + return returnvalue::OK; +} -ReturnValue_t TcPacketCheckCFDP::checkPacket(SpacePacketBase* currentPacket) { return RETURN_OK; } - -uint16_t TcPacketCheckCFDP::getApid() const { return apid; } +uint16_t CfdpPacketChecker::getApid() const { return apid; } diff --git a/src/fsfw/tcdistribution/TcPacketCheckPUS.cpp b/src/fsfw/tcdistribution/TcPacketCheckPUS.cpp deleted file mode 100644 index 83844337..00000000 --- a/src/fsfw/tcdistribution/TcPacketCheckPUS.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "fsfw/tcdistribution/TcPacketCheckPUS.h" - -#include "fsfw/globalfunctions/CRC.h" -#include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/storagemanager/StorageManagerIF.h" -#include "fsfw/tmtcpacket/pus/tc/TcPacketPusBase.h" -#include "fsfw/tmtcpacket/pus/tc/TcPacketStoredBase.h" -#include "fsfw/tmtcpacket/pus/tc/TcPacketStoredPus.h" -#include "fsfw/tmtcservices/VerificationCodes.h" - -TcPacketCheckPUS::TcPacketCheckPUS(uint16_t setApid) : apid(setApid) {} - -ReturnValue_t TcPacketCheckPUS::checkPacket(SpacePacketBase* currentPacket) { - TcPacketStoredBase* storedPacket = dynamic_cast(currentPacket); - TcPacketPusBase* tcPacketBase = dynamic_cast(currentPacket); - if (tcPacketBase == nullptr or storedPacket == nullptr) { - return RETURN_FAILED; - } - uint16_t calculated_crc = - CRC::crc16ccitt(tcPacketBase->getWholeData(), tcPacketBase->getFullSize()); - if (calculated_crc != 0) { - return INCORRECT_CHECKSUM; - } - bool condition = (not tcPacketBase->hasSecondaryHeader()) or - (tcPacketBase->getPacketVersionNumber() != CCSDS_VERSION_NUMBER) or - (not tcPacketBase->isTelecommand()); - if (condition) { - return INCORRECT_PRIMARY_HEADER; - } - if (tcPacketBase->getAPID() != this->apid) return ILLEGAL_APID; - - if (not storedPacket->isSizeCorrect()) { - return INCOMPLETE_PACKET; - } - - condition = (tcPacketBase->getSecondaryHeaderFlag() != CCSDS_SECONDARY_HEADER_FLAG) || - (tcPacketBase->getPusVersionNumber() != PUS_VERSION_NUMBER); - if (condition) { - return INCORRECT_SECONDARY_HEADER; - } - return RETURN_OK; -} - -uint16_t TcPacketCheckPUS::getApid() const { return apid; } diff --git a/src/fsfw/tcdistribution/TcPacketCheckPUS.h b/src/fsfw/tcdistribution/TcPacketCheckPUS.h deleted file mode 100644 index e3eca1a4..00000000 --- a/src/fsfw/tcdistribution/TcPacketCheckPUS.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef FSFW_TCDISTRIBUTION_TCPACKETCHECKPUS_H_ -#define FSFW_TCDISTRIBUTION_TCPACKETCHECKPUS_H_ - -#include "TcPacketCheckIF.h" -#include "fsfw/FSFW.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" -#include "fsfw/tmtcservices/PusVerificationReport.h" - -class TcPacketStoredBase; - -/** - * This class performs a formal packet check for incoming PUS Telecommand Packets. - * Currently, it only checks if the APID and CRC are correct. - * @ingroup tc_distribution - */ -class TcPacketCheckPUS : public TcPacketCheckIF, public HasReturnvaluesIF { - protected: - /** - * Describes the version number a packet must have to pass. - */ - static constexpr uint8_t CCSDS_VERSION_NUMBER = 0; - /** - * Describes the secondary header a packet must have to pass. - */ - static constexpr uint8_t CCSDS_SECONDARY_HEADER_FLAG = 0; - /** - * Describes the TC Packet PUS Version Number a packet must have to pass. - */ -#if FSFW_USE_PUS_C_TELECOMMANDS == 1 - static constexpr uint8_t PUS_VERSION_NUMBER = 2; -#else - static constexpr uint8_t PUS_VERSION_NUMBER = 1; -#endif - - /** - * The packet id each correct packet should have. - * It is composed of the APID and some static fields. - */ - uint16_t apid; - - public: - static const uint8_t INTERFACE_ID = CLASS_ID::TC_PACKET_CHECK; - static const ReturnValue_t ILLEGAL_APID = MAKE_RETURN_CODE(0); - static const ReturnValue_t INCOMPLETE_PACKET = MAKE_RETURN_CODE(1); - static const ReturnValue_t INCORRECT_CHECKSUM = MAKE_RETURN_CODE(2); - static const ReturnValue_t ILLEGAL_PACKET_TYPE = MAKE_RETURN_CODE(3); - static const ReturnValue_t ILLEGAL_PACKET_SUBTYPE = MAKE_RETURN_CODE(4); - static const ReturnValue_t INCORRECT_PRIMARY_HEADER = MAKE_RETURN_CODE(5); - static const ReturnValue_t INCORRECT_SECONDARY_HEADER = MAKE_RETURN_CODE(6); - /** - * The constructor only sets the APID attribute. - * @param set_apid The APID to set. - */ - TcPacketCheckPUS(uint16_t setApid); - - ReturnValue_t checkPacket(SpacePacketBase* currentPacket) override; - - uint16_t getApid() const; -}; - -#endif /* FSFW_TCDISTRIBUTION_TCPACKETCHECKPUS_H_ */ diff --git a/src/fsfw/tcdistribution/definitions.h b/src/fsfw/tcdistribution/definitions.h new file mode 100644 index 00000000..bec1dd1b --- /dev/null +++ b/src/fsfw/tcdistribution/definitions.h @@ -0,0 +1,31 @@ +#ifndef FSFW_TMTCPACKET_DEFINITIONS_H +#define FSFW_TMTCPACKET_DEFINITIONS_H + +#include + +#include "fsfw/events/Event.h" +#include "fsfw/events/fwSubsystemIdRanges.h" +#include "fsfw/returnvalues/FwClassIds.h" +#include "fsfw/returnvalues/returnvalue.h" + +namespace tmtcdistrib { +static const uint8_t INTERFACE_ID = CLASS_ID::TMTC_DISTRIBUTION; +static constexpr ReturnValue_t NO_DESTINATION_FOUND = returnvalue::makeCode(INTERFACE_ID, 0); +static constexpr ReturnValue_t INVALID_CCSDS_VERSION = MAKE_RETURN_CODE(1); +static constexpr ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(2); +static constexpr ReturnValue_t INVALID_PACKET_TYPE = MAKE_RETURN_CODE(3); +static constexpr ReturnValue_t INVALID_SEC_HEADER_FIELD = MAKE_RETURN_CODE(4); +static constexpr ReturnValue_t INCORRECT_PRIMARY_HEADER = MAKE_RETURN_CODE(5); + +static constexpr ReturnValue_t INCOMPLETE_PACKET = MAKE_RETURN_CODE(7); +static constexpr ReturnValue_t INVALID_PUS_VERSION = MAKE_RETURN_CODE(8); +static constexpr ReturnValue_t INCORRECT_CHECKSUM = MAKE_RETURN_CODE(9); +static constexpr ReturnValue_t ILLEGAL_PACKET_SUBTYPE = MAKE_RETURN_CODE(10); +static constexpr ReturnValue_t INCORRECT_SECONDARY_HEADER = MAKE_RETURN_CODE(11); + +static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::TMTC_DISTRIBUTION; +//! P1: Returnvalue, P2: 0 for TM issues, 1 for TC issues +static constexpr Event HANDLE_PACKET_FAILED = event::makeEvent(SUBSYSTEM_ID, 0, severity::LOW); + +}; // namespace tmtcdistrib +#endif // FSFW_TMTCPACKET_DEFINITIONS_H diff --git a/src/fsfw/thermal/AbstractTemperatureSensor.cpp b/src/fsfw/thermal/AbstractTemperatureSensor.cpp index 68cd3aca..fc182bf1 100644 --- a/src/fsfw/thermal/AbstractTemperatureSensor.cpp +++ b/src/fsfw/thermal/AbstractTemperatureSensor.cpp @@ -24,11 +24,11 @@ MessageQueueId_t AbstractTemperatureSensor::getCommandQueue() const { ReturnValue_t AbstractTemperatureSensor::initialize() { ReturnValue_t result = SystemObject::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = healthHelper.initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = parameterHelper.initialize(); @@ -38,24 +38,24 @@ ReturnValue_t AbstractTemperatureSensor::initialize() { ReturnValue_t AbstractTemperatureSensor::performOperation(uint8_t opCode) { handleCommandQueue(); doChildOperation(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t AbstractTemperatureSensor::performHealthOp() { handleCommandQueue(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void AbstractTemperatureSensor::handleCommandQueue() { CommandMessage command; ReturnValue_t result = commandQueue->receiveMessage(&command); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { result = healthHelper.handleHealthCommand(&command); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { return; } result = parameterHelper.handleParameterMessage(&command); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { return; } command.setToUnknownCommand(); @@ -65,7 +65,7 @@ void AbstractTemperatureSensor::handleCommandQueue() { ReturnValue_t AbstractTemperatureSensor::setHealth(HealthState health) { healthHelper.setHealth(health); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } HasHealthIF::HealthState AbstractTemperatureSensor::getHealth() { return healthHelper.getHealth(); } diff --git a/src/fsfw/thermal/CMakeLists.txt b/src/fsfw/thermal/CMakeLists.txt index ad532721..995ebc4d 100644 --- a/src/fsfw/thermal/CMakeLists.txt +++ b/src/fsfw/thermal/CMakeLists.txt @@ -1,10 +1,9 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - AbstractTemperatureSensor.cpp - Heater.cpp - RedundantHeater.cpp - ThermalComponentCore.cpp - ThermalComponent.cpp - ThermalModule.cpp - ThermalMonitorReporter.cpp -) +target_sources( + ${LIB_FSFW_NAME} + PRIVATE AbstractTemperatureSensor.cpp + Heater.cpp + RedundantHeater.cpp + ThermalComponentCore.cpp + ThermalComponent.cpp + ThermalModule.cpp + ThermalMonitorReporter.cpp) diff --git a/src/fsfw/thermal/Heater.cpp b/src/fsfw/thermal/Heater.cpp index 4f0f8060..64348106 100644 --- a/src/fsfw/thermal/Heater.cpp +++ b/src/fsfw/thermal/Heater.cpp @@ -21,14 +21,14 @@ ReturnValue_t Heater::set() { passive = false; // wait for clear before doing anything if (internalState == STATE_WAIT) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } if (healthHelper.healthTable->isHealthy(getObjectId())) { doAction(SET); if ((internalState == STATE_OFF) || (internalState == STATE_PASSIVE)) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } else { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } } else { if (healthHelper.healthTable->isFaulty(getObjectId())) { @@ -37,7 +37,7 @@ ReturnValue_t Heater::set() { doAction(CLEAR); } } - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -186,7 +186,7 @@ ReturnValue_t Heater::performOperation(uint8_t opCode) { wasOn = false; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void Heater::setSwitch(uint8_t number, ReturnValue_t state, uint32_t* uptimeOfSwitching) { @@ -220,54 +220,54 @@ MessageQueueId_t Heater::getCommandQueue() const { return commandQueue->getId(); ReturnValue_t Heater::initialize() { ReturnValue_t result = SystemObject::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } EventManagerIF* manager = ObjectManager::instance()->get(objects::EVENT_MANAGER); if (manager == NULL) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } result = manager->registerListener(eventQueue->getId()); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } ConfirmsFailuresIF* pcdu = ObjectManager::instance()->get( DeviceHandlerFailureIsolation::powerConfirmationId); if (pcdu == NULL) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } pcduQueueId = pcdu->getEventReceptionQueue(); result = manager->subscribeToAllEventsFrom(eventQueue->getId(), getObjectId()); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = parameterHelper.initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = healthHelper.initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void Heater::handleQueue() { CommandMessage command; ReturnValue_t result = commandQueue->receiveMessage(&command); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { result = healthHelper.handleHealthCommand(&command); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { return; } result = parameterHelper.handleParameterMessage(&command); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { return; } } @@ -286,13 +286,13 @@ ReturnValue_t Heater::getParameter(uint8_t domainId, uint8_t uniqueId, default: return INVALID_IDENTIFIER_ID; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void Heater::handleEventQueue() { EventMessage event; - for (ReturnValue_t result = eventQueue->receiveMessage(&event); - result == HasReturnvaluesIF::RETURN_OK; result = eventQueue->receiveMessage(&event)) { + for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK; + result = eventQueue->receiveMessage(&event)) { switch (event.getMessageId()) { case EventMessage::EVENT_MESSAGE: switch (event.getEvent()) { diff --git a/src/fsfw/thermal/Heater.h b/src/fsfw/thermal/Heater.h index 61d3776f..d535f54a 100644 --- a/src/fsfw/thermal/Heater.h +++ b/src/fsfw/thermal/Heater.h @@ -6,7 +6,7 @@ #include "fsfw/devicehandlers/HealthDevice.h" #include "fsfw/parameters/ParameterHelper.h" #include "fsfw/power/PowerSwitchIF.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/timemanager/Countdown.h" class Heater : public HealthDevice, public ReceivesParameterMessagesIF { diff --git a/src/fsfw/thermal/RedundantHeater.cpp b/src/fsfw/thermal/RedundantHeater.cpp index 431d9900..24b70c89 100644 --- a/src/fsfw/thermal/RedundantHeater.cpp +++ b/src/fsfw/thermal/RedundantHeater.cpp @@ -14,7 +14,7 @@ void RedundantHeater::performOperation(uint8_t opCode) { void RedundantHeater::set(bool on, bool both, bool passive) { if (on) { ReturnValue_t result = heater0.set(); - if (result != HasReturnvaluesIF::RETURN_OK || both) { + if (result != returnvalue::OK || both) { heater1.set(); } else { heater1.clear(passive); diff --git a/src/fsfw/thermal/TemperatureSensor.h b/src/fsfw/thermal/TemperatureSensor.h index 591fd7d9..4cb2a083 100644 --- a/src/fsfw/thermal/TemperatureSensor.h +++ b/src/fsfw/thermal/TemperatureSensor.h @@ -117,7 +117,7 @@ class TemperatureSensor : public AbstractTemperatureSensor { void doChildOperation() { ReturnValue_t result = inputTemperature->read(MutexIF::TimeoutType::WAITING, 20); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return; } @@ -209,7 +209,7 @@ class TemperatureSensor : public AbstractTemperatureSensor { default: return INVALID_IDENTIFIER_ID; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } virtual void resetOldState() { sensorMonitor.setToUnchecked(); } diff --git a/src/fsfw/thermal/ThermalComponent.cpp b/src/fsfw/thermal/ThermalComponent.cpp index 000f2e19..e0077af2 100644 --- a/src/fsfw/thermal/ThermalComponent.cpp +++ b/src/fsfw/thermal/ThermalComponent.cpp @@ -21,18 +21,18 @@ ReturnValue_t ThermalComponent::setTargetState(int8_t newState) { targetState.setReadWriteMode(pool_rwm_t::VAR_READ_WRITE); targetState.read(); if ((targetState == STATE_REQUEST_OPERATIONAL) and (newState != STATE_REQUEST_IGNORE)) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } switch (newState) { case STATE_REQUEST_NON_OPERATIONAL: targetState = newState; targetState.setValid(true); targetState.commit(PoolVariableIF::VALID); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; default: return ThermalComponentCore::setTargetState(newState); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t ThermalComponent::setLimits(const uint8_t* data, size_t size) { @@ -48,7 +48,7 @@ ReturnValue_t ThermalComponent::setLimits(const uint8_t* data, size_t size) { SerializeIF::Endianness::BIG); SerializeAdapter::deSerialize(&nopParameters.upperNopLimit, &data, &readSize, SerializeIF::Endianness::BIG); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ThermalComponentIF::State ThermalComponent::getState(float temperature, @@ -155,5 +155,5 @@ ReturnValue_t ThermalComponent::getParameter(uint8_t domainId, uint8_t uniqueId, default: return INVALID_IDENTIFIER_ID; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/src/fsfw/thermal/ThermalComponentCore.cpp b/src/fsfw/thermal/ThermalComponentCore.cpp index 887c30f2..ef47f49f 100644 --- a/src/fsfw/thermal/ThermalComponentCore.cpp +++ b/src/fsfw/thermal/ThermalComponentCore.cpp @@ -18,7 +18,7 @@ ThermalComponentCore::ThermalComponentCore(object_id_t reportingObjectId, uint8_ // Set thermal state once, then leave to operator. targetState.setReadWriteMode(PoolVariableIF::VAR_WRITE); ReturnValue_t result = targetState.read(); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { targetState = initialTargetState; targetState.setValid(true); targetState.commit(); @@ -91,7 +91,7 @@ ReturnValue_t ThermalComponentCore::setTargetState(int8_t newState) { targetState.setReadWriteMode(pool_rwm_t::VAR_READ_WRITE); targetState.read(); if ((targetState == STATE_REQUEST_OPERATIONAL) and (newState != STATE_REQUEST_IGNORE)) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } switch (newState) { @@ -106,7 +106,7 @@ ReturnValue_t ThermalComponentCore::setTargetState(int8_t newState) { } targetState.setValid(true); targetState.commit(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void ThermalComponentCore::setOutputInvalid() { @@ -267,5 +267,5 @@ ReturnValue_t ThermalComponentCore::getParameter(uint8_t domainId, uint8_t uniqu default: return INVALID_IDENTIFIER_ID; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/src/fsfw/thermal/ThermalComponentIF.h b/src/fsfw/thermal/ThermalComponentIF.h index 0c50fbad..0ab22d85 100644 --- a/src/fsfw/thermal/ThermalComponentIF.h +++ b/src/fsfw/thermal/ThermalComponentIF.h @@ -4,7 +4,7 @@ #include "../events/Event.h" #include "../objectmanager/SystemObjectIF.h" #include "../parameters/HasParametersIF.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "../returnvalues/returnvalue.h" class ThermalComponentIF : public HasParametersIF { public: diff --git a/src/fsfw/thermal/ThermalModule.cpp b/src/fsfw/thermal/ThermalModule.cpp index 976bbe45..6f62a02b 100644 --- a/src/fsfw/thermal/ThermalModule.cpp +++ b/src/fsfw/thermal/ThermalModule.cpp @@ -233,7 +233,7 @@ bool ThermalModule::calculateModuleHeaterRequestAndSetModuleStatus(Strategy stra void ThermalModule::setHeating(bool on) { ReturnValue_t result = targetState.read(); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { if (on) { targetState.value = STATE_REQUEST_HEATING; } else { diff --git a/src/fsfw/thermal/ThermalMonitorReporter.cpp b/src/fsfw/thermal/ThermalMonitorReporter.cpp index dc64280e..2e6796a6 100644 --- a/src/fsfw/thermal/ThermalMonitorReporter.cpp +++ b/src/fsfw/thermal/ThermalMonitorReporter.cpp @@ -46,20 +46,20 @@ ReturnValue_t ThermalMonitorReporter::translateState(ThermalComponentIF::State s if (componentIsOperational) { return monitorStateIs(ThermalComponentIF::BELOW_OPERATIONAL_LIMIT, sample, lowerLimit); } else { - return monitorStateIs(HasReturnvaluesIF::RETURN_OK, sample, 0.0); + return monitorStateIs(returnvalue::OK, sample, 0.0); } case ThermalComponentIF::OPERATIONAL: - return monitorStateIs(HasReturnvaluesIF::RETURN_OK, sample, 0.0); + return monitorStateIs(returnvalue::OK, sample, 0.0); case ThermalComponentIF::NON_OPERATIONAL_HIGH: if (componentIsOperational) { return monitorStateIs(ThermalComponentIF::ABOVE_OPERATIONAL_LIMIT, sample, upperLimit); } else { - return monitorStateIs(HasReturnvaluesIF::RETURN_OK, sample, 0.0); + return monitorStateIs(returnvalue::OK, sample, 0.0); } case ThermalComponentIF::OUT_OF_RANGE_HIGH: return monitorStateIs(MonitoringIF::ABOVE_HIGH_LIMIT, sample, upperLimit); default: // Never reached, all states covered. - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } diff --git a/src/fsfw/timemanager/CCSDSTime.cpp b/src/fsfw/timemanager/CCSDSTime.cpp index 9ebd1d79..cb0d5758 100644 --- a/src/fsfw/timemanager/CCSDSTime.cpp +++ b/src/fsfw/timemanager/CCSDSTime.cpp @@ -6,13 +6,9 @@ #include "fsfw/FSFW.h" -CCSDSTime::CCSDSTime() {} - -CCSDSTime::~CCSDSTime() {} - ReturnValue_t CCSDSTime::convertToCcsds(Ccs_seconds* to, const Clock::TimeOfDay_t* from) { ReturnValue_t result = checkTimeOfDay(from); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -26,12 +22,12 @@ ReturnValue_t CCSDSTime::convertToCcsds(Ccs_seconds* to, const Clock::TimeOfDay_ to->minute = from->minute; to->second = from->second; - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t CCSDSTime::convertToCcsds(Ccs_mseconds* to, const Clock::TimeOfDay_t* from) { ReturnValue_t result = checkTimeOfDay(from); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -47,7 +43,7 @@ ReturnValue_t CCSDSTime::convertToCcsds(Ccs_mseconds* to, const Clock::TimeOfDay to->secondEminus2 = from->usecond / 10000; to->secondEminus4 = (from->usecond % 10000) / 100; - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t CCSDSTime::convertFromCcsds(Clock::TimeOfDay_t* to, const uint8_t* from, @@ -57,8 +53,8 @@ ReturnValue_t CCSDSTime::convertFromCcsds(Clock::TimeOfDay_t* to, const uint8_t* return LENGTH_MISMATCH; } result = convertFromASCII(to, from, length); // Try to parse it as ASCII - if (result == RETURN_OK) { - return RETURN_OK; + if (result == returnvalue::OK) { + return returnvalue::OK; } // Seems to be no ascii, try the other formats @@ -88,7 +84,7 @@ ReturnValue_t CCSDSTime::convertFromCDS(Clock::TimeOfDay_t* to, const uint8_t* f uint8_t length) { timeval time; ReturnValue_t result = convertFromCDS(&time, from, NULL, length); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return Clock::convertTimevalToTimeOfDay(&time, to); @@ -106,7 +102,7 @@ ReturnValue_t CCSDSTime::convertFromCCS(Clock::TimeOfDay_t* to, const uint8_t* f ReturnValue_t result = checkCcs(from, maxLength); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } // At this point we made sure that this is a valid ccs time @@ -122,7 +118,7 @@ ReturnValue_t CCSDSTime::convertFromCCS(Clock::TimeOfDay_t* to, const uint8_t* f uint8_t tempDay = 0; uint8_t tempMonth = 0; result = convertDaysOfYear(tempDayOfYear, to->year, &tempMonth, &tempDay); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } to->month = tempMonth; @@ -148,13 +144,13 @@ ReturnValue_t CCSDSTime::convertFromCCS(Clock::TimeOfDay_t* to, const uint8_t* f to->usecond += temp->secondEminus4 * 100; } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* from, uint8_t length) { if (length < 19) { - return RETURN_FAILED; + return returnvalue::FAILED; } // Newlib nano can't parse uint8, see SCNu8 documentation and https://sourceware.org/newlib/README // Suggestion: use uint16 all the time. This should work on all systems. @@ -178,7 +174,7 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* to->minute = minute; to->second = second; to->usecond = (second - floor(second)) * 1000000; - return RETURN_OK; + return returnvalue::OK; } // try Code B (yyyy-ddd) @@ -191,8 +187,8 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* uint8_t tempDay; ReturnValue_t result = CCSDSTime::convertDaysOfYear( day, year, reinterpret_cast(&month), reinterpret_cast(&tempDay)); - if (result != RETURN_OK) { - return RETURN_FAILED; + if (result != returnvalue::OK) { + return returnvalue::FAILED; } to->year = year; to->month = month; @@ -201,7 +197,7 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* to->minute = minute; to->second = second; to->usecond = (second - floor(second)) * 1000000; - return RETURN_OK; + return returnvalue::OK; } // Warning: Compiler/Linker fails ambiguously if library does not implement // C99 I/O @@ -224,7 +220,7 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* to->minute = minute; to->second = second; to->usecond = (second - floor(second)) * 1000000; - return RETURN_OK; + return returnvalue::OK; } // try Code B (yyyy-ddd) @@ -233,8 +229,8 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* if (count == 5) { uint8_t tempDay; ReturnValue_t result = CCSDSTime::convertDaysOfYear(day, year, &month, &tempDay); - if (result != RETURN_OK) { - return RETURN_FAILED; + if (result != returnvalue::OK) { + return returnvalue::FAILED; } to->year = year; to->month = month; @@ -243,7 +239,7 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* to->minute = minute; to->second = second; to->usecond = (second - floor(second)) * 1000000; - return RETURN_OK; + return returnvalue::OK; } #endif @@ -288,7 +284,7 @@ ReturnValue_t CCSDSTime::checkCcs(const uint8_t* time, uint8_t length) { return INVALID_TIME_FORMAT; } } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t CCSDSTime::convertDaysOfYear(uint16_t dayofYear, uint16_t year, uint8_t* month, @@ -305,21 +301,21 @@ ReturnValue_t CCSDSTime::convertDaysOfYear(uint16_t dayofYear, uint16_t year, ui *month = 1; if (dayofYear <= 31) { *day = dayofYear; - return RETURN_OK; + return returnvalue::OK; } *month += 1; dayofYear -= 31; if (isLeapYear(year)) { if (dayofYear <= 29) { *day = dayofYear; - return RETURN_OK; + return returnvalue::OK; } *month += 1; dayofYear -= 29; } else { if (dayofYear <= 28) { *day = dayofYear; - return RETURN_OK; + return returnvalue::OK; } *month += 1; dayofYear -= 28; @@ -327,7 +323,7 @@ ReturnValue_t CCSDSTime::convertDaysOfYear(uint16_t dayofYear, uint16_t year, ui while (*month <= 12) { if (dayofYear <= 31) { *day = dayofYear; - return RETURN_OK; + return returnvalue::OK; } *month += 1; dayofYear -= 31; @@ -338,7 +334,7 @@ ReturnValue_t CCSDSTime::convertDaysOfYear(uint16_t dayofYear, uint16_t year, ui if (dayofYear <= 30) { *day = dayofYear; - return RETURN_OK; + return returnvalue::OK; } *month += 1; dayofYear -= 30; @@ -373,7 +369,7 @@ ReturnValue_t CCSDSTime::convertToCcsds(CDS_short* to, const timeval* from) { to->msDay_h = (msDay & 0xFF0000) >> 16; to->msDay_l = (msDay & 0xFF00) >> 8; to->msDay_ll = (msDay & 0xFF); - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t CCSDSTime::convertToCcsds(OBT_FLP* to, const timeval* from) { @@ -391,7 +387,7 @@ ReturnValue_t CCSDSTime::convertToCcsds(OBT_FLP* to, const timeval* from) { to->subsecondsMSB = (temp >> 8) & 0xff; to->subsecondsLSB = temp & 0xff; - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t CCSDSTime::convertFromCcsds(timeval* to, const uint8_t* from, size_t* foundLength, @@ -400,7 +396,7 @@ ReturnValue_t CCSDSTime::convertFromCcsds(timeval* to, const uint8_t* from, size Clock::TimeOfDay_t timeOfDay; /* Try to parse it as ASCII */ ReturnValue_t result = convertFromASCII(&timeOfDay, from, maxLength); - if (result == RETURN_OK) { + if (result == returnvalue::OK) { return Clock::convertTimeOfDayToTimeval(&timeOfDay, to); } } @@ -427,8 +423,8 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, const uint8_t* from, size_t uint8_t pField = *from; from++; ReturnValue_t result = convertFromCUC(to, pField, from, foundLength, maxLength - 1); - if (result == HasReturnvaluesIF::RETURN_OK) { - if (foundLength != NULL) { + if (result == returnvalue::OK) { + if (foundLength != nullptr) { *foundLength += 1; } } @@ -486,7 +482,7 @@ ReturnValue_t CCSDSTime::checkTimeOfDay(const Clock::TimeOfDay_t* time) { return INVALID_TIME_FORMAT; } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from, size_t* foundLength, @@ -508,7 +504,7 @@ ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from, size_t } else if ((pField & 0b11) == 0b10) { expectedLength += 4; } - if (foundLength != NULL) { + if (foundLength != nullptr) { *foundLength = expectedLength; } if (expectedLength > maxLength) { @@ -549,12 +545,12 @@ ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from, size_t // Not very useful. to->tv_usec += (picosecs / 1000); } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const CCSDSTime::CDS_short* from) { if (to == nullptr or from == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } uint16_t days = (from->dayMSB << 8) + from->dayLSB; if (days <= DAYS_CCSDS_TO_UNIX_EPOCH) { @@ -566,16 +562,16 @@ ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const CCSDSTime::CDS_short* (from->msDay_hh << 24) + (from->msDay_h << 16) + (from->msDay_l << 8) + from->msDay_ll; to->tv_sec += (msDay / 1000); to->tv_usec = (msDay % 1000) * 1000; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t CCSDSTime::convertFromCDS(Clock::TimeOfDay_t* to, const CCSDSTime::CDS_short* from) { if (to == nullptr or from == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } timeval tempTimeval; ReturnValue_t result = convertFromCDS(&tempTimeval, from); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return Clock::convertTimevalToTimeOfDay(&tempTimeval, to); @@ -588,18 +584,18 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField, const uint8 uint8_t nCoarse = ((pField & 0b1100) >> 2) + 1; uint8_t nFine = (pField & 0b11); size_t totalLength = nCoarse + nFine; - if (foundLength != NULL) { + if (foundLength != nullptr) { *foundLength = totalLength; } if (totalLength > maxLength) { return LENGTH_MISMATCH; } - for (int count = 0; count < nCoarse; count++) { - secs += *from << ((nCoarse * 8 - 8) * (1 + count)); + for (int count = nCoarse; count > 0; count--) { + secs += *from << (count * 8 - 8); from++; } - for (int count = 0; count < nFine; count++) { - subSeconds += *from << ((nFine * 8 - 8) * (1 + count)); + for (int count = nFine; count > 0; count--) { + subSeconds += *from << (count * 8 - 8); from++; } // Move to POSIX epoch. @@ -609,7 +605,7 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField, const uint8 to->tv_sec -= (DAYS_CCSDS_TO_UNIX_EPOCH * SECONDS_PER_DAY); } to->tv_usec = subsecondsToMicroseconds(subSeconds); - return RETURN_OK; + return returnvalue::OK; } uint32_t CCSDSTime::subsecondsToMicroseconds(uint16_t subseconds) { @@ -621,7 +617,7 @@ ReturnValue_t CCSDSTime::convertFromCCS(timeval* to, const uint8_t* from, size_t size_t maxLength) { Clock::TimeOfDay_t tempTime; ReturnValue_t result = convertFromCCS(&tempTime, from, foundLength, maxLength); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } diff --git a/src/fsfw/timemanager/CCSDSTime.h b/src/fsfw/timemanager/CCSDSTime.h index 19c980d0..77801cec 100644 --- a/src/fsfw/timemanager/CCSDSTime.h +++ b/src/fsfw/timemanager/CCSDSTime.h @@ -6,9 +6,9 @@ #include #include -#include "../returnvalues/HasReturnvaluesIF.h" #include "Clock.h" #include "clockDefinitions.h" +#include "fsfw/returnvalues/returnvalue.h" bool operator<(const timeval &lhs, const timeval &rhs); bool operator<=(const timeval &lhs, const timeval &rhs); @@ -20,7 +20,7 @@ bool operator==(const timeval &lhs, const timeval &rhs); * * Still work in progress */ -class CCSDSTime : public HasReturnvaluesIF { +class CCSDSTime { public: /** * The Time code identifications, bits 4-6 in the P-Field @@ -39,13 +39,13 @@ class CCSDSTime : public HasReturnvaluesIF { * Struct for CDS day-segmented format. */ struct CDS_short { - uint8_t pField; - uint8_t dayMSB; - uint8_t dayLSB; - uint8_t msDay_hh; - uint8_t msDay_h; - uint8_t msDay_l; - uint8_t msDay_ll; + uint8_t pField = P_FIELD_CDS_SHORT; + uint8_t dayMSB = 0; + uint8_t dayLSB = 0; + uint8_t msDay_hh = 0; + uint8_t msDay_h = 0; + uint8_t msDay_l = 0; + uint8_t msDay_ll = 0; }; /** * Struct for the CCS fromat in day of month variation with max resolution @@ -105,7 +105,7 @@ class CCSDSTime : public HasReturnvaluesIF { * @param to pointer to a CCS struct * @param from pointer to a TimeOfDay Struct * @return - * - @c RETURN_OK if OK + * - @c returnvalue::OK if OK * - @c INVALID_TIMECODE if not OK */ static ReturnValue_t convertToCcsds(Ccs_seconds *to, Clock::TimeOfDay_t const *from); @@ -115,7 +115,7 @@ class CCSDSTime : public HasReturnvaluesIF { * @param to pointer to the CDS struct to generate * @param from pointer to a timeval struct which comprises a time of day since UNIX epoch. * @return - * - @c RETURN_OK as it assumes a valid timeval. + * - @c returnvalue::OK as it assumes a valid timeval. */ static ReturnValue_t convertToCcsds(CDS_short *to, timeval const *from); @@ -129,7 +129,7 @@ class CCSDSTime : public HasReturnvaluesIF { * @param to pointer to a CCS struct * @param from pointer to a TimeOfDay Struct * @return - * - @c RETURN_OK if OK + * - @c returnvalue::OK if OK * - @c INVALID_TIMECODE if not OK */ static ReturnValue_t convertToCcsds(Ccs_mseconds *to, Clock::TimeOfDay_t const *from); @@ -145,7 +145,7 @@ class CCSDSTime : public HasReturnvaluesIF { * @param from pointer to an CCSDS Time code * @param length length of the Time code * @return - * - @c RETURN_OK if successful + * - @c returnvalue::OK if successful * - @c UNSUPPORTED_TIME_FORMAT if a (possibly valid) time code is not supported * - @c LENGTH_MISMATCH if the length does not match the P Field * - @c INVALID_TIME_FORMAT if the format or a value is invalid @@ -161,18 +161,37 @@ class CCSDSTime : public HasReturnvaluesIF { */ static ReturnValue_t convertFromCcsds(timeval *to, uint8_t const *from, size_t *foundLength, size_t maxLength); - + /** + * @brief Currently unsupported conversion due to leapseconds + * + * @param to Time Of Day (UTC) + * @param from Buffer to take the CUC from + * @param length Length of buffer + * @return ReturnValue_t UNSUPPORTED_TIME_FORMAT in any case ATM + */ static ReturnValue_t convertFromCUC(Clock::TimeOfDay_t *to, uint8_t const *from, uint8_t length); - + /** + * @brief Converts from CCSDS CUC to timeval + * + * If input is CCSDS Epoch this is TAI! -> No leapsecond support. + * + * Currently, it only supports seconds + 2 Byte Subseconds (1/65536 seconds) + * + * + * @param to Timeval to write the result to + * @param from Buffer to read from + * @param foundLength Length found by this function (can be nullptr if unused) + * @param maxLength Max length of the buffer to be read + * @return ReturnValue_t - returnvalue::OK if successful + * - LENGTH_MISMATCH if expected length is larger than maxLength + */ static ReturnValue_t convertFromCUC(timeval *to, uint8_t const *from, size_t *foundLength, size_t maxLength); - static ReturnValue_t convertFromCUC(timeval *to, uint8_t pField, uint8_t const *from, size_t *foundLength, size_t maxLength); static ReturnValue_t convertFromCCS(timeval *to, uint8_t const *from, size_t *foundLength, size_t maxLength); - static ReturnValue_t convertFromCCS(timeval *to, uint8_t pField, uint8_t const *from, size_t *foundLength, size_t maxLength); @@ -192,8 +211,8 @@ class CCSDSTime : public HasReturnvaluesIF { static uint32_t subsecondsToMicroseconds(uint16_t subseconds); private: - CCSDSTime(); - virtual ~CCSDSTime(); + CCSDSTime(){}; + virtual ~CCSDSTime(){}; /** * checks a ccs time stream for validity * diff --git a/src/fsfw/timemanager/CMakeLists.txt b/src/fsfw/timemanager/CMakeLists.txt index 00467772..7e38cc6a 100644 --- a/src/fsfw/timemanager/CMakeLists.txt +++ b/src/fsfw/timemanager/CMakeLists.txt @@ -1,8 +1,4 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - CCSDSTime.cpp - Countdown.cpp - Stopwatch.cpp - TimeMessage.cpp - TimeStamper.cpp - ClockCommon.cpp -) +target_sources( + ${LIB_FSFW_NAME} + PRIVATE CCSDSTime.cpp Countdown.cpp Stopwatch.cpp TimeMessage.cpp + CdsShortTimeStamper.cpp ClockCommon.cpp) diff --git a/src/fsfw/timemanager/CcsdsTimeStampReader.cpp b/src/fsfw/timemanager/CcsdsTimeStampReader.cpp new file mode 100644 index 00000000..d23d0387 --- /dev/null +++ b/src/fsfw/timemanager/CcsdsTimeStampReader.cpp @@ -0,0 +1,14 @@ +#include "CcsdsTimeStampReader.h" + +#include "CCSDSTime.h" + +ReturnValue_t CcsdsTimestampReader::readTimeStamp(const uint8_t* buffer, uint8_t maxSize) { + ReturnValue_t result = CCSDSTime::convertFromCcsds(&time, buffer, ×tampLen, maxSize); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return result; +} + +timeval& CcsdsTimestampReader::getTime() { return time; } +size_t CcsdsTimestampReader::getTimestampLen() { return timestampLen; } diff --git a/src/fsfw/timemanager/CcsdsTimeStampReader.h b/src/fsfw/timemanager/CcsdsTimeStampReader.h new file mode 100644 index 00000000..0bec2553 --- /dev/null +++ b/src/fsfw/timemanager/CcsdsTimeStampReader.h @@ -0,0 +1,17 @@ +#ifndef FSFW_TIMEMANAGER_CCSDSTIMESTAMPREADER_H +#define FSFW_TIMEMANAGER_CCSDSTIMESTAMPREADER_H + +#include + +#include "TimeReaderIF.h" + +class CcsdsTimestampReader : public TimeReaderIF { + public: + timeval& getTime() override; + + private: + timeval time{}; + size_t timestampLen = 0; +}; + +#endif // FSFW_TIMEMANAGER_CCSDSTIMESTAMPREADER_H diff --git a/src/fsfw/timemanager/CdsShortTimeStamper.cpp b/src/fsfw/timemanager/CdsShortTimeStamper.cpp new file mode 100644 index 00000000..aa259029 --- /dev/null +++ b/src/fsfw/timemanager/CdsShortTimeStamper.cpp @@ -0,0 +1,53 @@ +#include "fsfw/timemanager/CdsShortTimeStamper.h" + +#include + +#include "fsfw/timemanager/Clock.h" + +CdsShortTimeStamper::CdsShortTimeStamper() : SystemObject(0, false) {} + +CdsShortTimeStamper::CdsShortTimeStamper(object_id_t objectId) : SystemObject(objectId) {} + +ReturnValue_t CdsShortTimeStamper::serialize(uint8_t **buffer, size_t *size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const { + if (*size + getSerializedSize() > maxSize) { + return SerializeIF::BUFFER_TOO_SHORT; + } + timeval now{}; + Clock::getClock_timeval(&now); + CCSDSTime::CDS_short cds{}; + ReturnValue_t result = CCSDSTime::convertToCcsds(&cds, &now); + if (result != returnvalue::OK) { + return result; + } + std::memcpy(*buffer, &cds, sizeof(cds)); + *buffer += getSerializedSize(); + *size += getSerializedSize(); + return result; +} + +size_t CdsShortTimeStamper::getSerializedSize() const { return getTimestampSize(); } + +ReturnValue_t CdsShortTimeStamper::deSerialize(const uint8_t **buffer, size_t *size, + SerializeIF::Endianness streamEndianness) { + if (size == nullptr or buffer == nullptr) { + return returnvalue::FAILED; + } + if (*size < getTimestampSize()) { + return SerializeIF::STREAM_TOO_SHORT; + } + size_t foundLen = 0; + if (((**buffer >> 4) & 0b111) != CCSDSTime::TimeCodeIdentification::CDS) { + return BAD_TIMESTAMP; + } + auto res = CCSDSTime::convertFromCcsds(&readTime, *buffer, &foundLen, *size); + if (res == returnvalue::OK) { + *size -= getSerializedSize(); + *buffer += getSerializedSize(); + } + return res; +} + +timeval &CdsShortTimeStamper::getTime() { return readTime; } + +size_t CdsShortTimeStamper::getTimestampSize() const { return TIMESTAMP_LEN; } diff --git a/src/fsfw/timemanager/CdsShortTimeStamper.h b/src/fsfw/timemanager/CdsShortTimeStamper.h new file mode 100644 index 00000000..a16a07b6 --- /dev/null +++ b/src/fsfw/timemanager/CdsShortTimeStamper.h @@ -0,0 +1,41 @@ +#ifndef FSFW_TIMEMANAGER_TIMESTAMPER_H_ +#define FSFW_TIMEMANAGER_TIMESTAMPER_H_ + +#include "CCSDSTime.h" +#include "TimeReaderIF.h" +#include "TimeWriterIF.h" +#include "fsfw/objectmanager/SystemObject.h" + +/** + * @brief Time stamper which can be used to add any timestamp to a + * given buffer. + * @details + * This time stamper uses the CCSDS CDC short timestamp as a fault timestamp. + * This timestamp has a size of 8 bytes. A custom timestamp can be used by + * overriding the #addTimeStamp function. + * @ingroup utility + */ +class CdsShortTimeStamper : public TimeWriterIF, public TimeReaderIF, public SystemObject { + public: + static constexpr size_t TIMESTAMP_LEN = 7; + CdsShortTimeStamper(); + /** + * @brief Default constructor which also registers the time stamper as a + * system object so it can be found with the #objectManager. + * @param objectId + */ + explicit CdsShortTimeStamper(object_id_t objectId); + + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override; + [[nodiscard]] size_t getSerializedSize() const override; + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override; + timeval &getTime() override; + [[nodiscard]] size_t getTimestampSize() const override; + + private: + timeval readTime{}; +}; + +#endif /* FSFW_TIMEMANAGER_TIMESTAMPER_H_ */ diff --git a/src/fsfw/timemanager/Clock.h b/src/fsfw/timemanager/Clock.h index 75c898e5..83bc3d9f 100644 --- a/src/fsfw/timemanager/Clock.h +++ b/src/fsfw/timemanager/Clock.h @@ -6,12 +6,12 @@ #include "clockDefinitions.h" #include "fsfw/globalfunctions/timevalOperations.h" #include "fsfw/ipc/MutexFactory.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #ifdef WIN32 #include #else -#include +#include #endif class Clock { @@ -33,12 +33,12 @@ class Clock { * * @deprecated, we should not worry about ticks, but only time */ - static uint32_t getTicksPerSecond(void); + static uint32_t getTicksPerSecond(); /** * This system call sets the system time. * To set the time, it uses a TimeOfDay_t struct. * @param time The struct with the time settings to set. - * @return -@c RETURN_OK on success. Otherwise, the OS failure code + * @return -@c returnvalue::OK on success. Otherwise, the OS failure code * is returned. */ static ReturnValue_t setClock(const TimeOfDay_t *time); @@ -46,7 +46,7 @@ class Clock { * This system call sets the system time. * To set the time, it uses a timeval struct. * @param time The struct with the time settings to set. - * @return -@c RETURN_OK on success. Otherwise, the OS failure code is returned. + * @return -@c returnvalue::OK on success. Otherwise, the OS failure code is returned. */ static ReturnValue_t setClock(const timeval *time); /** @@ -54,7 +54,7 @@ class Clock { * The timval format has the fields @c tv_sec with seconds and @c tv_usec with * microseconds since an OS-defined epoch. * @param time A pointer to a timeval struct where the current time is stored. - * @return @c RETURN_OK on success. Otherwise, the OS failure code is returned. + * @return @c returnvalue::OK on success. Otherwise, the OS failure code is returned. */ static ReturnValue_t getClock_timeval(timeval *time); @@ -62,7 +62,7 @@ class Clock { * Get the time since boot in a timeval struct * * @param[out] time A pointer to a timeval struct where the uptime is stored. - * @return @c RETURN_OK on success. Otherwise, the OS failure code is returned. + * @return @c returnvalue::OK on success. Otherwise, the OS failure code is returned. * * @deprecated, I do not think this should be able to fail, use timeval getUptime() */ @@ -77,7 +77,7 @@ class Clock { * between two calls up to 49 days by always using uint32_t in the calculation * * @param ms uptime in ms - * @return RETURN_OK on success. Otherwise, the OS failure code is returned. + * @return returnvalue::OK on success. Otherwise, the OS failure code is returned. */ static ReturnValue_t getUptime(uint32_t *uptimeMs); @@ -86,7 +86,7 @@ class Clock { * The time is returned in a 64 bit unsigned integer. * @param time A pointer to a 64 bit unisigned integer where the data is stored. * @return - * - @c RETURN_OK on success. + * - @c returnvalue::OK on success. * - Otherwise, the OS failure code is returned. */ static ReturnValue_t getClock_usecs(uint64_t *time); @@ -94,7 +94,7 @@ class Clock { * Returns the time in a TimeOfDay_t struct. * @param time A pointer to a TimeOfDay_t struct. * @return - * - @c RETURN_OK on success. + * - @c returnvalue::OK on success. * - Otherwise, the OS failure code is returned. */ static ReturnValue_t getDateAndTime(TimeOfDay_t *time); @@ -111,7 +111,7 @@ class Clock { * @param time The time of day as input * @param timeval The corresponding seconds since the epoch. * @return - * - @c RETURN_OK on success. + * - @c returnvalue::OK on success. * - Otherwise, the OS failure code is returned. */ static ReturnValue_t convertTimeOfDayToTimeval(const TimeOfDay_t *from, timeval *to); @@ -122,7 +122,7 @@ class Clock { * * @param time seconds since unix epoch * @param[out] JD2000 days since J2000 - * @return @c RETURN_OK + * @return @c returnvalue::OK */ static ReturnValue_t convertTimevalToJD2000(timeval time, double *JD2000); @@ -136,8 +136,8 @@ class Clock { * @param utc timeval, corresponding to UTC time * @param[out] tt timeval, corresponding to Terrestial Time * @return - * - @c RETURN_OK on success - * - @c RETURN_FAILED if leapSeconds are not set + * - @c returnvalue::OK on success + * - @c returnvalue::FAILED if leapSeconds are not set */ static ReturnValue_t convertUTCToTT(timeval utc, timeval *tt); @@ -146,9 +146,9 @@ class Clock { * * @param leapSeconds_ * @return - * - @c RETURN_OK on success. + * - @c returnvalue::OK on success. */ - static ReturnValue_t setLeapSeconds(const uint16_t leapSeconds_); + static ReturnValue_t setLeapSeconds(uint16_t leapSeconds_); /** * Get the Leap Seconds since 1972 @@ -157,8 +157,8 @@ class Clock { * * @param[out] leapSeconds_ * @return - * - @c RETURN_OK on success. - * - @c RETURN_FAILED on error + * - @c returnvalue::OK on success. + * - @c returnvalue::FAILED on error */ static ReturnValue_t getLeapSeconds(uint16_t *leapSeconds_); @@ -166,8 +166,8 @@ class Clock { /** * Function to check and create the Mutex for the clock * @return - * - @c RETURN_OK on success. - * - Otherwise @c RETURN_FAILED if not able to create one + * - @c returnvalue::OK on success. + * - Otherwise @c returnvalue::FAILED if not able to create one */ static ReturnValue_t checkOrCreateClockMutex(); diff --git a/src/fsfw/timemanager/ClockCommon.cpp b/src/fsfw/timemanager/ClockCommon.cpp index ca8b12a4..d0ac9004 100644 --- a/src/fsfw/timemanager/ClockCommon.cpp +++ b/src/fsfw/timemanager/ClockCommon.cpp @@ -10,7 +10,7 @@ bool Clock::leapSecondsSet = false; ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) { uint16_t leapSeconds; ReturnValue_t result = getLeapSeconds(&leapSeconds); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } timeval leapSeconds_timeval = {0, 0}; @@ -23,33 +23,33 @@ ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) { *tt = utc + leapSeconds_timeval + UTCtoTAI1972 + TAItoTT; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { - if (checkOrCreateClockMutex() != HasReturnvaluesIF::RETURN_OK) { - return HasReturnvaluesIF::RETURN_FAILED; + if (checkOrCreateClockMutex() != returnvalue::OK) { + return returnvalue::FAILED; } MutexGuard helper(timeMutex); leapSeconds = leapSeconds_; leapSecondsSet = true; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { if (not leapSecondsSet) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - if (checkOrCreateClockMutex() != HasReturnvaluesIF::RETURN_OK) { - return HasReturnvaluesIF::RETURN_FAILED; + if (checkOrCreateClockMutex() != returnvalue::OK) { + return returnvalue::FAILED; } MutexGuard helper(timeMutex); *leapSeconds_ = leapSeconds; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* to) { @@ -58,13 +58,19 @@ ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* // in the Windows CRT is incompatible with the C standard but this should not be an issue for // this implementation ReturnValue_t result = checkOrCreateClockMutex(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } - MutexGuard helper(timeMutex); // gmtime writes its output in a global buffer which is not Thread Safe // Therefore we have to use a Mutex here + MutexGuard helper(timeMutex); +#ifdef PLATFORM_WIN + time_t time; + time = from->tv_sec; + timeInfo = gmtime(&time); +#else timeInfo = gmtime(&from->tv_sec); +#endif to->year = timeInfo->tm_year + 1900; to->month = timeInfo->tm_mon + 1; to->day = timeInfo->tm_mday; @@ -72,19 +78,19 @@ ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* to->minute = timeInfo->tm_min; to->second = timeInfo->tm_sec; to->usecond = from->tv_usec; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t Clock::checkOrCreateClockMutex() { if (timeMutex == nullptr) { MutexFactory* mutexFactory = MutexFactory::instance(); if (mutexFactory == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } timeMutex = mutexFactory->createMutex(); if (timeMutex == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/src/fsfw/timemanager/ReceivesTimeInfoIF.h b/src/fsfw/timemanager/ReceivesTimeInfoIF.h index 5fb915ae..a6067a33 100644 --- a/src/fsfw/timemanager/ReceivesTimeInfoIF.h +++ b/src/fsfw/timemanager/ReceivesTimeInfoIF.h @@ -1,7 +1,7 @@ #ifndef FSFW_TIMEMANAGER_RECEIVESTIMEINFOIF_H_ #define FSFW_TIMEMANAGER_RECEIVESTIMEINFOIF_H_ -#include "../ipc/MessageQueueSenderIF.h" +#include "fsfw/ipc/MessageQueueSenderIF.h" /** * This is a Interface for classes that receive timing information @@ -13,11 +13,11 @@ class ReceivesTimeInfoIF { * Returns the id of the queue which receives the timing information. * @return Queue id of the timing queue. */ - virtual MessageQueueId_t getTimeReceptionQueue() const = 0; + [[nodiscard]] virtual MessageQueueId_t getTimeReceptionQueue() const = 0; /** * Empty virtual destructor. */ - virtual ~ReceivesTimeInfoIF() {} + virtual ~ReceivesTimeInfoIF() = default; }; #endif /* FSFW_TIMEMANAGER_RECEIVESTIMEINFOIF_H_ */ diff --git a/src/fsfw/timemanager/TimeMessage.h b/src/fsfw/timemanager/TimeMessage.h index ae4a9caf..62833036 100644 --- a/src/fsfw/timemanager/TimeMessage.h +++ b/src/fsfw/timemanager/TimeMessage.h @@ -3,8 +3,8 @@ #include -#include "../ipc/MessageQueueMessage.h" #include "Clock.h" +#include "fsfw/ipc/MessageQueueMessage.h" class TimeMessage : public MessageQueueMessage { protected: diff --git a/src/fsfw/timemanager/TimeReaderIF.h b/src/fsfw/timemanager/TimeReaderIF.h new file mode 100644 index 00000000..aa64b754 --- /dev/null +++ b/src/fsfw/timemanager/TimeReaderIF.h @@ -0,0 +1,40 @@ +#ifndef FSFW_TIMEMANAGER_TIMEREADERIF_H +#define FSFW_TIMEMANAGER_TIMEREADERIF_H + +#include +#include + +#include "fsfw/platform.h" + +#ifdef PLATFORM_WIN +// wtf? Required for timeval! +#include +#endif + +#include "TimeStampIF.h" +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/serialize/SerializeIF.h" + +class TimeReaderIF : public SerializeIF, public TimeStampIF { + public: + ~TimeReaderIF() override = default; + virtual timeval& getTime() = 0; + + [[nodiscard]] size_t getSerializedSize() const override { return getTimestampSize(); } + + ReturnValue_t readTimeStamp(const uint8_t* buf, size_t maxSize) { + size_t dummy = 0; + return deSerialize(buf, dummy, maxSize, SerializeIF::Endianness::NETWORK); + } + + private: + /** + * Forbidden, use dedicated IF @TimeWriterIF + */ + [[nodiscard]] ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override { + return returnvalue::FAILED; + } +}; + +#endif // FSFW_TIMEMANAGER_TIMEREADERIF_H diff --git a/src/fsfw/timemanager/TimeStampIF.h b/src/fsfw/timemanager/TimeStampIF.h new file mode 100644 index 00000000..805cf3b1 --- /dev/null +++ b/src/fsfw/timemanager/TimeStampIF.h @@ -0,0 +1,20 @@ +#ifndef FSFW_TIMEMANAGER_TIMESTAMPIF_H +#define FSFW_TIMEMANAGER_TIMESTAMPIF_H + +#include + +#include "fsfw/retval.h" + +class TimeStampIF { + public: + static const uint8_t INTERFACE_ID = CLASS_ID::TIME_STAMPER_IF; + static const ReturnValue_t BAD_TIMESTAMP = MAKE_RETURN_CODE(1); + + // I am going to assume there are no larger timestamps + static constexpr size_t MAXIMUM_TIMESTAMP_LEN = 16; + + virtual ~TimeStampIF() = default; + [[nodiscard]] virtual size_t getTimestampSize() const = 0; +}; + +#endif // FSFW_TIMEMANAGER_TIMESTAMPIF_H diff --git a/src/fsfw/timemanager/TimeStamper.cpp b/src/fsfw/timemanager/TimeStamper.cpp deleted file mode 100644 index 9b4ad3d3..00000000 --- a/src/fsfw/timemanager/TimeStamper.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "fsfw/timemanager/TimeStamper.h" - -#include - -#include "fsfw/timemanager/Clock.h" - -TimeStamper::TimeStamper(object_id_t objectId) : SystemObject(objectId) {} - -ReturnValue_t TimeStamper::addTimeStamp(uint8_t* buffer, const uint8_t maxSize) { - if (maxSize < TimeStamperIF::MISSION_TIMESTAMP_SIZE) { - return HasReturnvaluesIF::RETURN_FAILED; - } - - timeval now; - Clock::getClock_timeval(&now); - CCSDSTime::CDS_short cds; - ReturnValue_t result = CCSDSTime::convertToCcsds(&cds, &now); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - std::memcpy(buffer, &cds, sizeof(cds)); - return result; -} diff --git a/src/fsfw/timemanager/TimeStamper.h b/src/fsfw/timemanager/TimeStamper.h deleted file mode 100644 index aa311ec4..00000000 --- a/src/fsfw/timemanager/TimeStamper.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef FSFW_TIMEMANAGER_TIMESTAMPER_H_ -#define FSFW_TIMEMANAGER_TIMESTAMPER_H_ - -#include "../objectmanager/SystemObject.h" -#include "CCSDSTime.h" -#include "TimeStamperIF.h" - -/** - * @brief Time stamper which can be used to add any timestamp to a - * given buffer. - * @details - * This time stamper uses the CCSDS CDC short timestamp as a fault timestamp. - * This timestamp has a size of 8 bytes. A custom timestamp can be used by - * overriding the #addTimeStamp function. - * @ingroup utility - */ -class TimeStamper : public TimeStamperIF, public SystemObject { - public: - /** - * @brief Default constructor which also registers the time stamper as a - * system object so it can be found with the #objectManager. - * @param objectId - */ - TimeStamper(object_id_t objectId); - - /** - * Adds a CCSDS CDC short 8 byte timestamp to the given buffer. - * This function can be overriden to use a custom timestamp. - * @param buffer - * @param maxSize - * @return - */ - virtual ReturnValue_t addTimeStamp(uint8_t* buffer, const uint8_t maxSize); -}; - -#endif /* FSFW_TIMEMANAGER_TIMESTAMPER_H_ */ diff --git a/src/fsfw/timemanager/TimeStamperIF.h b/src/fsfw/timemanager/TimeStamperIF.h deleted file mode 100644 index 5c3880ea..00000000 --- a/src/fsfw/timemanager/TimeStamperIF.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef FSFW_TIMEMANAGER_TIMESTAMPERIF_H_ -#define FSFW_TIMEMANAGER_TIMESTAMPERIF_H_ - -#include - -#include "../returnvalues/HasReturnvaluesIF.h" - -/** - * A class implementing this IF provides facilities to add a time stamp to the - * buffer provided. - * Implementors need to ensure that calling the method is thread-safe, i.e. - * addTimeStamp may be called in parallel from a different context. - */ -class TimeStamperIF { - public: - static const uint8_t INTERFACE_ID = CLASS_ID::TIME_STAMPER_IF; - static const ReturnValue_t BAD_TIMESTAMP = MAKE_RETURN_CODE(1); - - //! This is a mission-specific constant and determines the total - //! size reserved for timestamps. - static const uint8_t MISSION_TIMESTAMP_SIZE = fsfwconfig::FSFW_MISSION_TIMESTAMP_SIZE; - - virtual ReturnValue_t addTimeStamp(uint8_t* buffer, const uint8_t maxSize) = 0; - virtual ~TimeStamperIF() {} -}; - -#endif /* FSFW_TIMEMANAGER_TIMESTAMPERIF_H_ */ diff --git a/src/fsfw/timemanager/TimeWriterIF.h b/src/fsfw/timemanager/TimeWriterIF.h new file mode 100644 index 00000000..bc8aacc5 --- /dev/null +++ b/src/fsfw/timemanager/TimeWriterIF.h @@ -0,0 +1,34 @@ +#ifndef FSFW_TIMEMANAGER_TIMESTAMPERIF_H_ +#define FSFW_TIMEMANAGER_TIMESTAMPERIF_H_ + +#include "TimeStampIF.h" +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/serialize/SerializeIF.h" + +/** + * A class implementing this IF provides facilities to add a time stamp to the + * buffer provided. + * Implementors need to ensure that calling the method is thread-safe, i.e. + * addTimeStamp may be called in parallel from a different context. + */ +class TimeWriterIF : public SerializeIF, public TimeStampIF { + public: + ~TimeWriterIF() override = default; + [[nodiscard]] size_t getTimestampSize() const override { return getSerializedSize(); } + + ReturnValue_t addTimeStamp(uint8_t *buf, size_t maxSize) { + size_t dummy = 0; + return serialize(buf, dummy, maxSize, SerializeIF::Endianness::NETWORK); + } + + private: + /** + * Forbidden, use dedicated IF @TimeReaderIF + */ + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override { + return returnvalue::FAILED; + } +}; + +#endif /* FSFW_TIMEMANAGER_TIMESTAMPERIF_H_ */ diff --git a/src/fsfw/tmstorage/CMakeLists.txt b/src/fsfw/tmstorage/CMakeLists.txt index 7990d85a..80da7faf 100644 --- a/src/fsfw/tmstorage/CMakeLists.txt +++ b/src/fsfw/tmstorage/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - TmStoreMessage.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE TmStoreMessage.cpp) diff --git a/src/fsfw/tmstorage/TmStoreBackendIF.h b/src/fsfw/tmstorage/TmStoreBackendIF.h index d9f1a17b..84c94f77 100644 --- a/src/fsfw/tmstorage/TmStoreBackendIF.h +++ b/src/fsfw/tmstorage/TmStoreBackendIF.h @@ -3,7 +3,7 @@ #include "fsfw/objectmanager/SystemObjectIF.h" #include "fsfw/parameters/HasParametersIF.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/storagemanager/StorageManagerIF.h" #include "fsfw/timemanager/Clock.h" #include "tmStorageConf.h" diff --git a/src/fsfw/tmstorage/TmStoreFrontendIF.h b/src/fsfw/tmstorage/TmStoreFrontendIF.h index 3ab93ba1..56bcd7fa 100644 --- a/src/fsfw/tmstorage/TmStoreFrontendIF.h +++ b/src/fsfw/tmstorage/TmStoreFrontendIF.h @@ -3,7 +3,7 @@ #include "TmStorePackets.h" #include "fsfw/ipc/MessageQueueSenderIF.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "tmStorageConf.h" class TmPacketMinimal; @@ -28,7 +28,7 @@ class TmStoreFrontendIF { * @param packet Pointer to the newly received Space Packet. * @param address Start address of the packet found * @param isLastPacket Indicates if no more packets can be fetched. - * @return If more packets shall be fetched, RETURN_OK must be returned. + * @return If more packets shall be fetched, returnvalue::OK must be returned. * Any other code stops fetching packets. */ virtual ReturnValue_t packetRetrieved(TmPacketMinimal* packet, uint32_t address) = 0; diff --git a/src/fsfw/tmstorage/TmStoreMessage.cpp b/src/fsfw/tmstorage/TmStoreMessage.cpp index a6bab6c5..6165df6d 100644 --- a/src/fsfw/tmstorage/TmStoreMessage.cpp +++ b/src/fsfw/tmstorage/TmStoreMessage.cpp @@ -9,13 +9,13 @@ TmStoreMessage::TmStoreMessage() {} ReturnValue_t TmStoreMessage::setEnableStoringMessage(CommandMessage* cmd, bool setEnabled) { cmd->setCommand(ENABLE_STORING); cmd->setParameter(setEnabled); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t TmStoreMessage::setDeleteContentMessage(CommandMessage* cmd, ApidSsc upTo) { cmd->setCommand(DELETE_STORE_CONTENT); cmd->setParameter((upTo.apid << 16) + upTo.ssc); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t TmStoreMessage::setDownlinkContentMessage(CommandMessage* cmd, ApidSsc fromPacket, @@ -23,7 +23,7 @@ ReturnValue_t TmStoreMessage::setDownlinkContentMessage(CommandMessage* cmd, Api cmd->setCommand(DOWNLINK_STORE_CONTENT); cmd->setParameter((fromPacket.apid << 16) + fromPacket.ssc); cmd->setParameter2((toPacket.apid << 16) + toPacket.ssc); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ApidSsc TmStoreMessage::getPacketId1(CommandMessage* cmd) { @@ -86,7 +86,7 @@ bool TmStoreMessage::getAddToSelection(CommandMessage* cmd) { return (bool)cmd-> ReturnValue_t TmStoreMessage::setReportSelectionDefinitionMessage(CommandMessage* cmd) { cmd->setCommand(REPORT_SELECTION_DEFINITION); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void TmStoreMessage::setSelectionDefinitionReportMessage(CommandMessage* cmd, @@ -97,7 +97,7 @@ void TmStoreMessage::setSelectionDefinitionReportMessage(CommandMessage* cmd, ReturnValue_t TmStoreMessage::setReportStoreCatalogueMessage(CommandMessage* cmd) { cmd->setCommand(REPORT_STORE_CATALOGUE); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void TmStoreMessage::setStoreCatalogueReportMessage(CommandMessage* cmd, object_id_t objectId, @@ -127,18 +127,18 @@ ReturnValue_t TmStoreMessage::setDeleteBlocksMessage(CommandMessage* cmd, uint32 cmd->setCommand(DELETE_STORE_CONTENT_BLOCKS); cmd->setParameter(addressLow); cmd->setParameter2(addressHigh); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t TmStoreMessage::setDownlinkBlocksMessage(CommandMessage* cmd, uint32_t addressLow, uint32_t addressHigh) { cmd->setCommand(DOWNLINK_STORE_CONTENT_BLOCKS); cmd->setParameter(addressLow); cmd->setParameter2(addressHigh); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t TmStoreMessage::setIndexRequestMessage(CommandMessage* cmd) { cmd->setCommand(REPORT_INDEX_REQUEST); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void TmStoreMessage::setIndexReportMessage(CommandMessage* cmd, store_address_t storeId) { diff --git a/src/fsfw/tmstorage/TmStorePackets.h b/src/fsfw/tmstorage/TmStorePackets.h index d54b7b52..e519b3b7 100644 --- a/src/fsfw/tmstorage/TmStorePackets.h +++ b/src/fsfw/tmstorage/TmStorePackets.h @@ -7,8 +7,8 @@ #include "fsfw/serialize/SerialLinkedListAdapter.h" #include "fsfw/serialize/SerializeElement.h" #include "fsfw/timemanager/CCSDSTime.h" -#include "fsfw/timemanager/TimeStamperIF.h" -#include "fsfw/tmtcpacket/pus/tm/TmPacketMinimal.h" +#include "fsfw/timemanager/TimeWriterIF.h" +#include "fsfw/tmtcpacket/pus/tm/PusTmMinimal.h" #include "tmStorageConf.h" class ServiceSubservice : public SerialLinkedListAdapter { @@ -32,7 +32,7 @@ class ApidSsc : public SerializeIF { Endianness streamEndianness) const { ReturnValue_t result = SerializeAdapter::serialize(&apid, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return SerializeAdapter::serialize(&ssc, buffer, size, maxSize, streamEndianness); @@ -42,7 +42,7 @@ class ApidSsc : public SerializeIF { ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::deSerialize(&apid, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return SerializeAdapter::deSerialize(&ssc, buffer, size, streamEndianness); @@ -87,7 +87,7 @@ class TmPacketInformation : public SerializeIF { const uint8_t* pField = NULL; uint32_t size = 0; ReturnValue_t result = packet->getPacketTimeRaw(&pField, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return; } if (*pField == CCSDSTime::P_FIELD_CDS_SHORT && size <= TimeStamperIF::MISSION_TIMESTAMP_SIZE) { @@ -97,13 +97,13 @@ class TmPacketInformation : public SerializeIF { } timeval time = {0, 0}; result = packet->getPacketTime(&time); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return; } CCSDSTime::CDS_short cdsFormat; result = CCSDSTime::convertToCcsds(&cdsFormat, &time); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return; } memcpy(rawTimestamp, &cdsFormat, sizeof(cdsFormat)); @@ -196,24 +196,24 @@ class TmPacketInformation : public SerializeIF { Endianness streamEndianness) const { ReturnValue_t result = SerializeAdapter::serialize(&apid, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&sourceSequenceCount, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&serviceType, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&serviceSubtype, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::serialize(&subCounter, buffer, size, maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } SerialBufferAdapter adapter(rawTimestamp, sizeof(rawTimestamp)); @@ -234,23 +234,23 @@ class TmPacketInformation : public SerializeIF { ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::deSerialize(&apid, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::deSerialize(&sourceSequenceCount, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::deSerialize(&serviceType, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::deSerialize(&serviceSubtype, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = SerializeAdapter::deSerialize(&subCounter, buffer, size, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } SerialBufferAdapter adapter(rawTimestamp, sizeof(rawTimestamp)); diff --git a/src/fsfw/tmtcpacket/CMakeLists.txt b/src/fsfw/tmtcpacket/CMakeLists.txt index e1deaba9..e1b54efe 100644 --- a/src/fsfw/tmtcpacket/CMakeLists.txt +++ b/src/fsfw/tmtcpacket/CMakeLists.txt @@ -1,8 +1,4 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - SpacePacket.cpp - SpacePacketBase.cpp -) - +add_subdirectory(ccsds) +add_subdirectory(pus) add_subdirectory(cfdp) add_subdirectory(packetmatcher) -add_subdirectory(pus) \ No newline at end of file diff --git a/src/fsfw/tmtcpacket/ReadablePacketIF.h b/src/fsfw/tmtcpacket/ReadablePacketIF.h new file mode 100644 index 00000000..4f2f09e8 --- /dev/null +++ b/src/fsfw/tmtcpacket/ReadablePacketIF.h @@ -0,0 +1,15 @@ +#ifndef FSFW_TMTCPACKET_SPACEPACKETREADERIF_H +#define FSFW_TMTCPACKET_SPACEPACKETREADERIF_H + +#include "fsfw/tmtcpacket/ccsds/SpacePacketIF.h" + +class ReadablePacketIF { + public: + virtual ~ReadablePacketIF() = default; + + /** + * This method returns a raw uint8_t pointer to the readable data + */ + [[nodiscard]] virtual const uint8_t* getFullData() const = 0; +}; +#endif // FSFW_TMTCPACKET_SPACEPACKETREADERIF_H diff --git a/src/fsfw/tmtcpacket/RedirectableDataPointerIF.h b/src/fsfw/tmtcpacket/RedirectableDataPointerIF.h index 364feb4e..52b3df0a 100644 --- a/src/fsfw/tmtcpacket/RedirectableDataPointerIF.h +++ b/src/fsfw/tmtcpacket/RedirectableDataPointerIF.h @@ -3,7 +3,7 @@ #include -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" /** * @brief This interface can be used for classes which store a reference to data. It allows @@ -11,7 +11,7 @@ */ class RedirectableDataPointerIF { public: - virtual ~RedirectableDataPointerIF(){}; + virtual ~RedirectableDataPointerIF() = default; /** * Redirect the data pointer, but allow an implementation to change the data. @@ -22,12 +22,15 @@ class RedirectableDataPointerIF { * large enough * @param args Any additional user arguments required to set the data pointer * @return - * - RETURN_OK if the pointer was set successfully - * - RETURN_FAILED on general error of if the maximum size is too small + * - returnvalue::OK if the pointer was set successfully + * - returnvalue::FAILED on general error of if the maximum size is too small */ - virtual ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize, void* args = nullptr) = 0; + virtual ReturnValue_t setData(uint8_t* dataPtr, size_t size, void* args) = 0; + virtual ReturnValue_t setData(uint8_t* dataPtr, size_t size) { + return setData(dataPtr, size, nullptr); + } private: }; -#endif /* FSFW_SRC_FSFW_TMTCPACKET_PUS_TC_SETTABLEDATAPOINTERIF_H_ */ +#endif /* TMTCPACKET_PUS_TC_SETTABLEDATAPOINTERIF_H_ */ diff --git a/src/fsfw/tmtcpacket/SpacePacket.cpp b/src/fsfw/tmtcpacket/SpacePacket.cpp deleted file mode 100644 index c8ebbd97..00000000 --- a/src/fsfw/tmtcpacket/SpacePacket.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "fsfw/tmtcpacket/SpacePacket.h" - -#include - -#include "fsfw/tmtcpacket/ccsds_header.h" - -SpacePacket::SpacePacket(uint16_t packetDataLength, bool isTelecommand, uint16_t apid, - uint16_t sequenceCount) - : SpacePacketBase((uint8_t*)&this->localData) { - initSpacePacketHeader(isTelecommand, false, apid, sequenceCount); - this->setPacketSequenceCount(sequenceCount); - if (packetDataLength <= sizeof(this->localData.fields.buffer)) { - this->setPacketDataLength(packetDataLength); - } else { - this->setPacketDataLength(sizeof(this->localData.fields.buffer)); - } -} - -SpacePacket::~SpacePacket(void) {} - -bool SpacePacket::addWholeData(const uint8_t* p_Data, uint32_t packet_size) { - if (packet_size <= sizeof(this->data)) { - memcpy(&this->localData.byteStream, p_Data, packet_size); - return true; - } else { - return false; - } -} diff --git a/src/fsfw/tmtcpacket/SpacePacket.h b/src/fsfw/tmtcpacket/SpacePacket.h deleted file mode 100644 index 10140db1..00000000 --- a/src/fsfw/tmtcpacket/SpacePacket.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef SPACEPACKET_H_ -#define SPACEPACKET_H_ - -#include "SpacePacketBase.h" - -/** - * The SpacePacket class is a representation of a simple CCSDS Space Packet - * without (control over) a secondary header. - * It can be instantiated with a size smaller than \c PACKET_MAX_SIZE. Its - * main use is to serve as an idle packet in case no other packets are sent. - * For the ECSS PUS part the TcPacket and TmPacket classes are used. - * A pointer to \c local_data is passed to the \c SpacePacketBase parent class, - * so the parent's methods are reachable. - * @ingroup tmtcpackets - */ -class SpacePacket : public SpacePacketBase { - public: - static const uint16_t PACKET_MAX_SIZE = 1024; - /** - * The constructor initializes the packet and sets all header information - * according to the passed parameters. - * @param packetDataLength Sets the packet data length field and therefore specifies - * the size of the packet. - * @param isTelecommand Sets the packet type field to either TC (true) or TM (false). - * @param apid Sets the packet's APID field. The default value describes an idle packet. - * @param sequenceCount ets the packet's Source Sequence Count field. - */ - SpacePacket(uint16_t packetDataLength, bool isTelecommand = false, - uint16_t apid = APID_IDLE_PACKET, uint16_t sequenceCount = 0); - /** - * The class's default destructor. - */ - virtual ~SpacePacket(); - /** - * With this call, the complete data content (including the CCSDS Primary - * Header) is overwritten with the byte stream given. - * @param p_data Pointer to data to overwrite the content with - * @param packet_size Size of the data - * @return @li \c true if packet_size is smaller than \c MAX_PACKET_SIZE. - * @li \c false else. - */ - bool addWholeData(const uint8_t* p_data, uint32_t packet_size); - - protected: - /** - * This structure defines the data structure of a Space Packet as local data. - * There's a buffer which corresponds to the Space Packet Data Field with a - * maximum size of \c PACKET_MAX_SIZE. - */ - struct PacketStructured { - CCSDSPrimaryHeader header; - uint8_t buffer[PACKET_MAX_SIZE]; - }; - /** - * This union simplifies accessing the full data content of the Space Packet. - * This is achieved by putting the \c PacketStructured struct in a union with - * a plain buffer. - */ - union SpacePacketData { - PacketStructured fields; - uint8_t byteStream[PACKET_MAX_SIZE + sizeof(CCSDSPrimaryHeader)]; - }; - /** - * This is the data representation of the class. - * It is a struct of CCSDS Primary Header and a data field, which again is - * packed in an union, so the data can be accessed as a byte stream without - * a cast. - */ - SpacePacketData localData; -}; - -namespace spacepacket { - -constexpr uint16_t getSpacePacketIdFromApid(bool isTc, uint16_t apid, - bool secondaryHeaderFlag = true) { - return ((isTc << 4) | (secondaryHeaderFlag << 3) | ((apid >> 8) & 0x07)) << 8 | (apid & 0x00ff); -} - -constexpr uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag = true) { - return getSpacePacketIdFromApid(true, apid, secondaryHeaderFlag); -} - -constexpr uint16_t getTmSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag = true) { - return getSpacePacketIdFromApid(false, apid, secondaryHeaderFlag); -} - -} // namespace spacepacket - -#endif /* SPACEPACKET_H_ */ diff --git a/src/fsfw/tmtcpacket/SpacePacketBase.cpp b/src/fsfw/tmtcpacket/SpacePacketBase.cpp deleted file mode 100644 index 756d7e50..00000000 --- a/src/fsfw/tmtcpacket/SpacePacketBase.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include "fsfw/tmtcpacket/SpacePacketBase.h" - -#include - -#include "fsfw/serviceinterface/ServiceInterface.h" - -SpacePacketBase::SpacePacketBase(const uint8_t* setAddress) { - this->data = reinterpret_cast(const_cast(setAddress)); -} - -SpacePacketBase::~SpacePacketBase(){}; - -// CCSDS Methods: -uint8_t SpacePacketBase::getPacketVersionNumber(void) { - return (this->data->header.packet_id_h & 0b11100000) >> 5; -} - -ReturnValue_t SpacePacketBase::initSpacePacketHeader(bool isTelecommand, bool hasSecondaryHeader, - uint16_t apid, uint16_t sequenceCount) { - if (data == nullptr) { -#if FSFW_VERBOSE_LEVEL >= 1 -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "SpacePacketBase::initSpacePacketHeader: Data pointer is invalid" << std::endl; -#else - sif::printWarning("SpacePacketBase::initSpacePacketHeader: Data pointer is invalid!\n"); -#endif -#endif - return HasReturnvaluesIF::RETURN_FAILED; - } - // reset header to zero: - memset(data, 0, sizeof(this->data->header)); - // Set TC/TM bit. - data->header.packet_id_h = ((isTelecommand ? 1 : 0)) << 4; - // Set secondaryHeader bit - data->header.packet_id_h |= ((hasSecondaryHeader ? 1 : 0)) << 3; - this->setAPID(apid); - // Always initialize as standalone packets. - data->header.sequence_control_h = 0b11000000; - setPacketSequenceCount(sequenceCount); - return HasReturnvaluesIF::RETURN_OK; -} - -bool SpacePacketBase::isTelecommand(void) { - return (this->data->header.packet_id_h & 0b00010000) >> 4; -} - -bool SpacePacketBase::hasSecondaryHeader(void) { - return (this->data->header.packet_id_h & 0b00001000) >> 3; -} - -uint16_t SpacePacketBase::getPacketId() { - return ((this->data->header.packet_id_h) << 8) + this->data->header.packet_id_l; -} - -uint16_t SpacePacketBase::getAPID(void) const { - return ((this->data->header.packet_id_h & 0b00000111) << 8) + this->data->header.packet_id_l; -} - -void SpacePacketBase::setAPID(uint16_t new_apid) { - // Use first three bits of new APID, but keep rest of packet id as it was (see specification). - this->data->header.packet_id_h = - (this->data->header.packet_id_h & 0b11111000) | ((new_apid & 0x0700) >> 8); - this->data->header.packet_id_l = (new_apid & 0x00FF); -} - -void SpacePacketBase::setSequenceFlags(uint8_t sequenceflags) { - this->data->header.sequence_control_h &= 0x3F; - this->data->header.sequence_control_h |= sequenceflags << 6; -} - -uint16_t SpacePacketBase::getPacketSequenceControl(void) { - return ((this->data->header.sequence_control_h) << 8) + this->data->header.sequence_control_l; -} - -uint8_t SpacePacketBase::getSequenceFlags(void) { - return (this->data->header.sequence_control_h & 0b11000000) >> 6; -} - -uint16_t SpacePacketBase::getPacketSequenceCount(void) const { - return ((this->data->header.sequence_control_h & 0b00111111) << 8) + - this->data->header.sequence_control_l; -} - -void SpacePacketBase::setPacketSequenceCount(uint16_t new_count) { - this->data->header.sequence_control_h = (this->data->header.sequence_control_h & 0b11000000) | - (((new_count % LIMIT_SEQUENCE_COUNT) & 0x3F00) >> 8); - this->data->header.sequence_control_l = ((new_count % LIMIT_SEQUENCE_COUNT) & 0x00FF); -} - -uint16_t SpacePacketBase::getPacketDataLength() const { - return ((this->data->header.packet_length_h) << 8) + this->data->header.packet_length_l; -} - -void SpacePacketBase::setPacketDataLength(uint16_t new_length) { - this->data->header.packet_length_h = ((new_length & 0xFF00) >> 8); - this->data->header.packet_length_l = (new_length & 0x00FF); -} - -size_t SpacePacketBase::getFullSize() { - // +1 is done because size in packet data length field is: size of data field -1 - return this->getPacketDataLength() + sizeof(this->data->header) + 1; -} - -uint8_t* SpacePacketBase::getWholeData() { return (uint8_t*)this->data; } - -uint32_t SpacePacketBase::getApidAndSequenceCount() const { - return (getAPID() << 16) + getPacketSequenceCount(); -} - -uint8_t* SpacePacketBase::getPacketData() { return &(data->packet_data); } - -ReturnValue_t SpacePacketBase::setData(uint8_t* pData, size_t maxSize, void* args) { - if (maxSize < 6) { - return HasReturnvaluesIF::RETURN_FAILED; - } - this->data = reinterpret_cast(const_cast(pData)); - return HasReturnvaluesIF::RETURN_OK; -} diff --git a/src/fsfw/tmtcpacket/SpacePacketBase.h b/src/fsfw/tmtcpacket/SpacePacketBase.h deleted file mode 100644 index d9ee2b83..00000000 --- a/src/fsfw/tmtcpacket/SpacePacketBase.h +++ /dev/null @@ -1,192 +0,0 @@ -#ifndef FSFW_TMTCPACKET_SPACEPACKETBASE_H_ -#define FSFW_TMTCPACKET_SPACEPACKETBASE_H_ - -#include - -#include - -#include "ccsds_header.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" - -/** - * @defgroup tmtcpackets Space Packets - * This is the group, where all classes associated with Telecommand and - * Telemetry packets belong to. - * The class hierarchy resembles the dependency between the different standards - * applied, namely the CCSDS Space Packet standard and the ECCSS Packet - * Utilization Standard. Most field and structure names are taken from these - * standards. - */ - -/** - * This struct defines the data structure of a Space Packet when accessed - * via a pointer. - * @ingroup tmtcpackets - */ -struct SpacePacketPointer { - CCSDSPrimaryHeader header; - uint8_t packet_data; -}; - -/** - * This class is the basic data handler for any CCSDS Space Packet - * compatible Telecommand and Telemetry packet. - * It does not contain the packet data itself but a pointer to the - * data must be set on instantiation. An invalid pointer may cause - * damage, as no getter method checks data validity. Anyway, a NULL - * check can be performed by making use of the getWholeData method. - * Remark: All bit numbers in this documentation are counted from - * the most significant bit (from left). - * @ingroup tmtcpackets - */ -class SpacePacketBase : virtual public RedirectableDataPointerIF { - protected: - /** - * A pointer to a structure which defines the data structure of - * the packet header. - * To be hardware-safe, all elements are of byte size. - */ - SpacePacketPointer* data; - - public: - static const uint16_t LIMIT_APID = 2048; // 2^1 - static const uint16_t LIMIT_SEQUENCE_COUNT = 16384; // 2^14 - static const uint16_t APID_IDLE_PACKET = 0x7FF; - static const uint8_t TELECOMMAND_PACKET = 1; - static const uint8_t TELEMETRY_PACKET = 0; - /** - * This definition defines the CRC size in byte. - */ - static const uint8_t CRC_SIZE = 2; - /** - * This is the minimum size of a SpacePacket. - */ - static const uint16_t MINIMUM_SIZE = sizeof(CCSDSPrimaryHeader) + CRC_SIZE; - /** - * This is the default constructor. - * It sets its internal data pointer to the address passed. - * @param set_address The position where the packet data lies. - */ - SpacePacketBase(const uint8_t* set_address); - /** - * No data is allocated, so the destructor is empty. - */ - virtual ~SpacePacketBase(); - - // CCSDS Methods: - /** - * Getter for the packet version number field. - * @return Returns the highest three bit of the packet in one byte. - */ - uint8_t getPacketVersionNumber(void); - /** - * This method checks the type field in the header. - * This bit specifies, if the command is interpreted as Telecommand of - * as Telemetry. For a Telecommand, the bit is set. - * @return Returns true if the bit is set and false if not. - */ - bool isTelecommand(void); - - ReturnValue_t initSpacePacketHeader(bool isTelecommand, bool hasSecondaryHeader, uint16_t apid, - uint16_t sequenceCount = 0); - /** - * The CCSDS header provides a secondary header flag (the fifth-highest bit), - * which is checked with this method. - * @return Returns true if the bit is set and false if not. - */ - bool hasSecondaryHeader(void); - /** - * Returns the complete first two bytes of the packet, which together form - * the CCSDS packet id. - * @return The CCSDS packet id. - */ - uint16_t getPacketId(void); - /** - * Returns the APID of a packet, which are the lowest 11 bit of the packet - * id. - * @return The CCSDS APID. - */ - uint16_t getAPID(void) const; - /** - * Sets the APID of a packet, which are the lowest 11 bit of the packet - * id. - * @param The APID to set. The highest five bits of the parameter are - * ignored. - */ - void setAPID(uint16_t setAPID); - - /** - * Sets the sequence flags of a packet, which are bit 17 and 18 in the space packet header. - * @param The sequence flags to set - */ - void setSequenceFlags(uint8_t sequenceflags); - - /** - * Returns the CCSDS packet sequence control field, which are the third and - * the fourth byte of the CCSDS primary header. - * @return The CCSDS packet sequence control field. - */ - uint16_t getPacketSequenceControl(void); - /** - * Returns the SequenceFlags, which are the highest two bit of the packet - * sequence control field. - * @return The CCSDS sequence flags. - */ - uint8_t getSequenceFlags(void); - /** - * Returns the packet sequence count, which are the lowest 14 bit of the - * packet sequence control field. - * @return The CCSDS sequence count. - */ - uint16_t getPacketSequenceCount(void) const; - /** - * Sets the packet sequence count, which are the lowest 14 bit of the - * packet sequence control field. - * setCount is modulo-divided by \c LIMIT_SEQUENCE_COUNT to avoid overflows. - * @param setCount The value to set the count to. - */ - void setPacketSequenceCount(uint16_t setCount); - /** - * Returns the packet data length, which is the fifth and sixth byte of the - * CCSDS Primary Header. The packet data length is the size of every kind - * of data \b after the CCSDS Primary Header \b -1. - * @return - * The CCSDS packet data length. uint16_t is sufficient, - * because this is limit in CCSDS standard - */ - uint16_t getPacketDataLength(void) const; - /** - * Sets the packet data length, which is the fifth and sixth byte of the - * CCSDS Primary Header. - * @param setLength The value of the length to set. It must fit the true - * CCSDS packet data length . The packet data length is - * the size of every kind of data \b after the CCSDS - * Primary Header \b -1. - */ - void setPacketDataLength(uint16_t setLength); - - // Helper methods: - /** - * This method returns a raw uint8_t pointer to the packet. - * @return A \c uint8_t pointer to the first byte of the CCSDS primary header. - */ - virtual uint8_t* getWholeData(void); - - uint8_t* getPacketData(); - - /** - * With this method, the packet data pointer can be redirected to another - * location. - * @param p_Data A pointer to another raw Space Packet. - */ - virtual ReturnValue_t setData(uint8_t* p_Data, size_t maxSize, void* args = nullptr) override; - /** - * This method returns the full raw packet size. - * @return The full size of the packet in bytes. - */ - size_t getFullSize(); - - uint32_t getApidAndSequenceCount() const; -}; - -#endif /* FSFW_TMTCPACKET_SPACEPACKETBASE_H_ */ diff --git a/src/fsfw/tmtcpacket/ccsds/CMakeLists.txt b/src/fsfw/tmtcpacket/ccsds/CMakeLists.txt new file mode 100644 index 00000000..68efe09c --- /dev/null +++ b/src/fsfw/tmtcpacket/ccsds/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE SpacePacketReader.cpp + SpacePacketCreator.cpp header.cpp) diff --git a/src/fsfw/tmtcpacket/ccsds/PacketId.h b/src/fsfw/tmtcpacket/ccsds/PacketId.h new file mode 100644 index 00000000..5b61db7d --- /dev/null +++ b/src/fsfw/tmtcpacket/ccsds/PacketId.h @@ -0,0 +1,87 @@ +#ifndef FSFW_TMTCPACKET_PACKETID_H +#define FSFW_TMTCPACKET_PACKETID_H + +#include + +#include "defs.h" +#include "fsfw/serialize/SerializeAdapter.h" +#include "fsfw/serialize/SerializeIF.h" + +struct PacketId : public SerializeIF { + public: + PacketId() = default; + /** + * Simple wrapper for Space Packet IDs. Does not check the APID for validity + * @param packetType_ + * @param secHeaderFlag_ + * @param apid_ + */ + PacketId(ccsds::PacketType packetType_, bool secHeaderFlag_, uint16_t apid_) + : packetType(packetType_), secHeaderFlag(secHeaderFlag_), apid(apid_) {} + + bool operator==(const PacketId &other) const { + return packetType == other.packetType and secHeaderFlag == other.secHeaderFlag and + apid == other.apid; + } + /** + * NOTE: If the APID has an invalid value, the invalid bits will be cut off + * @return + */ + [[nodiscard]] uint16_t raw() const { + return (static_cast(packetType) << 12) | + (static_cast(secHeaderFlag) << 11) | (apid & 0x7ff); + } + + static PacketId fromRaw(uint16_t raw) { + uint8_t highByte = (raw >> 8) & 0xff; + uint8_t lowByte = raw & 0xff; + return {static_cast((highByte >> 4) & 0b1), + static_cast((highByte >> 3) & 0b1), + static_cast((highByte & 0b111) << 8 | lowByte)}; + } + + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override { + if (*size + getSerializedSize() > maxSize) { + return SerializeIF::BUFFER_TOO_SHORT; + } + uint16_t idRaw = raw(); + // Leave the first three bits untouched, they could generally contain the CCSDS version, + // or more generally, the packet ID is a 13 bit field + **buffer &= ~0x1f; + **buffer |= (idRaw >> 8) & 0x1f; + *size += 1; + *buffer += 1; + **buffer = idRaw & 0xff; + *size += 1; + *buffer += 1; + return returnvalue::OK; + } + + [[nodiscard]] size_t getSerializedSize() const override { return 2; } + + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override { + if (*size < 2) { + return SerializeIF::STREAM_TOO_SHORT; + } + uint8_t highByte = **buffer; + *buffer += 1; + uint8_t lowByte = **buffer; + *buffer += 1; + *size -= 2; + packetType = static_cast((highByte >> 4) & 0b1); + secHeaderFlag = (highByte >> 3) & 0b1; + apid = static_cast((highByte & 0b111) << 8 | lowByte); + return returnvalue::OK; + } + + ccsds::PacketType packetType = ccsds::PacketType::TM; + bool secHeaderFlag = false; + uint16_t apid = 0; + + using SerializeIF::deSerialize; + using SerializeIF::serialize; +}; + +#endif // FSFW_TMTCPACKET_PACKETID_H diff --git a/src/fsfw/tmtcpacket/ccsds/PacketSeqCtrl.h b/src/fsfw/tmtcpacket/ccsds/PacketSeqCtrl.h new file mode 100644 index 00000000..1944e8c2 --- /dev/null +++ b/src/fsfw/tmtcpacket/ccsds/PacketSeqCtrl.h @@ -0,0 +1,63 @@ +#ifndef FSFW_TMTCPACKET_PACKETSEQCTRL_H +#define FSFW_TMTCPACKET_PACKETSEQCTRL_H + +#include "defs.h" +#include "fsfw/serialize/SerializeAdapter.h" +#include "fsfw/serialize/SerializeIF.h" + +struct PacketSeqCtrl : public SerializeIF { + public: + PacketSeqCtrl() = default; + + PacketSeqCtrl(ccsds::SequenceFlags seqFlags, uint16_t seqCount) + : seqFlags(seqFlags), seqCount(seqCount) {} + + bool operator==(const PacketSeqCtrl &other) const { + return seqCount == other.seqCount and seqFlags == other.seqFlags; + } + + /** + * NOTE: If the sequence control has an invalid value, the invalid bits will be cut off + * @return + */ + [[nodiscard]] uint16_t raw() const { + return (static_cast(seqFlags) << 14) | (seqCount & 0x3FFF); + } + + static PacketSeqCtrl fromRaw(uint16_t raw) { + uint8_t highByte = (raw >> 8) & 0xff; + uint8_t lowByte = raw & 0xff; + return {static_cast((highByte >> 6) & 0b11), + static_cast(((highByte << 8) | lowByte) & 0x3FFF)}; + } + + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override { + uint16_t packetIdRaw = raw(); + return SerializeAdapter::serialize(&packetIdRaw, buffer, size, maxSize, streamEndianness); + } + [[nodiscard]] size_t getSerializedSize() const override { return 2; } + + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override { + if (*size < 2) { + return SerializeIF::STREAM_TOO_SHORT; + } + uint8_t highByte = **buffer; + *buffer += 1; + uint8_t lowByte = **buffer; + *buffer += 1; + *size -= 2; + seqFlags = static_cast((highByte >> 6) & 0b11); + seqCount = ((highByte << 8) | lowByte) & 0x3FFF; + return returnvalue::OK; + } + + ccsds::SequenceFlags seqFlags = ccsds::SequenceFlags::CONTINUATION; + uint16_t seqCount = 0; + + using SerializeIF::deSerialize; + using SerializeIF::serialize; +}; + +#endif // FSFW_TMTCPACKET_PACKETSEQCTRL_H diff --git a/src/fsfw/tmtcpacket/ccsds/SpacePacketCreator.cpp b/src/fsfw/tmtcpacket/ccsds/SpacePacketCreator.cpp new file mode 100644 index 00000000..745d5834 --- /dev/null +++ b/src/fsfw/tmtcpacket/ccsds/SpacePacketCreator.cpp @@ -0,0 +1,94 @@ +#include "SpacePacketCreator.h" + +#include + +#include "fsfw/serialize/SerializeAdapter.h" + +SpacePacketCreator::SpacePacketCreator(SpacePacketParams params_) : params(std::move(params_)) { + checkFieldValidity(); +} + +SpacePacketCreator::SpacePacketCreator(ccsds::PacketType packetType, bool secHeaderFlag, + uint16_t apid, ccsds::SequenceFlags seqFlags, + uint16_t seqCount, uint16_t dataLen, uint8_t version) + : params(SpacePacketParams(PacketId(packetType, secHeaderFlag, apid), + PacketSeqCtrl(seqFlags, seqCount), dataLen)) { + params.version = version; + checkFieldValidity(); +} + +uint16_t SpacePacketCreator::getPacketIdRaw() const { return params.packetId.raw(); } +uint16_t SpacePacketCreator::getPacketSeqCtrlRaw() const { return params.packetSeqCtrl.raw(); } +uint16_t SpacePacketCreator::getPacketDataLen() const { return params.dataLen; } + +ReturnValue_t SpacePacketCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const { + if (not isValid()) { + return returnvalue::FAILED; + } + uint16_t packetIdAndVersion = + (static_cast(params.version) << 13) | params.packetId.raw(); + ReturnValue_t result = + SerializeAdapter::serialize(&packetIdAndVersion, buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + uint16_t pscRaw = params.packetSeqCtrl.raw(); + result = SerializeAdapter::serialize(&pscRaw, buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + return SerializeAdapter::serialize(¶ms.dataLen, buffer, size, maxSize, streamEndianness); +} + +void SpacePacketCreator::setCcsdsLenFromTotalDataFieldLen(size_t actualLength) { + if (actualLength == 0) { + return; + } + setDataLenField(actualLength - 1); +} +size_t SpacePacketCreator::getSerializedSize() const { return ccsds::HEADER_LEN; } + +ReturnValue_t SpacePacketCreator::deSerialize(const uint8_t **buffer, size_t *size, + SerializeIF::Endianness streamEndianness) { + return returnvalue::FAILED; +} +bool SpacePacketCreator::isValid() const { return valid; } + +void SpacePacketCreator::setApid(uint16_t apid) { + if (apid < ccsds::LIMIT_APID) { + params.packetId.apid = apid; + } + checkFieldValidity(); +} + +void SpacePacketCreator::setSeqCount(uint16_t seqCount) { + if (seqCount < ccsds::LIMIT_SEQUENCE_COUNT) { + params.packetSeqCtrl.seqCount = seqCount; + } + checkFieldValidity(); +} +void SpacePacketCreator::setSeqFlags(ccsds::SequenceFlags flags) { + params.packetSeqCtrl.seqFlags = flags; +} +void SpacePacketCreator::setDataLenField(uint16_t dataLen_) { params.dataLen = dataLen_; } +void SpacePacketCreator::checkFieldValidity() { + valid = true; + if (params.packetId.apid > ccsds::LIMIT_APID or + params.packetSeqCtrl.seqCount > ccsds::LIMIT_SEQUENCE_COUNT) { + valid = false; + } +} + +void SpacePacketCreator::setParams(SpacePacketParams params_) { params = std::move(params_); } + +SpacePacketParams &SpacePacketCreator::getParams() { return params; } + +void SpacePacketCreator::setPacketType(ccsds::PacketType type) { + params.packetId.packetType = type; +} +bool SpacePacketCreator::operator==(const SpacePacketCreator &other) const { return false; } + +SpacePacketCreator::operator bool() const { return isValid(); } + +void SpacePacketCreator::setSecHeaderFlag() { params.packetId.secHeaderFlag = true; } diff --git a/src/fsfw/tmtcpacket/ccsds/SpacePacketCreator.h b/src/fsfw/tmtcpacket/ccsds/SpacePacketCreator.h new file mode 100644 index 00000000..59234a1b --- /dev/null +++ b/src/fsfw/tmtcpacket/ccsds/SpacePacketCreator.h @@ -0,0 +1,88 @@ +#ifndef FSFW_TMTCPACKET_SPACEPACKETCREATOR_H +#define FSFW_TMTCPACKET_SPACEPACKETCREATOR_H + +#include + +#include "PacketId.h" +#include "PacketSeqCtrl.h" +#include "SpacePacketIF.h" +#include "fsfw/serialize/SerializeIF.h" + +struct SpacePacketParams { + SpacePacketParams() = default; + + SpacePacketParams(PacketId packetId, PacketSeqCtrl psc, uint16_t dataLen) + : packetId(std::move(packetId)), packetSeqCtrl(std::move(psc)), dataLen(dataLen) {} + + PacketId packetId{}; + PacketSeqCtrl packetSeqCtrl{}; + uint16_t dataLen = 0; + uint8_t version = 0b000; +}; + +class SpacePacketCreator : public SpacePacketIF, public SerializeIF { + public: + SpacePacketCreator() = default; + explicit SpacePacketCreator(SpacePacketParams params); + + bool operator==(const SpacePacketCreator &other) const; + explicit operator bool() const; + + SpacePacketCreator(ccsds::PacketType packetType, bool secHeaderFlag, uint16_t apid, + ccsds::SequenceFlags seqFlags, uint16_t seqCount, uint16_t dataLen, + uint8_t version = 0); + + [[nodiscard]] bool isValid() const; + [[nodiscard]] uint16_t getPacketIdRaw() const override; + [[nodiscard]] uint16_t getPacketSeqCtrlRaw() const override; + [[nodiscard]] uint16_t getPacketDataLen() const override; + + SpacePacketParams &getParams(); + /** + * Sets the CCSDS data length field from the actual data field length. The field will contain + * the actual length minus one. This means that the minimum allowed size is one, as is also + * specified in 4.1.4.1.2 of the standard. Values of 0 will be ignored. + * @param dataFieldLen + */ + void setCcsdsLenFromTotalDataFieldLen(size_t dataFieldLen); + void setParams(SpacePacketParams params); + void setSecHeaderFlag(); + void setPacketType(ccsds::PacketType type); + void setApid(uint16_t apid); + void setSeqCount(uint16_t seqCount); + void setSeqFlags(ccsds::SequenceFlags flags); + void setDataLenField(uint16_t dataLen); + + /** + * Please note that this method will only serialize the header part of the space packet. + * @param buffer + * @param size + * @param maxSize + * @param streamEndianness + * @return + */ + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override; + + /** + * This will always return 6 or ccsds::HEADER_LEN + * @return + */ + [[nodiscard]] size_t getSerializedSize() const override; + + private: + void checkFieldValidity(); + bool valid{}; + SpacePacketParams params{}; + + /** + * Forbidden to call and always return HasReturnvaluesIF::RETURN_FAILED + * @param buffer + * @param size + * @param streamEndianness + * @return + */ + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override; +}; +#endif // FSFW_TMTCPACKET_SPACEPACKETCREATOR_H diff --git a/src/fsfw/tmtcpacket/ccsds/SpacePacketIF.h b/src/fsfw/tmtcpacket/ccsds/SpacePacketIF.h new file mode 100644 index 00000000..41d087ad --- /dev/null +++ b/src/fsfw/tmtcpacket/ccsds/SpacePacketIF.h @@ -0,0 +1,97 @@ +#ifndef FSFW_TMTCPACKET_SPACEPACKETIF_H +#define FSFW_TMTCPACKET_SPACEPACKETIF_H + +#include +#include + +#include "PacketId.h" +#include "PacketSeqCtrl.h" +#include "fsfw/tmtcpacket/ccsds/defs.h" +#include "header.h" + +class SpacePacketIF { + public: + /** + * This definition defines the CRC size in byte. + */ + static const uint8_t CRC_SIZE = 2; + /** + * This is the minimum size of a SpacePacket. + */ + static const uint16_t MIN_CCSDS_SIZE = sizeof(ccsds::PrimaryHeader) + CRC_SIZE; + + virtual ~SpacePacketIF() = default; + + /** + * CCSDS header always has 6 bytes + * @return + */ + static constexpr size_t getHeaderLen() { return ccsds::HEADER_LEN; } + + /** + * Returns the complete first two bytes of the packet, which together form + * the CCSDS packet ID + * @return The CCSDS packet ID + */ + [[nodiscard]] virtual uint16_t getPacketIdRaw() const = 0; + /** + * Returns the third and the fourth byte of the CCSDS header which are the packet sequence + * control field + * @return + */ + [[nodiscard]] virtual uint16_t getPacketSeqCtrlRaw() const = 0; + /** + * Returns the fifth and the sixth byte of the CCSDS header which is the packet length field + * @return + */ + [[nodiscard]] virtual uint16_t getPacketDataLen() const = 0; + + virtual PacketId getPacketId() { return PacketId::fromRaw(getPacketIdRaw()); } + + virtual PacketSeqCtrl getPacketSeqCtrl() { return PacketSeqCtrl::fromRaw(getPacketSeqCtrlRaw()); } + + [[nodiscard]] virtual uint16_t getApid() const { + // Uppermost 11 bits of packet ID + return getPacketIdRaw() & 0x7ff; + } + + /** + * Returns the CCSDS version number + * @return + */ + [[nodiscard]] virtual uint8_t getVersion() const { + uint16_t packetId = getPacketIdRaw(); + return (packetId >> 13) & 0b111; + } + + [[nodiscard]] virtual ccsds::PacketType getPacketType() const { + return static_cast((getPacketIdRaw() >> 12) & 0b1); + } + + [[nodiscard]] virtual bool isTc() const { return getPacketType() == ccsds::PacketType::TC; } + + [[nodiscard]] virtual bool isTm() const { return not isTc(); } + + /** + * The CCSDS header provides a secondary header flag (the fifth-highest bit), + * which is checked with this method. + * @return Returns true if the bit is set and false if not. + */ + [[nodiscard]] virtual bool hasSecHeader() const { return (getPacketIdRaw() >> 11) & 0b1; } + + [[nodiscard]] virtual ccsds::SequenceFlags getSequenceFlags() const { + return static_cast(getPacketSeqCtrlRaw() >> 14 & 0b11); + } + + [[nodiscard]] virtual uint16_t getSequenceCount() const { return getPacketSeqCtrlRaw() & 0x3FFF; } + + /** + * Returns the full packet length based of the packet data length field + * @return + */ + [[nodiscard]] virtual size_t getFullPacketLen() const { + return ccsds::HEADER_LEN + getPacketDataLen() + 1; + } +}; + +#endif // FSFW_TMTCPACKET_SPACEPACKETIF_H diff --git a/src/fsfw/tmtcpacket/ccsds/SpacePacketReader.cpp b/src/fsfw/tmtcpacket/ccsds/SpacePacketReader.cpp new file mode 100644 index 00000000..262653c9 --- /dev/null +++ b/src/fsfw/tmtcpacket/ccsds/SpacePacketReader.cpp @@ -0,0 +1,57 @@ +#include "SpacePacketReader.h" + +#include "fsfw/serialize/SerializeIF.h" +#include "fsfw/serviceinterface/ServiceInterface.h" + +SpacePacketReader::SpacePacketReader(const uint8_t* setAddress, size_t maxSize_) { + setInternalFields(setAddress, maxSize_); +} + +ReturnValue_t SpacePacketReader::checkSize() const { + if (isNull()) { + return returnvalue::FAILED; + } + if (getFullPacketLen() > bufSize) { + return SerializeIF::STREAM_TOO_SHORT; + } + return returnvalue::OK; +} + +SpacePacketReader::~SpacePacketReader() = default; + +inline uint16_t SpacePacketReader::getPacketIdRaw() const { return ccsds::getPacketId(*spHeader); } + +const uint8_t* SpacePacketReader::getPacketData() const { return packetDataField; } + +ReturnValue_t SpacePacketReader::setData(uint8_t* data, size_t maxSize_, void* args) { + return setInternalFields(data, maxSize_); +} + +uint16_t SpacePacketReader::getPacketSeqCtrlRaw() const { + return ccsds::getPacketSeqCtrl(*spHeader); +} + +uint16_t SpacePacketReader::getPacketDataLen() const { return ccsds::getPacketLen(*spHeader); } + +ReturnValue_t SpacePacketReader::setInternalFields(const uint8_t* data, size_t maxSize_) { + bufSize = maxSize_; + if (maxSize_ < ccsds::HEADER_LEN) { + return SerializeIF::STREAM_TOO_SHORT; + } + spHeader = reinterpret_cast(data); + if (maxSize_ > ccsds::HEADER_LEN) { + packetDataField = data + ccsds::HEADER_LEN; + } + return checkSize(); +} + +const uint8_t* SpacePacketReader::getFullData() const { + return reinterpret_cast(spHeader); +} +size_t SpacePacketReader::getBufSize() const { return bufSize; } + +bool SpacePacketReader::isNull() const { return spHeader == nullptr; } + +ReturnValue_t SpacePacketReader::setReadOnlyData(const uint8_t* data, size_t maxSize) { + return setData(const_cast(data), maxSize, nullptr); +} diff --git a/src/fsfw/tmtcpacket/ccsds/SpacePacketReader.h b/src/fsfw/tmtcpacket/ccsds/SpacePacketReader.h new file mode 100644 index 00000000..61939217 --- /dev/null +++ b/src/fsfw/tmtcpacket/ccsds/SpacePacketReader.h @@ -0,0 +1,97 @@ +#ifndef FSFW_TMTCPACKET_SPACEPACKETBASE_H_ +#define FSFW_TMTCPACKET_SPACEPACKETBASE_H_ + +#include + +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/tmtcpacket/ReadablePacketIF.h" +#include "fsfw/tmtcpacket/RedirectableDataPointerIF.h" +#include "fsfw/tmtcpacket/ccsds/defs.h" + +/** + * @defgroup tmtcpackets Space Packets + * This is the group, where all classes associated with Telecommand and + * Telemetry packets belong to. + * The class hierarchy resembles the dependency between the different standards + * applied, namely the CCSDS Space Packet standard and the ECCSS Packet + * Utilization Standard. Most field and structure names are taken from these + * standards. + */ + +/** + * This class is the basic data handler for any CCSDS Space Packet + * compatible Telecommand and Telemetry packet. + * It does not contain the packet data itself but a pointer to the + * data must be set on instantiation or with the @setData or @setReadOnlyData call. + * The @isNull and @checkSize methods can be used to check the validity of the data pointed to. + * + * This is a zero-copy reader class. It does not contain the packet data itself but a pointer to + * the data. Calling any accessor methods without pointing the object to valid data first will + * cause undefined behaviour. + * @ingroup tmtcpackets + */ +class SpacePacketReader : public SpacePacketIF, + public ReadablePacketIF, + public RedirectableDataPointerIF { + public: + /** + * Initialize an empty space packet reader which points to no data + */ + SpacePacketReader() = default; + /** + * This is the default constructor. + * It sets its internal data pointer to the address passed. + * @param set_address The position where the packet data lies. + */ + explicit SpacePacketReader(const uint8_t* setAddress, size_t maxSize); + /** + * No data is allocated, so the destructor is empty. + */ + ~SpacePacketReader() override; + + /** + * Check whether any data is set for the reader object + * @return + */ + [[nodiscard]] bool isNull() const; + /** + * Get size of the buffer. This is the size which is passed to the constructor or to the + * @setData call. It is not the content of the CCSDS data length field and it is not necessarily + * equal to the full packet length of the space packet. + * @return + */ + [[nodiscard]] size_t getBufSize() const; + + [[nodiscard]] uint16_t getPacketIdRaw() const override; + [[nodiscard]] uint16_t getPacketSeqCtrlRaw() const override; + [[nodiscard]] uint16_t getPacketDataLen() const override; + + [[nodiscard]] const uint8_t* getFullData() const override; + + // Helper methods: + [[nodiscard]] ReturnValue_t checkSize() const; + + const uint8_t* getPacketData() const; + + ReturnValue_t setReadOnlyData(const uint8_t* data, size_t maxSize); + + protected: + /** + * A pointer to a structure which defines the data structure of + * the packet header. + * To be hardware-safe, all elements are of byte size. + */ + const ccsds::PrimaryHeader* spHeader{}; + const uint8_t* packetDataField{}; + size_t bufSize = 0; + /** + * With this method, the packet data pointer can be redirected to another + * location. + * @param data A pointer to another raw Space Packet. + */ + ReturnValue_t setData(uint8_t* data, size_t maxSize, void* args) override; + + ReturnValue_t setInternalFields(const uint8_t* data, size_t maxSize); +}; + +#endif /* FSFW_TMTCPACKET_SPACEPACKETBASE_H_ */ diff --git a/src/fsfw/tmtcpacket/ccsds/defs.h b/src/fsfw/tmtcpacket/ccsds/defs.h new file mode 100644 index 00000000..da7c524d --- /dev/null +++ b/src/fsfw/tmtcpacket/ccsds/defs.h @@ -0,0 +1,36 @@ +#ifndef CCSDS_HEADER_H_ +#define CCSDS_HEADER_H_ + +#include + +namespace ccsds { + +enum PacketType : uint8_t { TM = 0, TC = 1 }; + +enum SequenceFlags : uint8_t { + CONTINUATION = 0b00, + FIRST_SEGMENT = 0b01, + LAST_SEGMENT = 0b10, + UNSEGMENTED = 0b11 +}; + +static const uint16_t LIMIT_APID = 2048; // 2^11 +static const uint16_t LIMIT_SEQUENCE_COUNT = 16384; // 2^14 +static const uint16_t APID_IDLE_PACKET = 0x7FF; + +constexpr uint16_t getSpacePacketIdFromApid(bool isTc, uint16_t apid, + bool secondaryHeaderFlag = true) { + return ((isTc << 4) | (secondaryHeaderFlag << 3) | ((apid >> 8) & 0x07)) << 8 | (apid & 0x00ff); +} + +constexpr uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag) { + return getSpacePacketIdFromApid(true, apid, secondaryHeaderFlag); +} + +constexpr uint16_t getTmSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag) { + return getSpacePacketIdFromApid(false, apid, secondaryHeaderFlag); +} + +} // namespace ccsds + +#endif /* CCSDS_HEADER_H_ */ diff --git a/src/fsfw/tmtcpacket/ccsds/header.cpp b/src/fsfw/tmtcpacket/ccsds/header.cpp new file mode 100644 index 00000000..6491d207 --- /dev/null +++ b/src/fsfw/tmtcpacket/ccsds/header.cpp @@ -0,0 +1,34 @@ +#include "header.h" + +uint16_t ccsds::getPacketId(const PrimaryHeader &header) { + return ((header.packetIdHAndVersion & 0x1F) << 8) + header.packetIdL; +} + +uint16_t ccsds::getPacketSeqCtrl(const PrimaryHeader &header) { + return (header.packetSeqCtrlH << 8) | header.packetSeqCtrlL; +} + +uint8_t ccsds::getVersion(const PrimaryHeader &header) { + return (header.packetIdHAndVersion >> 5) & 0b111; +} + +uint16_t ccsds::getPacketLen(const PrimaryHeader &header) { + return (header.packetLenH << 8) | header.packetLenL; +} + +void ccsds::setPacketId(PrimaryHeader &header, uint16_t packetId) { + header.packetIdHAndVersion |= (packetId >> 8) & 0x1F; + header.packetIdL = packetId & 0xff; +} + +void ccsds::setApid(PrimaryHeader &header, uint16_t apid) { + uint16_t packetIdRaw = getPacketId(header); + packetIdRaw &= ~0x7FF; + packetIdRaw |= apid & 0x7FF; + setPacketId(header, packetIdRaw); +} + +void ccsds::setSequenceCount(PrimaryHeader &header, uint16_t seqCount) { + header.packetSeqCtrlH |= (seqCount >> 8) & 0x3F; + header.packetSeqCtrlL = seqCount & 0xFF; +} diff --git a/src/fsfw/tmtcpacket/ccsds/header.h b/src/fsfw/tmtcpacket/ccsds/header.h new file mode 100644 index 00000000..89e00601 --- /dev/null +++ b/src/fsfw/tmtcpacket/ccsds/header.h @@ -0,0 +1,31 @@ +#ifndef FSFW_TMTCPACKET_HEADER_H +#define FSFW_TMTCPACKET_HEADER_H + +#include +#include + +namespace ccsds { + +static constexpr size_t HEADER_LEN = 6; + +struct PrimaryHeader { + uint8_t packetIdHAndVersion; + uint8_t packetIdL; + uint8_t packetSeqCtrlH; + uint8_t packetSeqCtrlL; + uint8_t packetLenH; + uint8_t packetLenL; +}; + +uint16_t getPacketId(const PrimaryHeader& header); +uint16_t getPacketSeqCtrl(const PrimaryHeader& header); +uint8_t getVersion(const PrimaryHeader& header); +uint16_t getPacketLen(const PrimaryHeader& header); + +void setPacketId(PrimaryHeader& header, uint16_t packetId); +void setApid(PrimaryHeader& header, uint16_t apid); +void setSequenceCount(PrimaryHeader& header, uint16_t seqCount); + +} // namespace ccsds + +#endif // FSFW_TMTCPACKET_HEADER_H diff --git a/src/fsfw/tmtcpacket/ccsds_header.h b/src/fsfw/tmtcpacket/ccsds_header.h deleted file mode 100644 index 232790c0..00000000 --- a/src/fsfw/tmtcpacket/ccsds_header.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef CCSDS_HEADER_H_ -#define CCSDS_HEADER_H_ - -#include - -struct CCSDSPrimaryHeader { - uint8_t packet_id_h; - uint8_t packet_id_l; - uint8_t sequence_control_h; - uint8_t sequence_control_l; - uint8_t packet_length_h; - uint8_t packet_length_l; -}; - -#endif /* CCSDS_HEADER_H_ */ diff --git a/src/fsfw/tmtcpacket/cfdp/CFDPPacket.cpp b/src/fsfw/tmtcpacket/cfdp/CFDPPacket.cpp deleted file mode 100644 index 5df50cd7..00000000 --- a/src/fsfw/tmtcpacket/cfdp/CFDPPacket.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "fsfw/tmtcpacket/cfdp/CFDPPacket.h" - -#include - -#include "fsfw/globalfunctions/CRC.h" -#include "fsfw/globalfunctions/arrayprinter.h" -#include "fsfw/serviceinterface/ServiceInterface.h" - -CFDPPacket::CFDPPacket(const uint8_t* setData) : SpacePacketBase(setData) {} - -CFDPPacket::~CFDPPacket() {} - -void CFDPPacket::print() { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::info << "CFDPPacket::print:" << std::endl; -#else - sif::printInfo("CFDPPacket::print:\n"); -#endif - arrayprinter::print(getWholeData(), getFullSize()); -} diff --git a/src/fsfw/tmtcpacket/cfdp/CFDPPacketStored.cpp b/src/fsfw/tmtcpacket/cfdp/CFDPPacketStored.cpp deleted file mode 100644 index 9a410b40..00000000 --- a/src/fsfw/tmtcpacket/cfdp/CFDPPacketStored.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "fsfw/tmtcpacket/cfdp/CFDPPacketStored.h" - -#include "fsfw/objectmanager/ObjectManager.h" - -StorageManagerIF* CFDPPacketStored::store = nullptr; - -CFDPPacketStored::CFDPPacketStored() : CFDPPacket(nullptr) {} - -CFDPPacketStored::CFDPPacketStored(store_address_t setAddress) : CFDPPacket(nullptr) { - this->setStoreAddress(setAddress); -} - -CFDPPacketStored::CFDPPacketStored(const uint8_t* data, size_t size) : CFDPPacket(data) { - if (this->getFullSize() != size) { - return; - } - if (this->checkAndSetStore()) { - ReturnValue_t status = store->addData(&storeAddress, data, size); - if (status != HasReturnvaluesIF::RETURN_OK) { - this->setData(nullptr, -1); - } - const uint8_t* storePtr = nullptr; - // Repoint base data pointer to the data in the store. - store->getData(storeAddress, &storePtr, &size); - this->setData(const_cast(storePtr), size); - } -} - -ReturnValue_t CFDPPacketStored::deletePacket() { - ReturnValue_t result = this->store->deleteData(this->storeAddress); - this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - // To circumvent size checks - this->setData(nullptr, -1); - return result; -} - -// CFDPPacket* CFDPPacketStored::getPacketBase() { -// return this; -// } -void CFDPPacketStored::setStoreAddress(store_address_t setAddress) { - this->storeAddress = setAddress; - const uint8_t* tempData = nullptr; - size_t tempSize; - ReturnValue_t status = StorageManagerIF::RETURN_FAILED; - if (this->checkAndSetStore()) { - status = this->store->getData(this->storeAddress, &tempData, &tempSize); - } - if (status == StorageManagerIF::RETURN_OK) { - this->setData(const_cast(tempData), tempSize); - } else { - // To circumvent size checks - this->setData(nullptr, -1); - this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - } -} - -store_address_t CFDPPacketStored::getStoreAddress() { return this->storeAddress; } - -CFDPPacketStored::~CFDPPacketStored() {} - -ReturnValue_t CFDPPacketStored::getData(const uint8_t** dataPtr, size_t* dataSize) { - return HasReturnvaluesIF::RETURN_OK; -} - -// ReturnValue_t CFDPPacketStored::setData(const uint8_t *data) { -// return HasReturnvaluesIF::RETURN_OK; -// } - -bool CFDPPacketStored::checkAndSetStore() { - if (this->store == nullptr) { - this->store = ObjectManager::instance()->get(objects::TC_STORE); - if (this->store == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "CFDPPacketStored::CFDPPacketStored: TC Store not found!" << std::endl; -#endif - return false; - } - } - return true; -} - -bool CFDPPacketStored::isSizeCorrect() { - const uint8_t* temp_data = nullptr; - size_t temp_size; - ReturnValue_t status = this->store->getData(this->storeAddress, &temp_data, &temp_size); - if (status == StorageManagerIF::RETURN_OK) { - if (this->getFullSize() == temp_size) { - return true; - } - } - return false; -} diff --git a/src/fsfw/tmtcpacket/cfdp/CMakeLists.txt b/src/fsfw/tmtcpacket/cfdp/CMakeLists.txt index 0b7ab18a..a0d48465 100644 --- a/src/fsfw/tmtcpacket/cfdp/CMakeLists.txt +++ b/src/fsfw/tmtcpacket/cfdp/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - CFDPPacket.cpp - CFDPPacketStored.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE) diff --git a/src/fsfw/tmtcpacket/cfdp/CFDPPacket.h b/src/fsfw/tmtcpacket/cfdp/CfdpPacket.h similarity index 76% rename from src/fsfw/tmtcpacket/cfdp/CFDPPacket.h rename to src/fsfw/tmtcpacket/cfdp/CfdpPacket.h index 30ba98ae..e391202f 100644 --- a/src/fsfw/tmtcpacket/cfdp/CFDPPacket.h +++ b/src/fsfw/tmtcpacket/cfdp/CfdpPacket.h @@ -1,9 +1,9 @@ #ifndef FSFW_INC_FSFW_TMTCPACKET_CFDP_CFDPPACKET_H_ #define FSFW_INC_FSFW_TMTCPACKET_CFDP_CFDPPACKET_H_ -#include "fsfw/tmtcpacket/SpacePacketBase.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" -class CFDPPacket : public SpacePacketBase { +class CfdpReader : public SpacePacketReader { public: /** * This is the default constructor. @@ -11,11 +11,11 @@ class CFDPPacket : public SpacePacketBase { * forwards the data pointer to the parent SpacePacketBase class. * @param setData The position where the packet data lies. */ - CFDPPacket(const uint8_t* setData); + explicit CfdpReader(const uint8_t* setData, size_t maxSize); /** * This is the empty default destructor. */ - virtual ~CFDPPacket(); + ~CfdpReader() override; /** * This is a debugging helper method that prints the whole packet content diff --git a/src/fsfw/tmtcpacket/cfdp/CFDPPacketStored.h b/src/fsfw/tmtcpacket/cfdp/CfdpPacketStored.h similarity index 54% rename from src/fsfw/tmtcpacket/cfdp/CFDPPacketStored.h rename to src/fsfw/tmtcpacket/cfdp/CfdpPacketStored.h index f9c73bdd..8b0da723 100644 --- a/src/fsfw/tmtcpacket/cfdp/CFDPPacketStored.h +++ b/src/fsfw/tmtcpacket/cfdp/CfdpPacketStored.h @@ -1,31 +1,31 @@ -#ifndef FSFW_INC_FSFW_TMTCPACKET_CFDP_CFDPPACKETSTORED_H_ -#define FSFW_INC_FSFW_TMTCPACKET_CFDP_CFDPPACKETSTORED_H_ +#ifndef FSFW_TMTCPACKET_CFDP_CFDPPACKETSTORED_H_ +#define FSFW_TMTCPACKET_CFDP_CFDPPACKETSTORED_H_ -#include "../pus/tc/TcPacketStoredBase.h" -#include "CFDPPacket.h" +#include "CfdpPacket.h" +#include "fsfw/storagemanager/storeAddress.h" -class CFDPPacketStored : public CFDPPacket, public TcPacketStoredBase { +class CfdpPacketStored : public CfdpReader { public: /** * Create stored packet with existing data. * @param data * @param size */ - CFDPPacketStored(const uint8_t* data, size_t size); + CfdpPacketStored(const uint8_t* data, size_t size); /** * Create stored packet from existing packet in store * @param setAddress */ - CFDPPacketStored(store_address_t setAddress); - CFDPPacketStored(); + explicit CfdpPacketStored(store_address_t setAddress); + CfdpPacketStored(); - virtual ~CFDPPacketStored(); + ~CfdpPacketStored() override; /** * Getter function for the raw data. * @param dataPtr [out] Pointer to the data pointer to set * @param dataSize [out] Address of size to set. - * @return -@c RETURN_OK if data was retrieved successfully. + * @return -@c returnvalue::OK if data was retrieved successfully. */ ReturnValue_t getData(const uint8_t** dataPtr, size_t* dataSize); @@ -39,13 +39,6 @@ class CFDPPacketStored : public CFDPPacket, public TcPacketStoredBase { bool isSizeCorrect(); protected: - /** - * This is a pointer to the store all instances of the class use. - * If the store is not yet set (i.e. @c store is NULL), every constructor - * call tries to set it and throws an error message in case of failures. - * The default store is objects::TC_STORE. - */ - static StorageManagerIF* store; /** * The address where the packet data of the object instance is stored. */ @@ -60,4 +53,4 @@ class CFDPPacketStored : public CFDPPacket, public TcPacketStoredBase { bool checkAndSetStore(); }; -#endif /* FSFW_INC_FSFW_TMTCPACKET_CFDP_CFDPPACKETSTORED_H_ */ +#endif /* FSFW_TMTCPACKET_CFDP_CFDPPACKETSTORED_H_ */ diff --git a/src/fsfw/tmtcpacket/packetmatcher/ApidMatcher.h b/src/fsfw/tmtcpacket/packetmatcher/ApidMatcher.h index cf4c88f2..47e23f1c 100644 --- a/src/fsfw/tmtcpacket/packetmatcher/ApidMatcher.h +++ b/src/fsfw/tmtcpacket/packetmatcher/ApidMatcher.h @@ -1,32 +1,36 @@ #ifndef FSFW_TMTCPACKET_PACKETMATCHER_APIDMATCHER_H_ #define FSFW_TMTCPACKET_PACKETMATCHER_APIDMATCHER_H_ -#include "../../globalfunctions/matching/SerializeableMatcherIF.h" -#include "../../serialize/SerializeAdapter.h" -#include "../../tmtcpacket/pus/tm/TmPacketMinimal.h" +#include "fsfw/globalfunctions/matching/SerializeableMatcherIF.h" +#include "fsfw/serialize/SerializeAdapter.h" +#include "fsfw/tmtcpacket/pus/tm/PusTmIF.h" +#include "fsfw/tmtcpacket/pus/tm/PusTmMinimal.h" -class ApidMatcher : public SerializeableMatcherIF { +class ApidMatcher : public SerializeableMatcherIF { private: uint16_t apid; public: - ApidMatcher(uint16_t setApid) : apid(setApid) {} - ApidMatcher(TmPacketMinimal* test) : apid(test->getAPID()) {} - bool match(TmPacketMinimal* packet) { - if (packet->getAPID() == apid) { + explicit ApidMatcher(uint16_t setApid) : apid(setApid) {} + explicit ApidMatcher(PusTmIF* test) : apid(test->getApid()) {} + bool match(PusTmIF* packet) override { + if (packet->getApid() == apid) { return true; } else { return false; } } ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const { + Endianness streamEndianness) const override { return SerializeAdapter::serialize(&apid, buffer, size, maxSize, streamEndianness); } - size_t getSerializedSize() const { return SerializeAdapter::getSerializedSize(&apid); } - ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { + [[nodiscard]] size_t getSerializedSize() const override { + return SerializeAdapter::getSerializedSize(&apid); + } + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override { return SerializeAdapter::deSerialize(&apid, buffer, size, streamEndianness); } }; -#endif /* FRAMEWORK_TMTCPACKET_PACKETMATCHER_APIDMATCHER_H_ */ +#endif /* FSFW_TMTCPACKET_PACKETMATCHER_APIDMATCHER_H_ */ diff --git a/src/fsfw/tmtcpacket/packetmatcher/CMakeLists.txt b/src/fsfw/tmtcpacket/packetmatcher/CMakeLists.txt index e9a8d03b..6ea94799 100644 --- a/src/fsfw/tmtcpacket/packetmatcher/CMakeLists.txt +++ b/src/fsfw/tmtcpacket/packetmatcher/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - PacketMatchTree.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE PacketMatchTree.cpp) diff --git a/src/fsfw/tmtcpacket/packetmatcher/PacketMatchTree.cpp b/src/fsfw/tmtcpacket/packetmatcher/PacketMatchTree.cpp index 6b900030..8542694a 100644 --- a/src/fsfw/tmtcpacket/packetmatcher/PacketMatchTree.cpp +++ b/src/fsfw/tmtcpacket/packetmatcher/PacketMatchTree.cpp @@ -1,5 +1,6 @@ #include "fsfw/tmtcpacket/packetmatcher/PacketMatchTree.h" +#include "fsfw/storagemanager/LocalPool.h" #include "fsfw/tmtcpacket/packetmatcher/ApidMatcher.h" #include "fsfw/tmtcpacket/packetmatcher/ServiceMatcher.h" #include "fsfw/tmtcpacket/packetmatcher/SubserviceMatcher.h" @@ -12,78 +13,77 @@ const LocalPool::LocalPoolConfig PacketMatchTree::poolConfig = { {40, sizeof(PacketMatchTree::Node)}}; PacketMatchTree::PacketMatchTree(Node* root) - : MatchTree(root, 2), + : MatchTree(root, 2), factoryBackend(0, poolConfig, false, true), factory(&factoryBackend) {} PacketMatchTree::PacketMatchTree(iterator root) - : MatchTree(root.element, 2), + : MatchTree(root.element, 2), factoryBackend(0, poolConfig, false, true), factory(&factoryBackend) {} PacketMatchTree::PacketMatchTree() - : MatchTree((Node*)NULL, 2), + : MatchTree(nullptr, 2), factoryBackend(0, poolConfig, false, true), factory(&factoryBackend) {} -PacketMatchTree::~PacketMatchTree() {} +PacketMatchTree::~PacketMatchTree() = default; ReturnValue_t PacketMatchTree::addMatch(uint16_t apid, uint8_t type, uint8_t subtype) { // We assume adding APID is always requested. - TmPacketMinimal::TmPacketMinimalPointer data; - data.data_field.service_type = type; - data.data_field.service_subtype = subtype; - TmPacketMinimal testPacket((uint8_t*)&data); - testPacket.setAPID(apid); + mintm::MinimalPusTm data{}; + data.secHeader.service = type; + data.secHeader.subservice = subtype; + PusTmMinimal testPacket((uint8_t*)&data); + testPacket.setApid(apid); + iterator lastTest; iterator rollback; ReturnValue_t result = - findOrInsertMatch(this->begin(), &testPacket, &lastTest); + findOrInsertMatch(this->begin(), &testPacket, &lastTest); if (result == NEW_NODE_CREATED) { rollback = lastTest; - } else if (result != RETURN_OK) { + } else if (result != returnvalue::OK) { return result; } if (type == 0) { // Check if lastTest has no children, otherwise, delete them, // as a more general check is requested. - if (lastTest.left() != this->end()) { + if (lastTest.left() != PacketMatchTree::end()) { removeElementAndAllChildren(lastTest.left()); } - return RETURN_OK; + return returnvalue::OK; } // Type insertion required. - result = - findOrInsertMatch(lastTest.left(), &testPacket, &lastTest); + result = findOrInsertMatch(lastTest.left(), &testPacket, &lastTest); if (result == NEW_NODE_CREATED) { - if (rollback == this->end()) { + if (rollback == PacketMatchTree::end()) { rollback = lastTest; } - } else if (result != RETURN_OK) { - if (rollback != this->end()) { + } else if (result != returnvalue::OK) { + if (rollback != PacketMatchTree::end()) { removeElementAndAllChildren(rollback); } return result; } if (subtype == 0) { - if (lastTest.left() != this->end()) { + if (lastTest.left() != PacketMatchTree::end()) { // See above removeElementAndAllChildren(lastTest.left()); } - return RETURN_OK; + return returnvalue::OK; } // Subtype insertion required. - result = findOrInsertMatch(lastTest.left(), &testPacket, - &lastTest); + result = findOrInsertMatch(lastTest.left(), &testPacket, &lastTest); if (result == NEW_NODE_CREATED) { - return RETURN_OK; - } else if (result != RETURN_OK) { - if (rollback != this->end()) { + return returnvalue::OK; + } else if (result != returnvalue::OK) { + if (rollback != PacketMatchTree::end()) { removeElementAndAllChildren(rollback); } return result; } - return RETURN_OK; + return returnvalue::OK; } template @@ -91,12 +91,12 @@ ReturnValue_t PacketMatchTree::findOrInsertMatch(iterator startAt, VALUE_T test, iterator* lastTest) { bool attachToBranch = AND; iterator iter = startAt; - while (iter != this->end()) { + while (iter != PacketMatchTree::end()) { bool isMatch = iter->match(test); attachToBranch = OR; *lastTest = iter; if (isMatch) { - return RETURN_OK; + return returnvalue::OK; } else { // Go down OR branch. iter = iter.right(); @@ -104,11 +104,11 @@ ReturnValue_t PacketMatchTree::findOrInsertMatch(iterator startAt, VALUE_T test, } // Only reached if nothing was found. SerializeableMatcherIF* newContent = factory.generate(test); - if (newContent == NULL) { + if (newContent == nullptr) { return FULL; } Node* newNode = factory.generate(newContent); - if (newNode == NULL) { + if (newNode == nullptr) { // Need to make sure partially generated content is deleted, otherwise, that's a leak. factory.destroy(static_cast(newContent)); return FULL; @@ -116,19 +116,19 @@ ReturnValue_t PacketMatchTree::findOrInsertMatch(iterator startAt, VALUE_T test, *lastTest = insert(attachToBranch, *lastTest, newNode); if (*lastTest == end()) { // This actaully never fails, so creating a dedicated returncode seems an overshoot. - return RETURN_FAILED; + return returnvalue::FAILED; } return NEW_NODE_CREATED; } ReturnValue_t PacketMatchTree::removeMatch(uint16_t apid, uint8_t type, uint8_t subtype) { - TmPacketMinimal::TmPacketMinimalPointer data; - data.data_field.service_type = type; - data.data_field.service_subtype = subtype; - TmPacketMinimal testPacket((uint8_t*)&data); - testPacket.setAPID(apid); + mintm::MinimalPusTm data{}; + data.secHeader.service = type; + data.secHeader.subservice = subtype; + PusTmMinimal testPacket((uint8_t*)&data); + testPacket.setApid(apid); iterator foundElement = findMatch(begin(), &testPacket); - if (foundElement == this->end()) { + if (foundElement == PacketMatchTree::end()) { return NO_MATCH; } if (type == 0) { @@ -158,7 +158,7 @@ ReturnValue_t PacketMatchTree::removeMatch(uint16_t apid, uint8_t type, uint8_t return removeElementAndReconnectChildren(foundElement); } -PacketMatchTree::iterator PacketMatchTree::findMatch(iterator startAt, TmPacketMinimal* test) { +PacketMatchTree::iterator PacketMatchTree::findMatch(iterator startAt, PusTmIF* test) { iterator iter = startAt; while (iter != end()) { bool isMatch = iter->match(test); diff --git a/src/fsfw/tmtcpacket/packetmatcher/PacketMatchTree.h b/src/fsfw/tmtcpacket/packetmatcher/PacketMatchTree.h index 0cbd4494..b9d03f1d 100644 --- a/src/fsfw/tmtcpacket/packetmatcher/PacketMatchTree.h +++ b/src/fsfw/tmtcpacket/packetmatcher/PacketMatchTree.h @@ -4,21 +4,22 @@ #include "fsfw/container/PlacementFactory.h" #include "fsfw/globalfunctions/matching/MatchTree.h" #include "fsfw/storagemanager/LocalPool.h" -#include "fsfw/tmtcpacket/pus/tm/TmPacketMinimal.h" +#include "fsfw/tmtcpacket/pus/tm/PusTmIF.h" +#include "fsfw/tmtcpacket/pus/tm/PusTmMinimal.h" -class PacketMatchTree : public MatchTree, public HasReturnvaluesIF { +class PacketMatchTree : public MatchTree { public: - PacketMatchTree(Node* root); - PacketMatchTree(iterator root); + explicit PacketMatchTree(Node* root); + explicit PacketMatchTree(iterator root); PacketMatchTree(); - virtual ~PacketMatchTree(); + ~PacketMatchTree() override; ReturnValue_t changeMatch(bool addToMatch, uint16_t apid, uint8_t type = 0, uint8_t subtype = 0); ReturnValue_t addMatch(uint16_t apid, uint8_t type = 0, uint8_t subtype = 0); ReturnValue_t removeMatch(uint16_t apid, uint8_t type = 0, uint8_t subtype = 0); ReturnValue_t initialize(); protected: - ReturnValue_t cleanUpElement(iterator position); + ReturnValue_t cleanUpElement(iterator position) override; private: static const uint8_t N_POOLS = 4; @@ -29,7 +30,7 @@ class PacketMatchTree : public MatchTree, public HasReturnvalu static const uint16_t N_ELEMENTS[N_POOLS]; template ReturnValue_t findOrInsertMatch(iterator startAt, VALUE_T test, iterator* lastTest); - iterator findMatch(iterator startAt, TmPacketMinimal* test); + iterator findMatch(iterator startAt, PusTmIF* test); }; -#endif /* FRAMEWORK_TMTCPACKET_PACKETMATCHER_PACKETMATCHTREE_H_ */ +#endif /* FSFW_TMTCPACKET_PACKETMATCHER_PACKETMATCHTREE_H_ */ diff --git a/src/fsfw/tmtcpacket/packetmatcher/ServiceMatcher.h b/src/fsfw/tmtcpacket/packetmatcher/ServiceMatcher.h index 752c0354..6ccd9a6b 100644 --- a/src/fsfw/tmtcpacket/packetmatcher/ServiceMatcher.h +++ b/src/fsfw/tmtcpacket/packetmatcher/ServiceMatcher.h @@ -3,16 +3,16 @@ #include "../../globalfunctions/matching/SerializeableMatcherIF.h" #include "../../serialize/SerializeAdapter.h" -#include "../pus/tm/TmPacketMinimal.h" +#include "../pus/tm/PusTmMinimal.h" -class ServiceMatcher : public SerializeableMatcherIF { +class ServiceMatcher : public SerializeableMatcherIF { private: uint8_t service; public: - ServiceMatcher(uint8_t setService) : service(setService) {} - ServiceMatcher(TmPacketMinimal* test) : service(test->getService()) {} - bool match(TmPacketMinimal* packet) { + explicit ServiceMatcher(uint8_t setService) : service(setService) {} + explicit ServiceMatcher(PusTmIF* test) : service(test->getService()) {} + bool match(PusTmIF* packet) override { if (packet->getService() == service) { return true; } else { @@ -20,11 +20,14 @@ class ServiceMatcher : public SerializeableMatcherIF { } } ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const { + Endianness streamEndianness) const override { return SerializeAdapter::serialize(&service, buffer, size, maxSize, streamEndianness); } - size_t getSerializedSize() const { return SerializeAdapter::getSerializedSize(&service); } - ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { + [[nodiscard]] size_t getSerializedSize() const override { + return SerializeAdapter::getSerializedSize(&service); + } + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override { return SerializeAdapter::deSerialize(&service, buffer, size, streamEndianness); } }; diff --git a/src/fsfw/tmtcpacket/packetmatcher/SubserviceMatcher.h b/src/fsfw/tmtcpacket/packetmatcher/SubserviceMatcher.h index 934e8cb8..8729bbd5 100644 --- a/src/fsfw/tmtcpacket/packetmatcher/SubserviceMatcher.h +++ b/src/fsfw/tmtcpacket/packetmatcher/SubserviceMatcher.h @@ -3,13 +3,13 @@ #include "../../globalfunctions/matching/SerializeableMatcherIF.h" #include "../../serialize/SerializeAdapter.h" -#include "../pus/tm/TmPacketMinimal.h" +#include "../pus/tm/PusTmMinimal.h" -class SubServiceMatcher : public SerializeableMatcherIF { +class SubServiceMatcher : public SerializeableMatcherIF { public: - SubServiceMatcher(uint8_t subService) : subService(subService) {} - SubServiceMatcher(TmPacketMinimal* test) : subService(test->getSubService()) {} - bool match(TmPacketMinimal* packet) { + explicit SubServiceMatcher(uint8_t subService) : subService(subService) {} + explicit SubServiceMatcher(PusTmIF* test) : subService(test->getSubService()) {} + bool match(PusTmIF* packet) override { if (packet->getSubService() == subService) { return true; } else { @@ -17,16 +17,19 @@ class SubServiceMatcher : public SerializeableMatcherIF { } } ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const { + Endianness streamEndianness) const override { return SerializeAdapter::serialize(&subService, buffer, size, maxSize, streamEndianness); } - size_t getSerializedSize() const { return SerializeAdapter::getSerializedSize(&subService); } - ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { + [[nodiscard]] size_t getSerializedSize() const override { + return SerializeAdapter::getSerializedSize(&subService); + } + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override { return SerializeAdapter::deSerialize(&subService, buffer, size, streamEndianness); } private: - uint8_t subService; + uint8_t subService{}; }; #endif /* FRAMEWORK_TMTCPACKET_PACKETMATCHER_SUBSERVICEMATCHER_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/CustomUserDataIF.h b/src/fsfw/tmtcpacket/pus/CustomUserDataIF.h new file mode 100644 index 00000000..33592ed1 --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/CustomUserDataIF.h @@ -0,0 +1,12 @@ +#ifndef FSFW_TMTCPACKET_CREATORDATAIF_H +#define FSFW_TMTCPACKET_CREATORDATAIF_H + +#include "defs.h" + +class CustomUserDataIF { + public: + virtual ~CustomUserDataIF() = default; + virtual ReturnValue_t setRawUserData(const uint8_t* data, size_t len) = 0; + virtual ReturnValue_t setSerializableUserData(const SerializeIF& serializable) = 0; +}; +#endif // FSFW_TMTCPACKET_CREATORDATAIF_H diff --git a/src/fsfw/tmtcpacket/pus/PacketTimestampInterpreterIF.h b/src/fsfw/tmtcpacket/pus/PacketTimestampInterpreterIF.h index 340f7825..36743fe8 100644 --- a/src/fsfw/tmtcpacket/pus/PacketTimestampInterpreterIF.h +++ b/src/fsfw/tmtcpacket/pus/PacketTimestampInterpreterIF.h @@ -1,15 +1,15 @@ #ifndef FSFW_TMTCPACKET_PUS_PACKETTIMESTAMPINTERPRETERIF_H_ #define FSFW_TMTCPACKET_PUS_PACKETTIMESTAMPINTERPRETERIF_H_ -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" -class TmPacketMinimal; +class PusTmMinimal; class PacketTimestampInterpreterIF { public: virtual ~PacketTimestampInterpreterIF() {} - virtual ReturnValue_t getPacketTime(TmPacketMinimal* packet, timeval* timestamp) const = 0; - virtual ReturnValue_t getPacketTimeRaw(TmPacketMinimal* packet, const uint8_t** timePtr, + virtual ReturnValue_t getPacketTime(PusTmMinimal* packet, timeval* timestamp) const = 0; + virtual ReturnValue_t getPacketTimeRaw(PusTmMinimal* packet, const uint8_t** timePtr, uint32_t* size) const = 0; }; diff --git a/src/fsfw/tmtcpacket/pus/PusIF.h b/src/fsfw/tmtcpacket/pus/PusIF.h new file mode 100644 index 00000000..ed447c75 --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/PusIF.h @@ -0,0 +1,39 @@ +#ifndef FSFW_TMTCPACKET_PUSIF_H +#define FSFW_TMTCPACKET_PUSIF_H + +#include + +#include "fsfw/returnvalues/FwClassIds.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketIF.h" + +class PusIF : public SpacePacketIF { + public: + static constexpr uint8_t INTERFACE_ID = CLASS_ID::PUS_IF; + static constexpr ReturnValue_t INVALID_PUS_VERSION = returnvalue::makeCode(INTERFACE_ID, 0); + static constexpr ReturnValue_t INVALID_CRC_16 = returnvalue::makeCode(INTERFACE_ID, 1); + + ~PusIF() override = default; + /** + * This command returns the TC Packet PUS Version Number. + * The version number of ECSS PUS 2003 is 1. + * It consists of the second to fourth highest bits of the + * first byte. + * @return + */ + [[nodiscard]] virtual uint8_t getPusVersion() const = 0; + + /** + * This is a getter for the packet's PUS Service ID, which is the second + * byte of the Data Field Header. + * @return The packet's PUS Service ID. + */ + [[nodiscard]] virtual uint8_t getService() const = 0; + /** + * This is a getter for the packet's PUS Service Subtype, which is the + * third byte of the Data Field Header. + * @return The packet's PUS Service Subtype. + */ + [[nodiscard]] virtual uint8_t getSubService() const = 0; +}; + +#endif // FSFW_TMTCPACKET_PUSIF_H diff --git a/src/fsfw/tmtcpacket/pus/RawUserDataReaderIF.h b/src/fsfw/tmtcpacket/pus/RawUserDataReaderIF.h new file mode 100644 index 00000000..799b7940 --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/RawUserDataReaderIF.h @@ -0,0 +1,14 @@ +#ifndef FSFW_TMTCPACKET_RAWDATAIF_H +#define FSFW_TMTCPACKET_RAWDATAIF_H + +#include +#include + +class RawUserDataReaderIF { + public: + ~RawUserDataReaderIF() = default; + [[nodiscard]] virtual const uint8_t* getUserData() const = 0; + [[nodiscard]] virtual size_t getUserDataLen() const = 0; +}; + +#endif // FSFW_TMTCPACKET_RAWDATAIF_H diff --git a/src/fsfw/tmtcpacket/pus/definitions.h b/src/fsfw/tmtcpacket/pus/definitions.h deleted file mode 100644 index d4b649d0..00000000 --- a/src/fsfw/tmtcpacket/pus/definitions.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef FSFW_SRC_FSFW_TMTCPACKET_PUS_TM_DEFINITIONS_H_ -#define FSFW_SRC_FSFW_TMTCPACKET_PUS_TM_DEFINITIONS_H_ - -#include - -namespace pus { - -//! Version numbers according to ECSS-E-ST-70-41C p.439 -enum PusVersion : uint8_t { PUS_A_VERSION = 1, PUS_C_VERSION = 2 }; - -} // namespace pus - -#endif /* FSFW_SRC_FSFW_TMTCPACKET_PUS_TM_DEFINITIONS_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/defs.h b/src/fsfw/tmtcpacket/pus/defs.h new file mode 100644 index 00000000..c5172d8b --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/defs.h @@ -0,0 +1,30 @@ +#ifndef FSFW_SRC_FSFW_TMTCPACKET_PUS_TM_DEFINITIONS_H_ +#define FSFW_SRC_FSFW_TMTCPACKET_PUS_TM_DEFINITIONS_H_ + +#include +#include + +#include "fsfw/serialize/SerializeIF.h" + +namespace ecss { + +using PusChecksumT = uint16_t; + +//! Version numbers according to ECSS-E-ST-70-41C p.439 +enum PusVersion : uint8_t { PUS_A = 1, PUS_C = 2 }; + +/** + * This struct defines the data structure of a Space Packet when accessed + * via a pointer. + * @ingroup tmtcpackets + */ +struct PusPointers { + const uint8_t* spHeaderStart; + const uint8_t* secHeaderStart; + const uint8_t* userDataStart; + const uint8_t* crcStart; +}; + +} // namespace ecss + +#endif /* FSFW_SRC_FSFW_TMTCPACKET_PUS_TM_DEFINITIONS_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tc.h b/src/fsfw/tmtcpacket/pus/tc.h index f5a467aa..e5e5f9f7 100644 --- a/src/fsfw/tmtcpacket/pus/tc.h +++ b/src/fsfw/tmtcpacket/pus/tc.h @@ -1,7 +1,7 @@ #ifndef FSFW_TMTCPACKET_PUS_TC_H_ #define FSFW_TMTCPACKET_PUS_TC_H_ -#include "tc/TcPacketPus.h" -#include "tc/TcPacketStoredPus.h" +#include "tc/PusTcCreator.h" +#include "tc/PusTcReader.h" #endif /* FSFW_TMTCPACKET_PUS_TC_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tc/CMakeLists.txt b/src/fsfw/tmtcpacket/pus/tc/CMakeLists.txt index dc611263..adf7f34d 100644 --- a/src/fsfw/tmtcpacket/pus/tc/CMakeLists.txt +++ b/src/fsfw/tmtcpacket/pus/tc/CMakeLists.txt @@ -1,6 +1,2 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - TcPacketPusBase.cpp - TcPacketPus.cpp - TcPacketStoredBase.cpp - TcPacketStoredPus.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE PusTcReader.cpp PusTcReader.cpp + PusTcCreator.cpp) diff --git a/src/fsfw/tmtcpacket/pus/tc/PusTcCreator.cpp b/src/fsfw/tmtcpacket/pus/tc/PusTcCreator.cpp new file mode 100644 index 00000000..82dd1c41 --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/tc/PusTcCreator.cpp @@ -0,0 +1,105 @@ +#include "PusTcCreator.h" + +#include + +#include "PusTcIF.h" +#include "fsfw/globalfunctions/CRC.h" +#include "fsfw/serialize/SerializeAdapter.h" + +PusTcCreator::PusTcCreator(SpacePacketParams spParams, PusTcParams pusParams) + : spCreator(std::move(spParams)), pusParams(pusParams) { + setup(); +} + +ReturnValue_t PusTcCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const { + const uint8_t *start = *buffer; + if (*size + getSerializedSize() > maxSize) { + return SerializeIF::BUFFER_TOO_SHORT; + } + if (pusParams.pusVersion != ecss::PusVersion::PUS_C) { + return PusIF::INVALID_PUS_VERSION; + } + ReturnValue_t result = spCreator.serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + **buffer = pusParams.pusVersion << 4 | pusParams.ackFlags; + *buffer += 1; + **buffer = pusParams.service; + *buffer += 1; + **buffer = pusParams.subservice; + *buffer += 1; + *size += 3; + result = + SerializeAdapter::serialize(&pusParams.sourceId, buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + if (pusParams.appData != nullptr) { + result = pusParams.appData->serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + } + + uint16_t crc16 = CRC::crc16ccitt(start, getFullPacketLen() - sizeof(ecss::PusChecksumT)); + return SerializeAdapter::serialize(&crc16, buffer, size, maxSize, streamEndianness); +} + +void PusTcCreator::updateSpLengthField() { + size_t len = ecss::PusTcDataFieldHeader::MIN_SIZE + sizeof(ecss::PusChecksumT); + if (pusParams.appData != nullptr) { + len += pusParams.appData->getSerializedSize(); + } + spCreator.setCcsdsLenFromTotalDataFieldLen(len); +} + +size_t PusTcCreator::getSerializedSize() const { return spCreator.getFullPacketLen(); } + +ReturnValue_t PusTcCreator::deSerialize(const uint8_t **buffer, size_t *size, + SerializeIF::Endianness streamEndianness) { + return returnvalue::FAILED; +} + +uint16_t PusTcCreator::getPacketIdRaw() const { return spCreator.getPacketIdRaw(); } + +uint16_t PusTcCreator::getPacketSeqCtrlRaw() const { return spCreator.getPacketSeqCtrlRaw(); } + +uint16_t PusTcCreator::getPacketDataLen() const { return spCreator.getPacketDataLen(); } + +uint8_t PusTcCreator::getPusVersion() const { return pusParams.pusVersion; } + +uint8_t PusTcCreator::getAcknowledgeFlags() const { return pusParams.ackFlags; } + +uint8_t PusTcCreator::getService() const { return pusParams.service; } + +uint8_t PusTcCreator::getSubService() const { return pusParams.subservice; } + +uint16_t PusTcCreator::getSourceId() const { return pusParams.sourceId; } + +PusTcParams &PusTcCreator::getPusParams() { return pusParams; } + +SpacePacketParams &PusTcCreator::getSpParams() { return spCreator.getParams(); } + +ReturnValue_t PusTcCreator::setRawUserData(const uint8_t *data, size_t len) { + // TODO: Check length field? + pusParams.bufAdapter.setConstBuffer(data, len); + pusParams.appData = &pusParams.bufAdapter; + updateSpLengthField(); + return returnvalue::OK; +} + +ReturnValue_t PusTcCreator::setSerializableUserData(const SerializeIF &serializable) { + // TODO: Check length field? + pusParams.appData = &serializable; + updateSpLengthField(); + return returnvalue::OK; +} + +void PusTcCreator::setup() { + spCreator.setPacketType(ccsds::PacketType::TC); + spCreator.setSecHeaderFlag(); + spCreator.setSeqFlags(ccsds::SequenceFlags::UNSEGMENTED); + updateSpLengthField(); +} diff --git a/src/fsfw/tmtcpacket/pus/tc/PusTcCreator.h b/src/fsfw/tmtcpacket/pus/tc/PusTcCreator.h new file mode 100644 index 00000000..abccef8d --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/tc/PusTcCreator.h @@ -0,0 +1,80 @@ +#ifndef FSFW_TMTCPACKET_TCPACKETDESERIALIZER_H +#define FSFW_TMTCPACKET_TCPACKETDESERIALIZER_H + +#include "fsfw/serialize/SerialBufferAdapter.h" +#include "fsfw/tmtcpacket/RedirectableDataPointerIF.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketCreator.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketIF.h" +#include "fsfw/tmtcpacket/pus/CustomUserDataIF.h" +#include "fsfw/tmtcpacket/pus/defs.h" +#include "fsfw/tmtcpacket/pus/tc/PusTcIF.h" + +struct PusTcParams { + PusTcParams(uint8_t service_, uint8_t subservice_) : service(service_), subservice(subservice_) {} + + void setRawAppData(const uint8_t *data, size_t len) { + bufAdapter.setConstBuffer(data, len); + appData = &bufAdapter; + } + + void setSerializableAppData(const SerializeIF &serializable) { appData = &serializable; } + + uint8_t service; + uint8_t subservice; + uint8_t ackFlags = ecss::ACK_ALL; + uint16_t sourceId = 0; + SerialBufferAdapter bufAdapter; + const SerializeIF *appData = nullptr; + uint8_t pusVersion = ecss::PusVersion::PUS_C; +}; + +/** + * This class provides a high-level interface to create PUS TC packets and then @serialize + * them into a raw byte format. It implements @SerializeIF for that purpose. + * A custom time stamper can be set, with the implementation of @TimeStamperIF as the only + * requirement. + */ +class PusTcCreator : public PusTcIF, public SerializeIF, public CustomUserDataIF { + public: + PusTcCreator(SpacePacketParams initSpParams, PusTcParams initPusParams); + + /** + * If the parameter structure is changed in a way which changes the resulting serialized packet + * size, this function should be called to set the data length field in the space packet + * header. This fields is the primary source of information for length information. + * + * The only case for a telecommand where this size changes would be if user data is set. + */ + void updateSpLengthField(); + PusTcParams &getPusParams(); + SpacePacketParams &getSpParams(); + + [[nodiscard]] size_t getSerializedSize() const override; + + [[nodiscard]] uint16_t getPacketIdRaw() const override; + [[nodiscard]] uint16_t getPacketSeqCtrlRaw() const override; + [[nodiscard]] uint16_t getPacketDataLen() const override; + [[nodiscard]] uint8_t getPusVersion() const override; + [[nodiscard]] uint8_t getAcknowledgeFlags() const override; + [[nodiscard]] uint8_t getService() const override; + [[nodiscard]] uint8_t getSubService() const override; + [[nodiscard]] uint16_t getSourceId() const override; + ReturnValue_t setRawUserData(const uint8_t *data, size_t len) override; + ReturnValue_t setSerializableUserData(const SerializeIF &serializable) override; + + // Load all big endian helpers into the class namespace + using SerializeIF::serializeBe; + + private: + // Forbidden to use, enforce big endian serialization + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override; + // Forbidden to use + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override; + void setup(); + SpacePacketCreator spCreator; + PusTcParams pusParams; +}; + +#endif // FSFW_TMTCPACKET_TCPACKETDESERIALIZER_H diff --git a/src/fsfw/tmtcpacket/pus/tc/PusTcIF.h b/src/fsfw/tmtcpacket/pus/tc/PusTcIF.h new file mode 100644 index 00000000..43e9aab0 --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/tc/PusTcIF.h @@ -0,0 +1,67 @@ +#ifndef FSFW_TMTCPACKET_PUSTCIF_H +#define FSFW_TMTCPACKET_PUSTCIF_H + +#include + +#include "fsfw/tmtcpacket/pus/PusIF.h" + +namespace ecss { + +enum AckField { + //! No acknowledgements are expected. + ACK_NONE = 0b0000, + //! Acknowledgements on acceptance are expected. + ACK_ACCEPTANCE = 0b0001, + //! Acknowledgements on start are expected. + ACK_START = 0b0010, + //! Acknowledgements on step are expected. + ACK_STEP = 0b0100, + //! Acknowledgement on completion are expected. + ACK_COMPLETION = 0b1000 +}; + +static constexpr uint8_t ACK_ALL = ACK_ACCEPTANCE | ACK_START | ACK_STEP | ACK_COMPLETION; + +/** + * This struct defines a byte-wise structured PUS C data Field Header. + * Any optional fields in the header must be added or removed here. + * Currently, the Source Id field is present with one byte. + * No spare byte support for now. + * @ingroup tmtcpackets + */ +struct PusTcDataFieldHeader { + // Version and ACK byte, Service Byte, Subservice Byte, 2 byte Source ID + static constexpr size_t MIN_SIZE = 5; + uint8_t pusVersion; + uint8_t ackFlags; + uint8_t serviceType; + uint8_t serviceSubtype; + uint16_t sourceId; +}; + +} // namespace ecss + +class PusTcIF : public PusIF { + public: + ~PusTcIF() override = default; + static const size_t MIN_SIZE = + (sizeof(ccsds::PrimaryHeader) + ecss::PusTcDataFieldHeader::MIN_SIZE + 2); + + /** + * This is a getter for the packet's Ack field, which are the lowest four + * bits of the first byte of the Data Field Header. + * + * It is packed in a uint8_t variable. + * @return The packet's PUS Ack field. + */ + [[nodiscard]] virtual uint8_t getAcknowledgeFlags() const = 0; + + /** + * The source ID can be used to have an additional identifier, e.g. for different ground + * station. + * @return + */ + [[nodiscard]] virtual uint16_t getSourceId() const = 0; +}; + +#endif // FSFW_TMTCPACKET_PUSTCIF_H diff --git a/src/fsfw/tmtcpacket/pus/tc/PusTcReader.cpp b/src/fsfw/tmtcpacket/pus/tc/PusTcReader.cpp new file mode 100644 index 00000000..06805e30 --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/tc/PusTcReader.cpp @@ -0,0 +1,86 @@ +#include "PusTcReader.h" + +#include + +#include "fsfw/globalfunctions/CRC.h" +#include "fsfw/globalfunctions/arrayprinter.h" +#include "fsfw/serialize.h" +#include "fsfw/serviceinterface/ServiceInterface.h" + +PusTcReader::PusTcReader(const uint8_t* data, size_t size) { setReadOnlyData(data, size); } + +PusTcReader::~PusTcReader() = default; + +ReturnValue_t PusTcReader::parseDataWithCrcCheck() { return parseData(true); } + +ReturnValue_t PusTcReader::parseDataWithoutCrcCheck() { return parseData(false); } + +ReturnValue_t PusTcReader::parseData(bool withCrc) { + if (pointers.spHeaderStart == nullptr or spReader.isNull()) { + return returnvalue::FAILED; + } + ReturnValue_t result = spReader.checkSize(); + if (result != returnvalue::OK) { + return result; + } + size_t currentOffset = SpacePacketReader::getHeaderLen(); + pointers.secHeaderStart = pointers.spHeaderStart + currentOffset; + // Might become variable sized field in the future + // TODO: No support for spare bytes yet + currentOffset += ecss::PusTcDataFieldHeader::MIN_SIZE; + appDataSize = spReader.getFullPacketLen() - currentOffset - sizeof(ecss::PusChecksumT); + pointers.userDataStart = nullptr; + if (appDataSize > 0) { + pointers.userDataStart = pointers.spHeaderStart + currentOffset; + } + currentOffset += appDataSize; + pointers.crcStart = pointers.spHeaderStart + currentOffset; + if (withCrc) { + uint16_t crc16 = CRC::crc16ccitt(spReader.getFullData(), getFullPacketLen()); + if (crc16 != 0) { + // Checksum failure + return PusIF::INVALID_CRC_16; + } + } + return returnvalue::OK; +} + +uint8_t PusTcReader::getPusVersion() const { return (pointers.secHeaderStart[0] >> 4) & 0b1111; } + +uint8_t PusTcReader::getAcknowledgeFlags() const { return pointers.secHeaderStart[0] & 0b1111; } + +uint8_t PusTcReader::getService() const { return pointers.secHeaderStart[1]; } + +uint8_t PusTcReader::getSubService() const { return pointers.secHeaderStart[2]; } + +uint16_t PusTcReader::getSourceId() const { + return (pointers.secHeaderStart[3] << 8) | pointers.secHeaderStart[4]; +} + +uint16_t PusTcReader::getErrorControl() const { + return (pointers.crcStart[0] << 8) | pointers.crcStart[1]; +} + +uint16_t PusTcReader::getPacketIdRaw() const { return spReader.getPacketIdRaw(); } + +uint16_t PusTcReader::getPacketSeqCtrlRaw() const { return spReader.getPacketSeqCtrlRaw(); } + +uint16_t PusTcReader::getPacketDataLen() const { return spReader.getPacketDataLen(); } + +const uint8_t* PusTcReader::getFullData() const { return pointers.spHeaderStart; } + +ReturnValue_t PusTcReader::setData(uint8_t* pData, size_t size_, void* args) { + pointers.spHeaderStart = pData; + return spReader.setReadOnlyData(pData, size_); +} + +ReturnValue_t PusTcReader::setReadOnlyData(const uint8_t* data, size_t size_) { + return setData(const_cast(data), size_, nullptr); +} + +const uint8_t* PusTcReader::getUserData() const { return pointers.userDataStart; } +size_t PusTcReader::getUserDataLen() const { return appDataSize; } + +bool PusTcReader::isNull() const { return spReader.isNull(); } + +PusTcReader::operator bool() const { return not isNull(); } diff --git a/src/fsfw/tmtcpacket/pus/tc/PusTcReader.h b/src/fsfw/tmtcpacket/pus/tc/PusTcReader.h new file mode 100644 index 00000000..03af43a9 --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/tc/PusTcReader.h @@ -0,0 +1,80 @@ +#ifndef TMTCPACKET_PUS_TCPACKETBASE_H_ +#define TMTCPACKET_PUS_TCPACKETBASE_H_ + +#include + +#include "PusTcIF.h" +#include "fsfw/tmtcpacket/RedirectableDataPointerIF.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" +#include "fsfw/tmtcpacket/pus/RawUserDataReaderIF.h" +#include "fsfw/tmtcpacket/pus/defs.h" + +/** + * This class is the basic reader class to read ECSS PUS C Telecommand packets. + * + * 1. Implements the @SpacePacketIF to provide accessor methods for the contained space packet. + * 2. Implements the @PusTcIF to provide accessor methods for generic PUS C fields + * + * This is a zero-copy reader class. It does not contain the packet data itself but a pointer to + * the data. Calling any accessor methods without pointing the object to valid data first will + * cause undefined behaviour. + * @ingroup tmtcpackets + */ +class PusTcReader : public PusTcIF, + public RawUserDataReaderIF, + public ReadablePacketIF, + public RedirectableDataPointerIF { + public: + PusTcReader() = default; + /** + * This is the default constructor. + * It sets its internal data pointer to the address passed and also + * forwards the data pointer to the parent SpacePacketBase class. + * @param setData The position where the packet data lies. + */ + PusTcReader(const uint8_t* setData, size_t size); + ~PusTcReader() override; + + explicit operator bool() const; + [[nodiscard]] bool isNull() const; + ReturnValue_t parseDataWithCrcCheck(); + ReturnValue_t parseDataWithoutCrcCheck(); + + /** + * This is a debugging helper method that prints the whole packet content + * to the screen. + */ + // void print(); + [[nodiscard]] uint16_t getPacketIdRaw() const override; + [[nodiscard]] uint16_t getPacketSeqCtrlRaw() const override; + [[nodiscard]] uint16_t getPacketDataLen() const override; + [[nodiscard]] uint8_t getPusVersion() const override; + [[nodiscard]] uint8_t getAcknowledgeFlags() const override; + [[nodiscard]] uint8_t getService() const override; + [[nodiscard]] uint8_t getSubService() const override; + [[nodiscard]] uint16_t getSourceId() const override; + [[nodiscard]] uint16_t getErrorControl() const; + const uint8_t* getFullData() const override; + + ReturnValue_t setReadOnlyData(const uint8_t* data, size_t size); + [[nodiscard]] const uint8_t* getUserData() const override; + [[nodiscard]] size_t getUserDataLen() const override; + + protected: + /** + * With this method, the packet data pointer can be redirected to another + * location. + * This call overwrites the parent's setData method to set both its + * @c tc_data pointer and the parent's @c data pointer. + * + * @param p_data A pointer to another PUS Telecommand Packet. + */ + ReturnValue_t setData(uint8_t* pData, size_t size, void* args) override; + ReturnValue_t parseData(bool withCrc); + + SpacePacketReader spReader; + ecss::PusPointers pointers{}; + size_t appDataSize = 0; +}; + +#endif /* TMTCPACKET_PUS_TCPACKETBASE_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tc/TcPacketPus.cpp b/src/fsfw/tmtcpacket/pus/tc/TcPacketPus.cpp deleted file mode 100644 index f5ebe38c..00000000 --- a/src/fsfw/tmtcpacket/pus/tc/TcPacketPus.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "TcPacketPus.h" - -#include - -#include "fsfw/globalfunctions/CRC.h" - -TcPacketPus::TcPacketPus(const uint8_t *setData) : TcPacketPusBase(setData) { - tcData = reinterpret_cast(const_cast(setData)); -} - -void TcPacketPus::initializeTcPacket(uint16_t apid, uint16_t sequenceCount, uint8_t ack, - uint8_t service, uint8_t subservice, - pus::PusVersion pusVersion, uint16_t sourceId) { - initSpacePacketHeader(true, true, apid, sequenceCount); - std::memset(&tcData->dataField, 0, sizeof(tcData->dataField)); - setPacketDataLength(sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1); - // Data Field Header. For PUS A, the first bit (CCSDS Secondary Header Flag) is zero - tcData->dataField.versionTypeAck = pusVersion << 4 | (ack & 0x0F); - tcData->dataField.serviceType = service; - tcData->dataField.serviceSubtype = subservice; -#if FSFW_USE_PUS_C_TELECOMMANDS == 1 - tcData->dataField.sourceIdH = (sourceId >> 8) | 0xff; - tcData->dataField.sourceIdL = sourceId & 0xff; -#else - tcData->dataField.sourceId = sourceId; -#endif -} - -uint8_t TcPacketPus::getService() const { return tcData->dataField.serviceType; } - -uint8_t TcPacketPus::getSubService() const { return tcData->dataField.serviceSubtype; } - -uint8_t TcPacketPus::getAcknowledgeFlags() const { - return tcData->dataField.versionTypeAck & 0b00001111; -} - -const uint8_t *TcPacketPus::getApplicationData() const { return &tcData->appData; } - -uint16_t TcPacketPus::getApplicationDataSize() const { - return getPacketDataLength() - sizeof(tcData->dataField) - CRC_SIZE + 1; -} - -uint16_t TcPacketPus::getErrorControl() const { - uint16_t size = getApplicationDataSize() + CRC_SIZE; - uint8_t *p_to_buffer = &tcData->appData; - return (p_to_buffer[size - 2] << 8) + p_to_buffer[size - 1]; -} - -void TcPacketPus::setErrorControl() { - uint32_t full_size = getFullSize(); - uint16_t crc = CRC::crc16ccitt(getWholeData(), full_size - CRC_SIZE); - uint32_t size = getApplicationDataSize(); - (&tcData->appData)[size] = (crc & 0XFF00) >> 8; // CRCH - (&tcData->appData)[size + 1] = (crc)&0X00FF; // CRCL -} - -uint8_t TcPacketPus::getSecondaryHeaderFlag() const { -#if FSFW_USE_PUS_C_TELECOMMANDS == 1 - // Does not exist for PUS C - return 0; -#else - return (tcData->dataField.versionTypeAck & 0b10000000) >> 7; -#endif -} - -uint8_t TcPacketPus::getPusVersionNumber() const { -#if FSFW_USE_PUS_C_TELECOMMANDS == 1 - return (tcData->dataField.versionTypeAck & 0b11110000) >> 4; -#else - return (tcData->dataField.versionTypeAck & 0b01110000) >> 4; -#endif -} - -uint16_t TcPacketPus::getSourceId() const { -#if FSFW_USE_PUS_C_TELECOMMANDS == 1 - return (tcData->dataField.sourceIdH << 8) | tcData->dataField.sourceIdL; -#else - return tcData->dataField.sourceId; -#endif -} - -size_t TcPacketPus::calculateFullPacketLength(size_t appDataLen) const { - return sizeof(CCSDSPrimaryHeader) + sizeof(PUSTcDataFieldHeader) + appDataLen + - TcPacketPusBase::CRC_SIZE; -} - -ReturnValue_t TcPacketPus::setData(uint8_t *dataPtr, size_t maxSize, void *args) { - ReturnValue_t result = SpacePacketBase::setData(dataPtr, maxSize); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - if (maxSize < sizeof(TcPacketPointer)) { - return HasReturnvaluesIF::RETURN_FAILED; - } - // This function is const-correct, but it was decided to keep the pointer non-const - // for convenience. Therefore, cast away constness here and then cast to packet type. - tcData = reinterpret_cast(const_cast(dataPtr)); - return HasReturnvaluesIF::RETURN_OK; -} diff --git a/src/fsfw/tmtcpacket/pus/tc/TcPacketPus.h b/src/fsfw/tmtcpacket/pus/tc/TcPacketPus.h deleted file mode 100644 index 47173dad..00000000 --- a/src/fsfw/tmtcpacket/pus/tc/TcPacketPus.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef FSFW_TMTCPACKET_PUS_TCPACKETPUSA_H_ -#define FSFW_TMTCPACKET_PUS_TCPACKETPUSA_H_ - -#include - -#include "../definitions.h" -#include "TcPacketPusBase.h" -#include "fsfw/FSFW.h" -#include "fsfw/tmtcpacket/ccsds_header.h" - -/** - * This struct defines a byte-wise structured PUS TC A Data Field Header. - * Any optional fields in the header must be added or removed here. - * Currently, the Source Id field is present with one byte. - * @ingroup tmtcpackets - */ -struct PUSTcDataFieldHeader { - uint8_t versionTypeAck; - uint8_t serviceType; - uint8_t serviceSubtype; -#if FSFW_USE_PUS_C_TELECOMMANDS == 1 - uint8_t sourceIdH; - uint8_t sourceIdL; -#else - uint8_t sourceId; -#endif -}; - -/** - * This struct defines the data structure of a PUS Telecommand A packet when - * accessed via a pointer. - * @ingroup tmtcpackets - */ -struct TcPacketPointer { - CCSDSPrimaryHeader primary; - PUSTcDataFieldHeader dataField; - uint8_t appData; -}; - -class TcPacketPus : public TcPacketPusBase { - public: - static const uint16_t TC_PACKET_MIN_SIZE = - (sizeof(CCSDSPrimaryHeader) + sizeof(PUSTcDataFieldHeader) + 2); - - /** - * Initialize a PUS A telecommand packet which already exists. You can also - * create an empty (invalid) object by passing nullptr as the data pointer - * @param setData - */ - TcPacketPus(const uint8_t* setData); - - // Base class overrides - uint8_t getSecondaryHeaderFlag() const override; - uint8_t getPusVersionNumber() const override; - uint8_t getAcknowledgeFlags() const override; - uint8_t getService() const override; - uint8_t getSubService() const override; - uint16_t getSourceId() const override; - const uint8_t* getApplicationData() const override; - uint16_t getApplicationDataSize() const override; - uint16_t getErrorControl() const override; - void setErrorControl() override; - size_t calculateFullPacketLength(size_t appDataLen) const override; - - 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. - * - * To be hardware-safe, all elements are of byte size. - */ - TcPacketPointer* tcData = nullptr; -}; - -#endif /* FSFW_TMTCPACKET_PUS_TCPACKETPUSA_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tc/TcPacketPusBase.cpp b/src/fsfw/tmtcpacket/pus/tc/TcPacketPusBase.cpp deleted file mode 100644 index 812bae43..00000000 --- a/src/fsfw/tmtcpacket/pus/tc/TcPacketPusBase.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "TcPacketPusBase.h" - -#include - -#include "fsfw/globalfunctions/CRC.h" -#include "fsfw/globalfunctions/arrayprinter.h" -#include "fsfw/serviceinterface/ServiceInterface.h" - -TcPacketPusBase::TcPacketPusBase(const uint8_t* setData) : SpacePacketBase(setData) {} - -TcPacketPusBase::~TcPacketPusBase() {} - -void TcPacketPusBase::print() { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::info << "TcPacketBase::print:" << std::endl; -#else - sif::printInfo("TcPacketBase::print:\n"); -#endif - arrayprinter::print(getWholeData(), getFullSize()); -} diff --git a/src/fsfw/tmtcpacket/pus/tc/TcPacketPusBase.h b/src/fsfw/tmtcpacket/pus/tc/TcPacketPusBase.h deleted file mode 100644 index 9f1d07ed..00000000 --- a/src/fsfw/tmtcpacket/pus/tc/TcPacketPusBase.h +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef TMTCPACKET_PUS_TCPACKETBASE_H_ -#define TMTCPACKET_PUS_TCPACKETBASE_H_ - -#include - -#include - -#include "fsfw/tmtcpacket/SpacePacketBase.h" - -/** - * This class is the basic data handler for any ECSS PUS Telecommand packet. - * - * In addition to #SpacePacketBase, the class provides methods to handle - * the standardized entries of the PUS TC Packet Data Field Header. - * It does not contain the packet data itself but a pointer to the - * data must be set on instantiation. An invalid pointer may cause - * damage, as no getter method checks data validity. Anyway, a NULL - * check can be performed by making use of the getWholeData method. - * @ingroup tmtcpackets - */ -class TcPacketPusBase : public SpacePacketBase, virtual public RedirectableDataPointerIF { - friend class TcPacketStoredBase; - - public: - enum AckField { - //! No acknowledgements are expected. - ACK_NONE = 0b0000, - //! Acknowledgements on acceptance are expected. - ACK_ACCEPTANCE = 0b0001, - //! Acknowledgements on start are expected. - ACK_START = 0b0010, - //! Acknowledgements on step are expected. - ACK_STEP = 0b0100, - //! Acknowledfgement on completion are expected. - ACK_COMPLETION = 0b1000 - }; - - static constexpr uint8_t ACK_ALL = ACK_ACCEPTANCE | ACK_START | ACK_STEP | ACK_COMPLETION; - - /** - * This is the default constructor. - * It sets its internal data pointer to the address passed and also - * forwards the data pointer to the parent SpacePacketBase class. - * @param setData The position where the packet data lies. - */ - TcPacketPusBase(const uint8_t* setData); - /** - * This is the empty default destructor. - */ - virtual ~TcPacketPusBase(); - - /** - * This command returns the CCSDS Secondary Header Flag. - * It shall always be zero for PUS Packets. This is the - * highest bit of the first byte of the Data Field Header. - * @return the CCSDS Secondary Header Flag - */ - virtual uint8_t getSecondaryHeaderFlag() const = 0; - /** - * This command returns the TC Packet PUS Version Number. - * The version number of ECSS PUS 2003 is 1. - * It consists of the second to fourth highest bits of the - * first byte. - * @return - */ - virtual uint8_t getPusVersionNumber() const = 0; - /** - * This is a getter for the packet's Ack field, which are the lowest four - * bits of the first byte of the Data Field Header. - * - * It is packed in a uint8_t variable. - * @return The packet's PUS Ack field. - */ - virtual uint8_t getAcknowledgeFlags() const = 0; - /** - * This is a getter for the packet's PUS Service ID, which is the second - * byte of the Data Field Header. - * @return The packet's PUS Service ID. - */ - virtual uint8_t getService() const = 0; - /** - * This is a getter for the packet's PUS Service Subtype, which is the - * third byte of the Data Field Header. - * @return The packet's PUS Service Subtype. - */ - virtual uint8_t getSubService() const = 0; - /** - * The source ID can be used to have an additional identifier, e.g. for different ground - * station. - * @return - */ - virtual uint16_t getSourceId() const = 0; - - /** - * This is a getter for a pointer to the packet's Application data. - * - * These are the bytes that follow after the Data Field Header. They form - * the packet's application data. - * @return A pointer to the PUS Application Data. - */ - virtual const uint8_t* getApplicationData() const = 0; - /** - * This method calculates the size of the PUS Application data field. - * - * It takes the information stored in the CCSDS Packet Data Length field - * and subtracts the Data Field Header size and the CRC size. - * @return The size of the PUS Application Data (without Error Control - * field) - */ - virtual uint16_t getApplicationDataSize() const = 0; - /** - * This getter returns the Error Control Field of the packet. - * - * The field is placed after any possible Application Data. If no - * Application Data is present there's still an Error Control field. It is - * supposed to be a 16bit-CRC. - * @return The PUS Error Control - */ - virtual uint16_t getErrorControl() const = 0; - /** - * With this method, the Error Control Field is updated to match the - * current content of the packet. - */ - virtual void setErrorControl() = 0; - - /** - * Calculate full packet length from application data length. - * @param appDataLen - * @return - */ - virtual size_t calculateFullPacketLength(size_t appDataLen) const = 0; - - /** - * This is a debugging helper method that prints the whole packet content - * to the screen. - */ - void print(); - - protected: - /** - * With this method, the packet data pointer can be redirected to another - * location. - * This call overwrites the parent's setData method to set both its - * @c tc_data pointer and the parent's @c data pointer. - * - * @param p_data A pointer to another PUS Telecommand Packet. - */ - virtual ReturnValue_t setData(uint8_t* pData, size_t maxSize, void* args = nullptr) override = 0; -}; - -#endif /* TMTCPACKET_PUS_TCPACKETBASE_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredBase.cpp b/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredBase.cpp deleted file mode 100644 index 8cc38c5f..00000000 --- a/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredBase.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "fsfw/tmtcpacket/pus/tc/TcPacketStoredBase.h" - -#include - -#include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/objectmanager/frameworkObjects.h" -#include "fsfw/serviceinterface/ServiceInterface.h" - -StorageManagerIF* TcPacketStoredBase::store = nullptr; - -TcPacketStoredBase::TcPacketStoredBase() { - this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - this->checkAndSetStore(); -} - -TcPacketStoredBase::~TcPacketStoredBase() {} - -ReturnValue_t TcPacketStoredBase::getData(const uint8_t** dataPtr, size_t* dataSize) { - auto result = this->store->getData(storeAddress, dataPtr, dataSize); - if (result != HasReturnvaluesIF::RETURN_OK) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TcPacketStoredBase: Could not get data!" << std::endl; -#else - sif::printWarning("TcPacketStoredBase: Could not get data!\n"); -#endif - } - return result; -} - -bool TcPacketStoredBase::checkAndSetStore() { - if (this->store == nullptr) { - this->store = ObjectManager::instance()->get(objects::TC_STORE); - if (this->store == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TcPacketStoredBase::TcPacketStoredBase: TC Store not found!" << std::endl; -#endif - return false; - } - } - return true; -} - -void TcPacketStoredBase::setStoreAddress(store_address_t setAddress, - RedirectableDataPointerIF* packet) { - this->storeAddress = setAddress; - const uint8_t* tempData = nullptr; - size_t tempSize; - ReturnValue_t status = StorageManagerIF::RETURN_FAILED; - if (this->checkAndSetStore()) { - status = this->store->getData(this->storeAddress, &tempData, &tempSize); - } - - if (status == StorageManagerIF::RETURN_OK) { - packet->setData(const_cast(tempData), tempSize); - } else { - packet->setData(nullptr, -1); - this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - } -} - -store_address_t TcPacketStoredBase::getStoreAddress() { return this->storeAddress; } diff --git a/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredBase.h b/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredBase.h deleted file mode 100644 index 86f0d94e..00000000 --- a/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredBase.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef TMTCPACKET_PUS_TCPACKETSTORED_H_ -#define TMTCPACKET_PUS_TCPACKETSTORED_H_ - -#include "TcPacketStoredIF.h" -#include "fsfw/storagemanager/StorageManagerIF.h" - -/** - * Base class for telecommand packets like CFDP or PUS packets. - * @ingroup tmtcpackets - */ -class TcPacketStoredBase : public TcPacketStoredIF { - public: - /** - * This is a default constructor which does not set the data pointer to initialize - * with an empty cached store address - */ - TcPacketStoredBase(); - /** - * Constructor to set to an existing store address. - * @param setAddress - */ - TcPacketStoredBase(store_address_t setAddress); - /** - * Another constructor to create a TcPacket from a raw packet stream. - * Takes the data and adds it unchecked to the TcStore. - * @param data Pointer to the complete TC Space Packet. - * @param Size size of the packet. - */ - TcPacketStoredBase(const uint8_t* data, uint32_t size); - - virtual ~TcPacketStoredBase(); - - /** - * Getter function for the raw data. - * @param dataPtr [out] Pointer to the data pointer to set - * @param dataSize [out] Address of size to set. - * @return -@c RETURN_OK if data was retrieved successfully. - */ - ReturnValue_t getData(const uint8_t** dataPtr, size_t* dataSize) override; - - void setStoreAddress(store_address_t setAddress, RedirectableDataPointerIF* packet) override; - store_address_t getStoreAddress() override; - - /** - * With this call, the packet is deleted. - * It removes itself from the store and sets its data pointer to NULL. - * @return returncode from deleting the data. - */ - virtual ReturnValue_t deletePacket() = 0; - - /** - * This method performs a size check. - * It reads the stored size and compares it with the size entered in the - * packet header. This class is the optimal place for such a check as it - * has access to both the header data and the store. - * @return true if size is correct, false if packet is not registered in - * store or size is incorrect. - */ - virtual bool isSizeCorrect() = 0; - - protected: - /** - * This is a pointer to the store all instances of the class use. - * If the store is not yet set (i.e. @c store is NULL), every constructor - * call tries to set it and throws an error message in case of failures. - * The default store is objects::TC_STORE. - */ - static StorageManagerIF* store; - /** - * The address where the packet data of the object instance is stored. - */ - store_address_t storeAddress; - /** - * A helper method to check if a store is assigned to the class. - * If not, the method tries to retrieve the store from the global - * ObjectManager. - * @return @li @c true if the store is linked or could be created. - * @li @c false otherwise. - */ - bool checkAndSetStore(); -}; - -#endif /* TMTCPACKET_PUS_TcPacketStoredBase_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredIF.h b/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredIF.h deleted file mode 100644 index ac4019cd..00000000 --- a/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredIF.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef FSFW_TMTCPACKET_PUS_TCPACKETSTOREDIF_H_ -#define FSFW_TMTCPACKET_PUS_TCPACKETSTOREDIF_H_ - -#include - -#include "TcPacketPusBase.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" -#include "fsfw/storagemanager/storeAddress.h" - -class TcPacketStoredIF { - public: - virtual ~TcPacketStoredIF(){}; - - /** - * With this call, the stored packet can be set to another packet in a store. This is useful - * if the packet is a class member and used for more than one packet. - * @param setAddress The new packet id to link to. - */ - virtual void setStoreAddress(store_address_t setAddress, RedirectableDataPointerIF* packet) = 0; - - virtual store_address_t getStoreAddress() = 0; - - /** - * Getter function for the raw data. - * @param dataPtr [out] Pointer to the data pointer to set - * @param dataSize [out] Address of size to set. - * @return -@c RETURN_OK if data was retrieved successfully. - */ - virtual ReturnValue_t getData(const uint8_t** dataPtr, size_t* dataSize) = 0; -}; - -#endif /* FSFW_TMTCPACKET_PUS_TCPACKETSTOREDIF_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredPus.cpp b/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredPus.cpp deleted file mode 100644 index 153ad863..00000000 --- a/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredPus.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "fsfw/tmtcpacket/pus/tc/TcPacketStoredPus.h" - -#include - -#include "fsfw/serviceinterface/ServiceInterface.h" - -TcPacketStoredPus::TcPacketStoredPus(uint16_t apid, uint8_t service, uint8_t subservice, - uint8_t sequenceCount, const uint8_t* data, size_t size, - uint8_t ack) - : TcPacketPus(nullptr) { - this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - if (not this->checkAndSetStore()) { - return; - } - uint8_t* pData = nullptr; - ReturnValue_t returnValue = - this->store->getFreeElement(&this->storeAddress, (TC_PACKET_MIN_SIZE + size), &pData); - if (returnValue != this->store->RETURN_OK) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TcPacketStoredBase: Could not get free element from store!" << std::endl; -#endif - return; - } - this->setData(pData, TC_PACKET_MIN_SIZE + size); -#if FSFW_USE_PUS_C_TELECOMMANDS == 1 - pus::PusVersion pusVersion = pus::PusVersion::PUS_C_VERSION; -#else - 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->setErrorControl(); -} - -TcPacketStoredPus::TcPacketStoredPus() : TcPacketStoredBase(), TcPacketPus(nullptr) {} - -TcPacketStoredPus::TcPacketStoredPus(store_address_t setAddress) : TcPacketPus(nullptr) { - TcPacketStoredBase::setStoreAddress(setAddress, this); -} - -TcPacketStoredPus::TcPacketStoredPus(const uint8_t* data, size_t size) : TcPacketPus(data) { - if (this->getFullSize() != size) { - return; - } - if (this->checkAndSetStore()) { - ReturnValue_t status = store->addData(&storeAddress, data, size); - if (status != HasReturnvaluesIF::RETURN_OK) { - this->setData(nullptr, size); - } - const uint8_t* storePtr = nullptr; - // Repoint base data pointer to the data in the store. - store->getData(storeAddress, &storePtr, &size); - this->setData(const_cast(storePtr), size); - } -} - -ReturnValue_t TcPacketStoredPus::deletePacket() { - ReturnValue_t result = this->store->deleteData(this->storeAddress); - this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - // To circumvent size checks - this->setData(nullptr, -1); - return result; -} - -TcPacketPusBase* TcPacketStoredPus::getPacketBase() { return this; } - -bool TcPacketStoredPus::isSizeCorrect() { - const uint8_t* temp_data = nullptr; - size_t temp_size; - ReturnValue_t status = this->store->getData(this->storeAddress, &temp_data, &temp_size); - if (status == StorageManagerIF::RETURN_OK) { - if (this->getFullSize() == temp_size) { - return true; - } - } - return false; -} diff --git a/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredPus.h b/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredPus.h deleted file mode 100644 index 45dec293..00000000 --- a/src/fsfw/tmtcpacket/pus/tc/TcPacketStoredPus.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef FSFW_TMTCPACKET_PUS_TCPACKETSTOREDPUSA_H_ -#define FSFW_TMTCPACKET_PUS_TCPACKETSTOREDPUSA_H_ - -#include "TcPacketPus.h" -#include "TcPacketStoredBase.h" - -class TcPacketStoredPus : public TcPacketStoredBase, public TcPacketPus { - public: - /** - * With this constructor, new space is allocated in the packet store and - * a new PUS Telecommand Packet is created there. - * Packet Application Data passed in data is copied into the packet. - * @param apid Sets the packet's APID field. - * @param service Sets the packet's Service ID field. - * This specifies the destination service. - * @param subservice Sets the packet's Service Subtype field. - * This specifies the destination sub-service. - * @param sequence_count Sets the packet's Source Sequence Count field. - * @param data The data to be copied to the Application Data Field. - * @param size The amount of data to be copied. - * @param ack Set's the packet's Ack field, which specifies - * number of verification packets returned - * for this command. - */ - TcPacketStoredPus(uint16_t apid, uint8_t service, uint8_t subservice, uint8_t sequence_count = 0, - const uint8_t* data = nullptr, size_t size = 0, - uint8_t ack = TcPacketPusBase::ACK_ALL); - /** - * Create stored packet with existing data. - * @param data - * @param size - */ - TcPacketStoredPus(const uint8_t* data, size_t size); - /** - * Create stored packet from existing packet in store - * @param setAddress - */ - TcPacketStoredPus(store_address_t setAddress); - TcPacketStoredPus(); - - ReturnValue_t deletePacket() override; - TcPacketPusBase* getPacketBase(); - - private: - bool isSizeCorrect() override; -}; - -#endif /* FSFW_TMTCPACKET_PUS_TCPACKETSTOREDPUSA_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tm.h b/src/fsfw/tmtcpacket/pus/tm.h index afbe8251..fc3f0b94 100644 --- a/src/fsfw/tmtcpacket/pus/tm.h +++ b/src/fsfw/tmtcpacket/pus/tm.h @@ -1,16 +1,8 @@ #ifndef FSFW_TMTCPACKET_PUS_TM_H_ #define FSFW_TMTCPACKET_PUS_TM_H_ -#include "fsfw/FSFW.h" - -#if FSFW_USE_PUS_C_TELEMETRY == 1 -#include "tm/TmPacketPusC.h" -#include "tm/TmPacketStoredPusC.h" -#else -#include "tm/TmPacketPusA.h" -#include "tm/TmPacketStoredPusA.h" -#endif - -#include "tm/TmPacketMinimal.h" +#include "tm/PusTmCreator.h" +#include "tm/PusTmReader.h" +#include "tm/PusTmZcWriter.h" #endif /* FSFW_TMTCPACKET_PUS_TM_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tm/CMakeLists.txt b/src/fsfw/tmtcpacket/pus/tm/CMakeLists.txt index ace87820..1395d927 100644 --- a/src/fsfw/tmtcpacket/pus/tm/CMakeLists.txt +++ b/src/fsfw/tmtcpacket/pus/tm/CMakeLists.txt @@ -1,9 +1,2 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - TmPacketStoredPusA.cpp - TmPacketStoredPusC.cpp - TmPacketPusA.cpp - TmPacketPusC.cpp - TmPacketStoredBase.cpp - TmPacketBase.cpp - TmPacketMinimal.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE PusTmCreator.cpp PusTmReader.cpp + PusTmMinimal.cpp PusTmZcWriter.cpp) diff --git a/src/fsfw/tmtcpacket/pus/tm/PusTmCreator.cpp b/src/fsfw/tmtcpacket/pus/tm/PusTmCreator.cpp new file mode 100644 index 00000000..c9b3290a --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/tm/PusTmCreator.cpp @@ -0,0 +1,152 @@ +#include "PusTmCreator.h" + +#include + +#include "fsfw/globalfunctions/CRC.h" +#include "fsfw/timemanager/TimeWriterIF.h" + +PusTmCreator::PusTmCreator(SpacePacketParams initSpParams, PusTmParams initPusParams) + : pusParams(initPusParams), spCreator(std::move(initSpParams)) { + setup(); +} + +PusTmCreator::PusTmCreator() { setup(); } + +void PusTmCreator::disableCrcCalculation() { calculateCrcOnSerialization = false; } + +void PusTmCreator::enableCrcCalculation() { calculateCrcOnSerialization = true; } + +uint16_t PusTmCreator::getPacketIdRaw() const { return spCreator.getPacketIdRaw(); } + +uint16_t PusTmCreator::getPacketSeqCtrlRaw() const { return spCreator.getPacketSeqCtrlRaw(); } + +uint16_t PusTmCreator::getPacketDataLen() const { return spCreator.getPacketDataLen(); } + +uint8_t PusTmCreator::getPusVersion() const { return pusParams.secHeader.pusVersion; } + +uint8_t PusTmCreator::getService() const { return pusParams.secHeader.service; } + +uint8_t PusTmCreator::getSubService() const { return pusParams.secHeader.subservice; } + +PusTmParams& PusTmCreator::getParams() { return pusParams; } + +void PusTmCreator::setTimeStamper(TimeWriterIF& timeStamper_) { + pusParams.secHeader.timeStamper = &timeStamper_; + updateSpLengthField(); +} + +uint8_t PusTmCreator::getScTimeRefStatus() { return pusParams.secHeader.scTimeRefStatus; } + +uint16_t PusTmCreator::getMessageTypeCounter() { return pusParams.secHeader.messageTypeCounter; } + +uint16_t PusTmCreator::getDestId() { return pusParams.secHeader.destId; } + +ReturnValue_t PusTmCreator::serialize(uint8_t** buffer, size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const { + const uint8_t* start = *buffer; + if (*size + getSerializedSize() > maxSize) { + return SerializeIF::BUFFER_TOO_SHORT; + } + ReturnValue_t result = spCreator.serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + **buffer = + ((pusParams.secHeader.pusVersion << 4) & 0xF0) | (pusParams.secHeader.scTimeRefStatus & 0x0F); + *buffer += 1; + **buffer = pusParams.secHeader.service; + *buffer += 1; + **buffer = pusParams.secHeader.subservice; + *buffer += 1; + *size += 3; + result = SerializeAdapter::serialize(&pusParams.secHeader.messageTypeCounter, buffer, size, + maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + result = SerializeAdapter::serialize(&pusParams.secHeader.destId, buffer, size, maxSize, + streamEndianness); + if (result != returnvalue::OK) { + return result; + } + if (getTimestamper() != nullptr) { + result = pusParams.secHeader.timeStamper->serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + } + + if (pusParams.sourceData != nullptr) { + result = pusParams.sourceData->serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + } + if (calculateCrcOnSerialization) { + uint16_t crc16 = CRC::crc16ccitt(start, getFullPacketLen() - sizeof(ecss::PusChecksumT)); + return SerializeAdapter::serialize(&crc16, buffer, size, maxSize, streamEndianness); + } + // Even if no CRC is calculated, account for the space taken by it + *size += 2; + *buffer += 2; + return returnvalue::OK; +} + +size_t PusTmCreator::getSerializedSize() const { return getFullPacketLen(); } +ReturnValue_t PusTmCreator::deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) { + return returnvalue::FAILED; +} + +TimeWriterIF* PusTmCreator::getTimestamper() const { return pusParams.secHeader.timeStamper; } + +SpacePacketParams& PusTmCreator::getSpParams() { return spCreator.getParams(); } + +void PusTmCreator::updateSpLengthField() { + size_t headerLen = PusTmIF::MIN_SEC_HEADER_LEN + sizeof(ecss::PusChecksumT); + if (pusParams.sourceData != nullptr) { + headerLen += pusParams.sourceData->getSerializedSize(); + } + if (pusParams.secHeader.timeStamper != nullptr) { + headerLen += pusParams.secHeader.timeStamper->getSerializedSize(); + } + spCreator.setCcsdsLenFromTotalDataFieldLen(headerLen); +} + +void PusTmCreator::setApid(uint16_t apid) { spCreator.setApid(apid); } + +void PusTmCreator::setup() { + updateSpLengthField(); + spCreator.setPacketType(ccsds::PacketType::TM); + spCreator.setSecHeaderFlag(); + spCreator.setSeqFlags(ccsds::SequenceFlags::UNSEGMENTED); +} + +void PusTmCreator::setMessageTypeCounter(uint16_t messageTypeCounter) { + pusParams.secHeader.messageTypeCounter = messageTypeCounter; +}; + +void PusTmCreator::setDestId(uint16_t destId) { pusParams.secHeader.destId = destId; } + +ReturnValue_t PusTmCreator::setRawUserData(const uint8_t* data, size_t len) { + if (data == nullptr or len == 0) { + pusParams.sourceData = nullptr; + } else { + pusParams.adapter.setConstBuffer(data, len); + pusParams.sourceData = &pusParams.adapter; + } + updateSpLengthField(); + return returnvalue::OK; +} +ReturnValue_t PusTmCreator::setSerializableUserData(const SerializeIF& serializable) { + pusParams.sourceData = &serializable; + updateSpLengthField(); + return returnvalue::OK; +} + +void PusTmCreator::setService(uint8_t service) { pusParams.secHeader.service = service; } + +void PusTmCreator::setSubservice(uint8_t subservice) { + pusParams.secHeader.subservice = subservice; +} +bool PusTmCreator::crcCalculationEnabled() const { return calculateCrcOnSerialization; } diff --git a/src/fsfw/tmtcpacket/pus/tm/PusTmCreator.h b/src/fsfw/tmtcpacket/pus/tm/PusTmCreator.h new file mode 100644 index 00000000..19922b2f --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/tm/PusTmCreator.h @@ -0,0 +1,111 @@ +#ifndef FSFW_TMTCPACKET_TMPACKETCREATOR_H +#define FSFW_TMTCPACKET_TMPACKETCREATOR_H + +#include "PusTmIF.h" +#include "fsfw/serialize/SerialBufferAdapter.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketCreator.h" +#include "fsfw/tmtcpacket/pus/CustomUserDataIF.h" + +struct PusTmSecHeader { + PusTmSecHeader() = default; + PusTmSecHeader(uint8_t service, uint8_t subservice, TimeWriterIF* timeStamper) + : service(service), subservice(subservice), timeStamper(timeStamper) {} + + uint8_t service = 0; + uint8_t subservice = 0; + TimeWriterIF* timeStamper = nullptr; + uint8_t pusVersion = ecss::PusVersion::PUS_C; + uint8_t scTimeRefStatus = 0; + uint16_t messageTypeCounter = 0; + uint16_t destId = 0; +}; + +struct PusTmParams { + PusTmParams() = default; + explicit PusTmParams(PusTmSecHeader secHeader) : secHeader(secHeader){}; + PusTmParams(PusTmSecHeader secHeader, const SerializeIF& data) + : secHeader(secHeader), sourceData(&data) {} + PusTmParams(PusTmSecHeader secHeader, const uint8_t* data, size_t dataLen) + : secHeader(secHeader), adapter(data, dataLen), sourceData(&adapter) {} + PusTmParams(uint8_t service, uint8_t subservice, TimeWriterIF* timeStamper) + : secHeader(service, subservice, timeStamper) {} + + PusTmParams(uint8_t service, uint8_t subservice, TimeWriterIF* timeStamper, + const SerializeIF& data_) + : PusTmParams(service, subservice, timeStamper) { + sourceData = &data_; + } + + PusTmParams(uint8_t service, uint8_t subservice, TimeWriterIF* timeStamper, const uint8_t* data, + size_t dataLen) + : secHeader(service, subservice, timeStamper), adapter(data, dataLen), sourceData(&adapter) {} + PusTmSecHeader secHeader; + SerialBufferAdapter adapter; + const SerializeIF* sourceData = nullptr; +}; + +class TimeWriterIF; + +/** + * This class provides a high-level interface to create PUS TM packets and then @serialize + * them into a raw byte format. It implements @SerializeIF for that purpose. + * A custom time stamper can be set, with the implementation of @TimeStamperIF as the only + * requirement. + */ +class PusTmCreator : public SerializeIF, public PusTmIF, public CustomUserDataIF { + public: + /** + * Empty creator with all-default parameters. Please note that serializing this will + * generate an invalid PUS packet with no timestamp. + */ + PusTmCreator(); + PusTmCreator(SpacePacketParams initSpParams, PusTmParams initPusParams); + ~PusTmCreator() override = default; + + void setTimeStamper(TimeWriterIF& timeStamper); + /** + * This function disables the CRC16 calculation on serialization. This is useful to avoid + * duplicate calculation if some lower level component needs to update fields like the sequence + * count, which would require a checksum update. + */ + void disableCrcCalculation(); + void enableCrcCalculation(); + [[nodiscard]] bool crcCalculationEnabled() const; + + SpacePacketParams& getSpParams(); + void setApid(uint16_t apid); + void setDestId(uint16_t destId); + void setService(uint8_t service); + void setSubservice(uint8_t subservice); + void setMessageTypeCounter(uint16_t messageTypeCounter); + PusTmParams& getParams(); + void updateSpLengthField(); + [[nodiscard]] uint16_t getPacketIdRaw() const override; + [[nodiscard]] uint16_t getPacketSeqCtrlRaw() const override; + [[nodiscard]] uint16_t getPacketDataLen() const override; + [[nodiscard]] uint8_t getPusVersion() const override; + [[nodiscard]] uint8_t getService() const override; + [[nodiscard]] uint8_t getSubService() const override; + uint8_t getScTimeRefStatus() override; + uint16_t getMessageTypeCounter() override; + uint16_t getDestId() override; + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override; + [[nodiscard]] size_t getSerializedSize() const override; + [[nodiscard]] TimeWriterIF* getTimestamper() const; + ReturnValue_t setRawUserData(const uint8_t* data, size_t len) override; + ReturnValue_t setSerializableUserData(const SerializeIF& serializable) override; + + // Load all big endian (network endian) helpers into scope + using SerializeIF::serializeBe; + + private: + // Forbidden to use + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; + void setup(); + PusTmParams pusParams{}; + bool calculateCrcOnSerialization = true; + SpacePacketCreator spCreator; +}; +#endif // FSFW_TMTCPACKET_TMPACKETCREATOR_H diff --git a/src/fsfw/tmtcpacket/pus/tm/PusTmIF.h b/src/fsfw/tmtcpacket/pus/tm/PusTmIF.h new file mode 100644 index 00000000..ee3005ca --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/tm/PusTmIF.h @@ -0,0 +1,29 @@ +#ifndef FSFW_TMTCPACKET_PUSTMIF_H +#define FSFW_TMTCPACKET_PUSTMIF_H + +#include +#include + +#include "fsfw/timemanager/TimeWriterIF.h" +#include "fsfw/tmtcpacket/pus/PusIF.h" +#include "fsfw/tmtcpacket/pus/defs.h" + +class PusTmIF : public PusIF { + public: + ~PusTmIF() override = default; + + /** + * Minimum length without timestamp + */ + static constexpr size_t MIN_SEC_HEADER_LEN = 7; + /** + * 2 bytes for CRC16 + */ + static constexpr size_t MIN_SIZE = sizeof(ccsds::PrimaryHeader) + MIN_SEC_HEADER_LEN + 2; + + virtual uint8_t getScTimeRefStatus() = 0; + virtual uint16_t getMessageTypeCounter() = 0; + virtual uint16_t getDestId() = 0; +}; + +#endif // FSFW_TMTCPACKET_PUSTMIF_H diff --git a/src/fsfw/tmtcpacket/pus/tm/PusTmMinimal.cpp b/src/fsfw/tmtcpacket/pus/tm/PusTmMinimal.cpp new file mode 100644 index 00000000..3c0e6f64 --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/tm/PusTmMinimal.cpp @@ -0,0 +1,49 @@ +#include "fsfw/tmtcpacket/pus/tm/PusTmMinimal.h" + +#include +#include + +#include "fsfw/tmtcpacket/pus/PacketTimestampInterpreterIF.h" + +PusTmMinimal::PusTmMinimal(mintm::MinimalPusTm* data) { tmData = data; } +PusTmMinimal::PusTmMinimal(uint8_t* data) { + this->tmData = reinterpret_cast(data); +} + +PusTmMinimal::~PusTmMinimal() = default; + +ReturnValue_t PusTmMinimal::getPacketTime(timeval* timestamp) { + if (timestampInterpreter == nullptr) { + return returnvalue::FAILED; + } + return timestampInterpreter->getPacketTime(this, timestamp); +} + +void PusTmMinimal::setInterpretTimestampObject(PacketTimestampInterpreterIF* interpreter) { + if (PusTmMinimal::timestampInterpreter == nullptr) { + PusTmMinimal::timestampInterpreter = interpreter; + } +} + +PacketTimestampInterpreterIF* PusTmMinimal::timestampInterpreter = nullptr; +// TODO: Implement all of this +ReturnValue_t PusTmMinimal::setData(uint8_t* dataPtr, size_t size, void* args) { return 0; } +uint16_t PusTmMinimal::getPacketIdRaw() const { return 0; } +uint16_t PusTmMinimal::getPacketSeqCtrlRaw() const { return 0; } +uint16_t PusTmMinimal::getPacketDataLen() const { return 0; } +uint8_t PusTmMinimal::getPusVersion() const { return 0; } +uint8_t PusTmMinimal::getService() const { return tmData->secHeader.service; } +uint8_t PusTmMinimal::getSubService() const { return tmData->secHeader.subservice; } +uint8_t PusTmMinimal::getScTimeRefStatus() { return 0; } +uint16_t PusTmMinimal::getMessageTypeCounter() { + return (tmData->secHeader.messageTypeH << 8) | tmData->secHeader.messageTypeL; +} +uint16_t PusTmMinimal::getDestId() { return 0; } +void PusTmMinimal::setApid(uint16_t apid) { + /* TODO: Implement. Maybe provide low level function to do this */ +} +size_t PusTmMinimal::getUserDataLen() const { return userDataLen; } + +const uint8_t* PusTmMinimal::getUserData() const { + return reinterpret_cast(&tmData->rest); +} diff --git a/src/fsfw/tmtcpacket/pus/tm/PusTmMinimal.h b/src/fsfw/tmtcpacket/pus/tm/PusTmMinimal.h new file mode 100644 index 00000000..3b2e7600 --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/tm/PusTmMinimal.h @@ -0,0 +1,92 @@ +#ifndef FRAMEWORK_TMTCPACKET_PUS_TMPACKETMINIMAL_H_ +#define FRAMEWORK_TMTCPACKET_PUS_TMPACKETMINIMAL_H_ + +#include "PusTmIF.h" +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" +#include "fsfw/tmtcpacket/pus/RawUserDataReaderIF.h" + +struct timeval; + +class PacketTimestampInterpreterIF; + +namespace mintm { + +// NOTE: Only PUS C compatible! +struct PusTmMinimalSecHeaderPacked { + uint8_t versionAndScTimeRefStatus; + uint8_t service; + uint8_t subservice; + uint8_t messageTypeH; + uint8_t messageTypeL; +}; + +/** + * This struct defines the data structure of a PUS Telecommand Packet when + * accessed via a pointer. + * @ingroup tmtcpackets + */ +struct MinimalPusTm { + ccsds::PrimaryHeader primary; + PusTmMinimalSecHeaderPacked secHeader; + uint8_t rest; +}; + +// Must include a checksum and is therefore at least one larger than the above struct. +static const uint16_t MINIMUM_SIZE = sizeof(MinimalPusTm) + 1; + +} // namespace mintm + +/** + * This is a minimal version of a PUS TmPacket without any variable field, or, + * in other words with Service Type, Subtype and subcounter only. + * This is required for handling TM packets with different APIDs with different + * secondary headers. + */ +class PusTmMinimal : public PusTmIF, public RawUserDataReaderIF, public RedirectableDataPointerIF { + public: + explicit PusTmMinimal(mintm::MinimalPusTm* data); + /** + * This is the default constructor. + * It sets its internal data pointer to the address passed and also + * forwards the data pointer to the parent SpacePacketBase class. + * @param set_address The position where the packet data lies. + */ + explicit PusTmMinimal(uint8_t* data); + /** + * This is the empty default destructor. + */ + ~PusTmMinimal() override; + + void setApid(uint16_t apid); + + ReturnValue_t getPacketTime(timeval* timestamp); + + static void setInterpretTimestampObject(PacketTimestampInterpreterIF* interpreter); + ReturnValue_t setData(uint8_t* dataPtr, size_t size, void* args) override; + [[nodiscard]] uint16_t getPacketIdRaw() const override; + [[nodiscard]] uint16_t getPacketSeqCtrlRaw() const override; + [[nodiscard]] uint16_t getPacketDataLen() const override; + [[nodiscard]] uint8_t getPusVersion() const override; + [[nodiscard]] uint8_t getService() const override; + [[nodiscard]] uint8_t getSubService() const override; + uint8_t getScTimeRefStatus() override; + uint16_t getMessageTypeCounter() override; + uint16_t getDestId() override; + const uint8_t* getUserData() const override; + size_t getUserDataLen() const override; + + protected: + /** + * A pointer to a structure which defines the data structure of + * the packet's data. + * + * To be hardware-safe, all elements are of byte size. + */ + size_t userDataLen = 0; + mintm::MinimalPusTm* tmData; + + static PacketTimestampInterpreterIF* timestampInterpreter; +}; + +#endif /* FRAMEWORK_TMTCPACKET_PUS_TMPACKETMINIMAL_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tm/PusTmReader.cpp b/src/fsfw/tmtcpacket/pus/tm/PusTmReader.cpp new file mode 100644 index 00000000..491eccac --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/tm/PusTmReader.cpp @@ -0,0 +1,91 @@ +#include "PusTmReader.h" + +#include "fsfw/globalfunctions/CRC.h" + +PusTmReader::PusTmReader(TimeReaderIF *timeReader) : timeReader(timeReader) {} + +PusTmReader::PusTmReader(const uint8_t *data, size_t size) { setReadOnlyData(data, size); } + +PusTmReader::PusTmReader(TimeReaderIF *timeReader, const uint8_t *data, size_t size) + : PusTmReader(timeReader) { + setReadOnlyData(data, size); +} + +ReturnValue_t PusTmReader::parseDataWithCrcCheck() { return parseData(true); } + +ReturnValue_t PusTmReader::parseDataWithoutCrcCheck() { return parseData(false); } + +const uint8_t *PusTmReader::getFullData() const { return spReader.getFullData(); } + +ReturnValue_t PusTmReader::setReadOnlyData(const uint8_t *data, size_t size) { + return setData(const_cast(data), size, nullptr); +} + +ReturnValue_t PusTmReader::setData(uint8_t *dataPtr, size_t size, void *args) { + pointers.spHeaderStart = dataPtr; + return spReader.setReadOnlyData(dataPtr, size); +} + +uint16_t PusTmReader::getPacketIdRaw() const { return spReader.getPacketIdRaw(); } +uint16_t PusTmReader::getPacketSeqCtrlRaw() const { return spReader.getPacketSeqCtrlRaw(); } +uint16_t PusTmReader::getPacketDataLen() const { return spReader.getPacketDataLen(); } +uint8_t PusTmReader::getPusVersion() const { return (pointers.secHeaderStart[0] >> 4) & 0b1111; } +uint8_t PusTmReader::getScTimeRefStatus() { return pointers.secHeaderStart[0] & 0b1111; } +uint8_t PusTmReader::getService() const { return pointers.secHeaderStart[1]; } +uint8_t PusTmReader::getSubService() const { return pointers.secHeaderStart[2]; } +const uint8_t *PusTmReader::getUserData() const { return pointers.userDataStart; } +size_t PusTmReader::getUserDataLen() const { return sourceDataLen; } + +uint16_t PusTmReader::getMessageTypeCounter() { + return (pointers.secHeaderStart[3] << 8) | pointers.secHeaderStart[4]; +} + +uint16_t PusTmReader::getDestId() { + return (pointers.secHeaderStart[5] << 8) | pointers.secHeaderStart[6]; +} + +void PusTmReader::setTimeReader(TimeReaderIF *timeReader_) { timeReader = timeReader_; } + +TimeReaderIF *PusTmReader::getTimeReader() { return timeReader; } + +ReturnValue_t PusTmReader::parseData(bool crcCheck) { + // Time reader is required to read the time stamp length at run-time + if (pointers.spHeaderStart == nullptr or spReader.isNull() or timeReader == nullptr) { + return returnvalue::FAILED; + } + ReturnValue_t result = spReader.checkSize(); + if (result != returnvalue::OK) { + return result; + } + size_t currentOffset = SpacePacketReader::getHeaderLen(); + pointers.secHeaderStart = pointers.spHeaderStart + currentOffset; + currentOffset += PusTmIF::MIN_SEC_HEADER_LEN; + size_t minTimestampLen = spReader.getFullPacketLen() - currentOffset; + result = timeReader->readTimeStamp(pointers.spHeaderStart + currentOffset, minTimestampLen); + if (result != returnvalue::OK) { + return result; + } + size_t timestampLen = timeReader->getTimestampSize(); + if (currentOffset + timestampLen > spReader.getBufSize()) { + return SerializeIF::STREAM_TOO_SHORT; + } + currentOffset += timestampLen; + sourceDataLen = spReader.getFullPacketLen() - currentOffset - sizeof(ecss::PusChecksumT); + pointers.userDataStart = nullptr; + if (sourceDataLen > 0) { + pointers.userDataStart = pointers.spHeaderStart + currentOffset; + } + currentOffset += sourceDataLen; + pointers.crcStart = pointers.spHeaderStart + currentOffset; + if (crcCheck) { + uint16_t crc16 = CRC::crc16ccitt(spReader.getFullData(), getFullPacketLen()); + if (crc16 != 0) { + // Checksum failure + return PusIF::INVALID_CRC_16; + } + } + return returnvalue::OK; +} +bool PusTmReader::isNull() const { return spReader.isNull() or pointers.secHeaderStart == nullptr; } + +PusTmReader::operator bool() const { return not isNull(); } diff --git a/src/fsfw/tmtcpacket/pus/tm/PusTmReader.h b/src/fsfw/tmtcpacket/pus/tm/PusTmReader.h new file mode 100644 index 00000000..c12bb4c8 --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/tm/PusTmReader.h @@ -0,0 +1,83 @@ +#ifndef FSFW_TMTCPACKET_PUSTMREADER_H +#define FSFW_TMTCPACKET_PUSTMREADER_H + +#include "fsfw/timemanager/TimeReaderIF.h" +#include "fsfw/tmtcpacket/ReadablePacketIF.h" +#include "fsfw/tmtcpacket/RedirectableDataPointerIF.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" +#include "fsfw/tmtcpacket/pus/RawUserDataReaderIF.h" +#include "fsfw/tmtcpacket/pus/tm/PusTmIF.h" + +/** + * This object can be used to read existing PUS TM packets in raw byte format. + * It is a zero-copy object, so reading a TM packet with will not copy anything. + * + * Please note that a parser function must be called after the constructor. This will also check + * the packet for validity. + * + * There are two parser function, where one does not perform the CRC check. This is useful + * if the CRC calculation will is performed in a separate step. + * This object also requires an explicit time stamp reader to allow flexibility in the used + * timestamp. + */ +class PusTmReader : public PusTmIF, + public RawUserDataReaderIF, + public ReadablePacketIF, + public RedirectableDataPointerIF { + public: + explicit PusTmReader(TimeReaderIF* timeReader); + PusTmReader(const uint8_t* data, size_t size); + PusTmReader(TimeReaderIF* timeReader, const uint8_t* data, size_t size); + + /** + * No CRC check will be performed + * @return + */ + ReturnValue_t parseDataWithoutCrcCheck(); + /** + * Performs a CRC check on the data as well + * @return + * - HasReturnvaluesIF::RETURN_OK: Successfully parsed the packet + * - SerializeIF::STREAM_TOO_SHORT: Stream too short for detected packet size + * - PusIF::INVALID_CRC_16 on invalid CRC + */ + ReturnValue_t parseDataWithCrcCheck(); + [[nodiscard]] const uint8_t* getFullData() const override; + + /** + * Returns @isNull + * @return + */ + explicit operator bool() const; + /** + * No (valid) data was set yet or the parse function was not called yet. + * @return + */ + [[nodiscard]] bool isNull() const; + void setTimeReader(TimeReaderIF* timeReader); + TimeReaderIF* getTimeReader(); + ReturnValue_t setReadOnlyData(const uint8_t* data, size_t size); + [[nodiscard]] uint16_t getPacketIdRaw() const override; + [[nodiscard]] uint16_t getPacketSeqCtrlRaw() const override; + [[nodiscard]] uint16_t getPacketDataLen() const override; + [[nodiscard]] uint8_t getPusVersion() const override; + [[nodiscard]] uint8_t getService() const override; + [[nodiscard]] uint8_t getSubService() const override; + [[nodiscard]] const uint8_t* getUserData() const override; + [[nodiscard]] size_t getUserDataLen() const override; + uint8_t getScTimeRefStatus() override; + uint16_t getMessageTypeCounter() override; + uint16_t getDestId() override; + + protected: + ecss::PusPointers pointers{}; + SpacePacketReader spReader{}; + size_t sourceDataLen = 0; + TimeReaderIF* timeReader{}; + ReturnValue_t setData(uint8_t* dataPtr, size_t size, void* args) override; + ReturnValue_t parseData(bool crcCheck); + + private: +}; + +#endif // FSFW_TMTCPACKET_PUSTMREADER_H diff --git a/src/fsfw/tmtcpacket/pus/tm/PusTmZcWriter.cpp b/src/fsfw/tmtcpacket/pus/tm/PusTmZcWriter.cpp new file mode 100644 index 00000000..6a9f6235 --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/tm/PusTmZcWriter.cpp @@ -0,0 +1,26 @@ +#include "PusTmZcWriter.h" + +#include "fsfw/globalfunctions/CRC.h" + +PusTmZeroCopyWriter::PusTmZeroCopyWriter(TimeReaderIF& timeReader, uint8_t* data, size_t size) + : PusTmReader(&timeReader, data, size) {} + +void PusTmZeroCopyWriter::setSequenceCount(uint16_t seqCount) { + if (isNull()) { + return; + } + auto* spHeader = + reinterpret_cast(const_cast((pointers.spHeaderStart))); + ccsds::setSequenceCount(*spHeader, seqCount); +} + +void PusTmZeroCopyWriter::updateErrorControl() { + if (isNull()) { + return; + } + auto* crcStart = const_cast((pointers.crcStart)); + uint16_t crc16 = + CRC::crc16ccitt(PusTmReader::getFullData(), getFullPacketLen() - sizeof(ecss::PusChecksumT)); + crcStart[0] = (crc16 >> 8) & 0xff; + crcStart[1] = crc16 & 0xff; +} diff --git a/src/fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h b/src/fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h new file mode 100644 index 00000000..36c43f51 --- /dev/null +++ b/src/fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h @@ -0,0 +1,21 @@ +#ifndef FSFW_EXAMPLE_HOSTED_PUSTMZCWRITER_H +#define FSFW_EXAMPLE_HOSTED_PUSTMZCWRITER_H + +#include "PusTmReader.h" + +/** + * This packet allows to update specific fields of a PUS TM packet where it is useful or necessary + * to update them in a second step. Otherwise, it offers the same interface as @PusTmReader. + * + * Right now, this class supports updating the CCSDS Sequence Count and the Error Control. + */ +class PusTmZeroCopyWriter : public PusTmReader { + public: + PusTmZeroCopyWriter(TimeReaderIF& timeReader, uint8_t* data, size_t size); + + void setSequenceCount(uint16_t seqCount); + void updateErrorControl(); + + private: +}; +#endif // FSFW_EXAMPLE_HOSTED_PUSTMZCWRITER_H diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketBase.cpp b/src/fsfw/tmtcpacket/pus/tm/TmPacketBase.cpp deleted file mode 100644 index bc761d0d..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketBase.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "fsfw/tmtcpacket/pus/tm/TmPacketBase.h" - -#include - -#include "fsfw/globalfunctions/CRC.h" -#include "fsfw/globalfunctions/arrayprinter.h" -#include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/timemanager/CCSDSTime.h" - -TimeStamperIF* TmPacketBase::timeStamper = nullptr; -object_id_t TmPacketBase::timeStamperId = objects::NO_OBJECT; - -TmPacketBase::TmPacketBase(uint8_t* setData) : SpacePacketBase(setData) {} - -TmPacketBase::~TmPacketBase() { - // Nothing to do. -} - -uint16_t TmPacketBase::getSourceDataSize() { - return getPacketDataLength() - getDataFieldSize() - CRC_SIZE + 1; -} - -uint16_t TmPacketBase::getErrorControl() { - uint32_t size = getSourceDataSize() + CRC_SIZE; - uint8_t* p_to_buffer = getSourceData(); - return (p_to_buffer[size - 2] << 8) + p_to_buffer[size - 1]; -} - -void TmPacketBase::setErrorControl() { - uint32_t full_size = getFullSize(); - uint16_t crc = CRC::crc16ccitt(getWholeData(), full_size - CRC_SIZE); - uint32_t size = getSourceDataSize(); - getSourceData()[size] = (crc & 0XFF00) >> 8; // CRCH - getSourceData()[size + 1] = (crc)&0X00FF; // CRCL -} - -ReturnValue_t TmPacketBase::getPacketTime(timeval* timestamp) const { - size_t tempSize = 0; - return CCSDSTime::convertFromCcsds(timestamp, getPacketTimeRaw(), &tempSize, getTimestampSize()); -} - -bool TmPacketBase::checkAndSetStamper() { - if (timeStamper == NULL) { - timeStamper = ObjectManager::instance()->get(timeStamperId); - if (timeStamper == NULL) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TmPacketBase::checkAndSetStamper: Stamper not found!" << std::endl; -#else - sif::printWarning("TmPacketBase::checkAndSetStamper: Stamper not found!\n"); -#endif - return false; - } - } - return true; -} - -void TmPacketBase::print() { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::info << "TmPacketBase::print:" << std::endl; -#else - sif::printInfo("TmPacketBase::print:\n"); -#endif - arrayprinter::print(getWholeData(), getFullSize()); -} diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketBase.h b/src/fsfw/tmtcpacket/pus/tm/TmPacketBase.h deleted file mode 100644 index 72f3abd4..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketBase.h +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef TMTCPACKET_PUS_TMPACKETBASE_H_ -#define TMTCPACKET_PUS_TMPACKETBASE_H_ - -#include "fsfw/objectmanager/SystemObjectIF.h" -#include "fsfw/timemanager/Clock.h" -#include "fsfw/timemanager/TimeStamperIF.h" -#include "fsfw/tmtcpacket/SpacePacketBase.h" - -namespace Factory { - -void setStaticFrameworkObjectIds(); - -} - -/** - * This class is the basic data handler for any ECSS PUS Telemetry packet. - * - * In addition to #SpacePacketBase, the class provides methods to handle - * the standardized entries of the PUS TM Packet Data Field Header. - * It does not contain the packet data itself but a pointer to the - * data must be set on instantiation. An invalid pointer may cause - * damage, as no getter method checks data validity. Anyway, a NULL - * check can be performed by making use of the getWholeData method. - * @ingroup tmtcpackets - */ -class TmPacketBase : public SpacePacketBase { - friend void(Factory::setStaticFrameworkObjectIds)(); - - public: - //! Maximum size of a TM Packet in this mission. - //! TODO: Make this dependant on a config variable. - static const uint32_t MISSION_TM_PACKET_MAX_SIZE = 2048; - - /** - * This is the default constructor. - * It sets its internal data pointer to the address passed and also - * forwards the data pointer to the parent SpacePacketBase class. - * @param set_address The position where the packet data lies. - */ - TmPacketBase(uint8_t* setData); - /** - * This is the empty default destructor. - */ - virtual ~TmPacketBase(); - - /** - * This is a getter for the packet's PUS Service ID, which is the second - * byte of the Data Field Header. - * @return The packet's PUS Service ID. - */ - virtual uint8_t getService() = 0; - /** - * This is a getter for the packet's PUS Service Subtype, which is the - * third byte of the Data Field Header. - * @return The packet's PUS Service Subtype. - */ - virtual uint8_t getSubService() = 0; - /** - * This is a getter for a pointer to the packet's Source data. - * - * These are the bytes that follow after the Data Field Header. They form - * the packet's source data. - * @return A pointer to the PUS Source Data. - */ - virtual uint8_t* getSourceData() = 0; - /** - * This method calculates the size of the PUS Source data field. - * - * It takes the information stored in the CCSDS Packet Data Length field - * and subtracts the Data Field Header size and the CRC size. - * @return The size of the PUS Source Data (without Error Control field) - */ - virtual uint16_t getSourceDataSize() = 0; - - /** - * Get size of data field which can differ based on implementation - * @return - */ - virtual uint16_t getDataFieldSize() = 0; - - virtual size_t getPacketMinimumSize() const = 0; - - /** - * Interprets the "time"-field in the secondary header and returns it in - * timeval format. - * @return Converted timestamp of packet. - */ - virtual ReturnValue_t getPacketTime(timeval* timestamp) const; - /** - * Returns a raw pointer to the beginning of the time field. - * @return Raw pointer to time field. - */ - virtual uint8_t* getPacketTimeRaw() const = 0; - - virtual size_t getTimestampSize() const = 0; - - /** - * This is a debugging helper method that prints the whole packet content - * to the screen. - */ - void print(); - /** - * With this method, the Error Control Field is updated to match the - * current content of the packet. This method is not protected because - * a recalculation by the user might be necessary when manipulating fields - * like the sequence count. - */ - void setErrorControl(); - /** - * This getter returns the Error Control Field of the packet. - * - * The field is placed after any possible Source Data. If no - * Source Data is present there's still an Error Control field. It is - * supposed to be a 16bit-CRC. - * @return The PUS Error Control - */ - uint16_t getErrorControl(); - - protected: - /** - * The timeStamper is responsible for adding a timestamp to the packet. - * It is initialized lazy. - */ - static TimeStamperIF* timeStamper; - //! The ID to use when looking for a time stamper. - static object_id_t timeStamperId; - - /** - * Checks if a time stamper is available and tries to set it if not. - * @return Returns false if setting failed. - */ - bool checkAndSetStamper(); -}; - -#endif /* TMTCPACKET_PUS_TMPACKETBASE_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketMinimal.cpp b/src/fsfw/tmtcpacket/pus/tm/TmPacketMinimal.cpp deleted file mode 100644 index 388a4098..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketMinimal.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "fsfw/tmtcpacket/pus/tm/TmPacketMinimal.h" - -#include -#include - -#include "fsfw/tmtcpacket/pus/PacketTimestampInterpreterIF.h" - -TmPacketMinimal::TmPacketMinimal(const uint8_t* set_data) : SpacePacketBase(set_data) { - this->tm_data = (TmPacketMinimalPointer*)set_data; -} - -TmPacketMinimal::~TmPacketMinimal() {} - -uint8_t TmPacketMinimal::getService() { return tm_data->data_field.service_type; } - -uint8_t TmPacketMinimal::getSubService() { return tm_data->data_field.service_subtype; } - -uint8_t TmPacketMinimal::getPacketSubcounter() { return tm_data->data_field.subcounter; } - -ReturnValue_t TmPacketMinimal::getPacketTime(timeval* timestamp) { - if (timestampInterpreter == NULL) { - return HasReturnvaluesIF::RETURN_FAILED; - } - return timestampInterpreter->getPacketTime(this, timestamp); -} - -ReturnValue_t TmPacketMinimal::getPacketTimeRaw(const uint8_t** timePtr, uint32_t* size) { - if (timestampInterpreter == NULL) { - return HasReturnvaluesIF::RETURN_FAILED; - } - return timestampInterpreter->getPacketTimeRaw(this, timePtr, size); -} - -void TmPacketMinimal::setInterpretTimestampObject(PacketTimestampInterpreterIF* interpreter) { - if (TmPacketMinimal::timestampInterpreter == NULL) { - TmPacketMinimal::timestampInterpreter = interpreter; - } -} - -PacketTimestampInterpreterIF* TmPacketMinimal::timestampInterpreter = NULL; diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketMinimal.h b/src/fsfw/tmtcpacket/pus/tm/TmPacketMinimal.h deleted file mode 100644 index dc9c33ae..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketMinimal.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef FRAMEWORK_TMTCPACKET_PUS_TMPACKETMINIMAL_H_ -#define FRAMEWORK_TMTCPACKET_PUS_TMPACKETMINIMAL_H_ - -#include "../../../returnvalues/HasReturnvaluesIF.h" -#include "../../SpacePacketBase.h" - -struct timeval; -class PacketTimestampInterpreterIF; -/** - * This is a minimal version of a PUS TmPacket without any variable field, or, - * in other words with Service Type, Subtype and subcounter only. - * This is required for handling TM packets with different APIDs with different - * secondary headers. - */ -class TmPacketMinimal : public SpacePacketBase { - public: - /** - * This is the default constructor. - * It sets its internal data pointer to the address passed and also - * forwards the data pointer to the parent SpacePacketBase class. - * @param set_address The position where the packet data lies. - */ - TmPacketMinimal(const uint8_t* set_data); - /** - * This is the empty default destructor. - */ - virtual ~TmPacketMinimal(); - /** - * This is a getter for the packet's PUS Service ID, which is the second - * byte of the Data Field Header. - * @return The packet's PUS Service ID. - */ - uint8_t getService(); - /** - * This is a getter for the packet's PUS Service Subtype, which is the - * third byte of the Data Field Header. - * @return The packet's PUS Service Subtype. - */ - uint8_t getSubService(); - /** - * Returns the subcounter. - * @return the subcounter of the Data Field Header. - */ - uint8_t getPacketSubcounter(); - struct PUSTmMinimalHeader { - uint8_t version_type_ack; - uint8_t service_type; - uint8_t service_subtype; - uint8_t subcounter; - }; - - ReturnValue_t getPacketTime(timeval* timestamp); - - ReturnValue_t getPacketTimeRaw(const uint8_t** timePtr, uint32_t* size); - - static void setInterpretTimestampObject(PacketTimestampInterpreterIF* interpreter); - /** - * This struct defines the data structure of a PUS Telecommand Packet when - * accessed via a pointer. - * @ingroup tmtcpackets - */ - struct TmPacketMinimalPointer { - CCSDSPrimaryHeader primary; - PUSTmMinimalHeader data_field; - uint8_t rest; - }; - // Must include a checksum and is therefore at least one larger than the above struct. - static const uint16_t MINIMUM_SIZE = sizeof(TmPacketMinimalPointer) + 1; - - protected: - /** - * A pointer to a structure which defines the data structure of - * the packet's data. - * - * To be hardware-safe, all elements are of byte size. - */ - TmPacketMinimalPointer* tm_data; - - static PacketTimestampInterpreterIF* timestampInterpreter; -}; - -#endif /* FRAMEWORK_TMTCPACKET_PUS_TMPACKETMINIMAL_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketPusA.cpp b/src/fsfw/tmtcpacket/pus/tm/TmPacketPusA.cpp deleted file mode 100644 index e8f71717..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketPusA.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "TmPacketPusA.h" - -#include - -#include "../definitions.h" -#include "TmPacketBase.h" -#include "fsfw/globalfunctions/CRC.h" -#include "fsfw/globalfunctions/arrayprinter.h" -#include "fsfw/objectmanager/ObjectManagerIF.h" -#include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/timemanager/CCSDSTime.h" - -TmPacketPusA::TmPacketPusA(uint8_t* setData) : TmPacketBase(setData) { - tmData = reinterpret_cast(setData); -} - -TmPacketPusA::~TmPacketPusA() { - // Nothing to do. -} - -uint8_t TmPacketPusA::getService() { return tmData->data_field.service_type; } - -uint8_t TmPacketPusA::getSubService() { return tmData->data_field.service_subtype; } - -uint8_t* TmPacketPusA::getSourceData() { return &tmData->data; } - -uint16_t TmPacketPusA::getSourceDataSize() { - return getPacketDataLength() - sizeof(tmData->data_field) - CRC_SIZE + 1; -} - -ReturnValue_t TmPacketPusA::setData(uint8_t* p_Data, size_t maxSize, void* args) { - ReturnValue_t result = SpacePacketBase::setData(p_Data, maxSize); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - tmData = reinterpret_cast(const_cast(p_Data)); - return HasReturnvaluesIF::RETURN_OK; -} - -size_t TmPacketPusA::getPacketMinimumSize() const { return TM_PACKET_MIN_SIZE; } - -uint16_t TmPacketPusA::getDataFieldSize() { return sizeof(PUSTmDataFieldHeaderPusA); } - -uint8_t* TmPacketPusA::getPacketTimeRaw() const { return tmData->data_field.time; } - -void TmPacketPusA::initializeTmPacket(uint16_t apid, uint8_t service, uint8_t subservice, - uint8_t packetSubcounter) { - // Set primary header: - initSpacePacketHeader(false, true, apid); - // Set data Field Header: - // First, set to zero. - memset(&tmData->data_field, 0, sizeof(tmData->data_field)); - - tmData->data_field.version_type_ack = pus::PusVersion::PUS_A_VERSION << 4; - tmData->data_field.service_type = service; - tmData->data_field.service_subtype = subservice; - tmData->data_field.subcounter = packetSubcounter; - // Timestamp packet - if (TmPacketBase::checkAndSetStamper()) { - timeStamper->addTimeStamp(tmData->data_field.time, sizeof(tmData->data_field.time)); - } -} - -void TmPacketPusA::setSourceDataSize(uint16_t size) { - setPacketDataLength(size + sizeof(PUSTmDataFieldHeaderPusA) + CRC_SIZE - 1); -} - -size_t TmPacketPusA::getTimestampSize() const { return sizeof(tmData->data_field.time); } diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketPusA.h b/src/fsfw/tmtcpacket/pus/tm/TmPacketPusA.h deleted file mode 100644 index a84547ff..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketPusA.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef FSFW_TMTCPACKET_PUS_TMPACKETPUSA_H_ -#define FSFW_TMTCPACKET_PUS_TMPACKETPUSA_H_ - -#include "TmPacketBase.h" -#include "fsfw/objectmanager/SystemObjectIF.h" -#include "fsfw/timemanager/Clock.h" -#include "fsfw/timemanager/TimeStamperIF.h" -#include "fsfw/tmtcpacket/SpacePacketBase.h" - -namespace Factory { -void setStaticFrameworkObjectIds(); -} - -/** - * This struct defines a byte-wise structured PUS TM Data Field Header. - * Any optional fields in the header must be added or removed here. - * Currently, no Destination field is present, but an eigth-byte representation - * for a time tag. - * @ingroup tmtcpackets - */ -struct PUSTmDataFieldHeaderPusA { - uint8_t version_type_ack; - uint8_t service_type; - uint8_t service_subtype; - uint8_t subcounter; - // uint8_t destination; - uint8_t time[TimeStamperIF::MISSION_TIMESTAMP_SIZE]; -}; - -/** - * This struct defines the data structure of a PUS Telecommand Packet when - * accessed via a pointer. - * @ingroup tmtcpackets - */ -struct TmPacketPointerPusA { - CCSDSPrimaryHeader primary; - PUSTmDataFieldHeaderPusA data_field; - uint8_t data; -}; - -/** - * PUS A packet implementation - * @ingroup tmtcpackets - */ -class TmPacketPusA : public TmPacketBase { - friend void(Factory::setStaticFrameworkObjectIds)(); - - public: - /** - * This constant defines the minimum size of a valid PUS Telemetry Packet. - */ - static const uint32_t TM_PACKET_MIN_SIZE = - (sizeof(CCSDSPrimaryHeader) + sizeof(PUSTmDataFieldHeaderPusA) + 2); - //! Maximum size of a TM Packet in this mission. - static const uint32_t MISSION_TM_PACKET_MAX_SIZE = fsfwconfig::FSFW_MAX_TM_PACKET_SIZE; - - /** - * This is the default constructor. - * It sets its internal data pointer to the address passed and also - * forwards the data pointer to the parent SpacePacketBase class. - * @param set_address The position where the packet data lies. - */ - TmPacketPusA(uint8_t* setData); - /** - * This is the empty default destructor. - */ - virtual ~TmPacketPusA(); - - /* TmPacketBase implementations */ - uint8_t getService() override; - uint8_t getSubService() override; - uint8_t* getSourceData() override; - uint16_t getSourceDataSize() override; - uint16_t getDataFieldSize() override; - - /** - * Returns a raw pointer to the beginning of the time field. - * @return Raw pointer to time field. - */ - uint8_t* getPacketTimeRaw() const override; - size_t getTimestampSize() const override; - - size_t getPacketMinimumSize() const override; - - protected: - /** - * A pointer to a structure which defines the data structure of - * the packet's data. - * - * To be hardware-safe, all elements are of byte size. - */ - TmPacketPointerPusA* tmData; - - /** - * Initializes the Tm Packet header. - * Does set the timestamp (to now), but not the error control field. - * @param apid APID used. - * @param service PUS Service - * @param subservice PUS Subservice - * @param packetSubcounter Additional subcounter used. - */ - void initializeTmPacket(uint16_t apid, uint8_t service, uint8_t subservice, - uint8_t packetSubcounter); - - /** - * With this method, the packet data pointer can be redirected to another - * location. - * - * This call overwrites the parent's setData method to set both its - * @c tc_data pointer and the parent's @c data pointer. - * - * @param p_data A pointer to another PUS Telemetry Packet. - */ - ReturnValue_t setData(uint8_t* pData, size_t maxSize, void* args = nullptr) override; - - /** - * In case data was filled manually (almost never the case). - * @param size Size of source data (without CRC and data filed header!). - */ - void setSourceDataSize(uint16_t size); - - /** - * Checks if a time stamper is available and tries to set it if not. - * @return Returns false if setting failed. - */ - bool checkAndSetStamper(); -}; - -#endif /* FSFW_TMTCPACKET_PUS_TMPACKETPUSA_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketPusC.cpp b/src/fsfw/tmtcpacket/pus/tm/TmPacketPusC.cpp deleted file mode 100644 index ab690414..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketPusC.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "TmPacketPusC.h" - -#include - -#include "../definitions.h" -#include "TmPacketBase.h" -#include "fsfw/globalfunctions/CRC.h" -#include "fsfw/globalfunctions/arrayprinter.h" -#include "fsfw/objectmanager/ObjectManagerIF.h" -#include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/timemanager/CCSDSTime.h" - -TmPacketPusC::TmPacketPusC(uint8_t* setData) : TmPacketBase(setData) { - tmData = reinterpret_cast(setData); -} - -TmPacketPusC::~TmPacketPusC() { - // Nothing to do. -} - -uint8_t TmPacketPusC::getService() { return tmData->dataField.serviceType; } - -uint8_t TmPacketPusC::getSubService() { return tmData->dataField.serviceSubtype; } - -uint8_t* TmPacketPusC::getSourceData() { return &tmData->data; } - -uint16_t TmPacketPusC::getSourceDataSize() { - return getPacketDataLength() - sizeof(tmData->dataField) - CRC_SIZE + 1; -} - -ReturnValue_t TmPacketPusC::setData(uint8_t* p_Data, size_t maxSize, void* args) { - ReturnValue_t result = SpacePacketBase::setData(p_Data, maxSize); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - if (maxSize < sizeof(TmPacketPointerPusC)) { - return HasReturnvaluesIF::RETURN_OK; - } - tmData = reinterpret_cast(const_cast(p_Data)); - return HasReturnvaluesIF::RETURN_OK; -} - -size_t TmPacketPusC::getPacketMinimumSize() const { return TM_PACKET_MIN_SIZE; } - -uint16_t TmPacketPusC::getDataFieldSize() { return sizeof(PUSTmDataFieldHeaderPusC); } - -uint8_t* TmPacketPusC::getPacketTimeRaw() const { return tmData->dataField.time; } - -ReturnValue_t TmPacketPusC::initializeTmPacket(uint16_t apid, uint8_t service, uint8_t subservice, - uint16_t packetSubcounter, uint16_t destinationId, - uint8_t timeRefField) { - // Set primary header: - ReturnValue_t result = initSpacePacketHeader(false, true, apid); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - // Set data Field Header: - // First, set to zero. - memset(&tmData->dataField, 0, sizeof(tmData->dataField)); - - /* Only account for last 4 bytes for time reference field */ - timeRefField &= 0b1111; - tmData->dataField.versionTimeReferenceField = - (pus::PusVersion::PUS_C_VERSION << 4) | timeRefField; - tmData->dataField.serviceType = service; - tmData->dataField.serviceSubtype = subservice; - tmData->dataField.subcounterMsb = packetSubcounter << 8 & 0xff; - tmData->dataField.subcounterLsb = packetSubcounter & 0xff; - tmData->dataField.destinationIdMsb = destinationId << 8 & 0xff; - tmData->dataField.destinationIdLsb = destinationId & 0xff; - // Timestamp packet - if (TmPacketBase::checkAndSetStamper()) { - timeStamper->addTimeStamp(tmData->dataField.time, sizeof(tmData->dataField.time)); - } - return HasReturnvaluesIF::RETURN_OK; -} - -void TmPacketPusC::setSourceDataSize(uint16_t size) { - setPacketDataLength(size + sizeof(PUSTmDataFieldHeaderPusC) + CRC_SIZE - 1); -} - -size_t TmPacketPusC::getTimestampSize() const { return sizeof(tmData->dataField.time); } diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketPusC.h b/src/fsfw/tmtcpacket/pus/tm/TmPacketPusC.h deleted file mode 100644 index bbd69693..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketPusC.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef FSFW_TMTCPACKET_PUS_TMPACKETPUSC_H_ -#define FSFW_TMTCPACKET_PUS_TMPACKETPUSC_H_ - -#include "TmPacketBase.h" -#include "fsfw/objectmanager/SystemObjectIF.h" -#include "fsfw/timemanager/Clock.h" -#include "fsfw/timemanager/TimeStamperIF.h" -#include "fsfw/tmtcpacket/SpacePacketBase.h" - -namespace Factory { -void setStaticFrameworkObjectIds(); -} - -/** - * This struct defines a byte-wise structured PUS TM Data Field Header. - * Any optional fields in the header must be added or removed here. - * Currently, no Destination field is present, but an eigth-byte representation - * for a time tag. - * @ingroup tmtcpackets - */ -struct PUSTmDataFieldHeaderPusC { - uint8_t versionTimeReferenceField; - uint8_t serviceType; - uint8_t serviceSubtype; - uint8_t subcounterMsb; - uint8_t subcounterLsb; - uint8_t destinationIdMsb; - uint8_t destinationIdLsb; - uint8_t time[TimeStamperIF::MISSION_TIMESTAMP_SIZE]; -}; - -/** - * This struct defines the data structure of a PUS Telecommand Packet when - * accessed via a pointer. - * @ingroup tmtcpackets - */ -struct TmPacketPointerPusC { - CCSDSPrimaryHeader primary; - PUSTmDataFieldHeaderPusC dataField; - uint8_t data; -}; - -/** - * PUS A packet implementation - * @ingroup tmtcpackets - */ -class TmPacketPusC : public TmPacketBase { - friend void(Factory::setStaticFrameworkObjectIds)(); - - public: - /** - * This constant defines the minimum size of a valid PUS Telemetry Packet. - */ - static const uint32_t TM_PACKET_MIN_SIZE = - (sizeof(CCSDSPrimaryHeader) + sizeof(PUSTmDataFieldHeaderPusC) + 2); - //! Maximum size of a TM Packet in this mission. - static const uint32_t MISSION_TM_PACKET_MAX_SIZE = fsfwconfig::FSFW_MAX_TM_PACKET_SIZE; - - /** - * This is the default constructor. - * It sets its internal data pointer to the address passed and also - * forwards the data pointer to the parent SpacePacketBase class. - * @param set_address The position where the packet data lies. - */ - TmPacketPusC(uint8_t* setData); - /** - * This is the empty default destructor. - */ - virtual ~TmPacketPusC(); - - /* TmPacketBase implementations */ - uint8_t getService() override; - uint8_t getSubService() override; - uint8_t* getSourceData() override; - uint16_t getSourceDataSize() override; - uint16_t getDataFieldSize() override; - - /** - * Returns a raw pointer to the beginning of the time field. - * @return Raw pointer to time field. - */ - uint8_t* getPacketTimeRaw() const override; - size_t getTimestampSize() const override; - - size_t getPacketMinimumSize() const override; - - protected: - /** - * A pointer to a structure which defines the data structure of - * the packet's data. - * - * To be hardware-safe, all elements are of byte size. - */ - TmPacketPointerPusC* tmData; - - /** - * Initializes the Tm Packet header. - * Does set the timestamp (to now), but not the error control field. - * @param apid APID used. - * @param service PUS Service - * @param subservice PUS Subservice - * @param packetSubcounter Additional subcounter used. - */ - ReturnValue_t initializeTmPacket(uint16_t apid, uint8_t service, uint8_t subservice, - uint16_t packetSubcounter, uint16_t destinationId = 0, - uint8_t timeRefField = 0); - - /** - * With this method, the packet data pointer can be redirected to another - * location. - * - * This call overwrites the parent's setData method to set both its - * @c tc_data pointer and the parent's @c data pointer. - * - * @param pData A pointer to another PUS Telemetry Packet. - */ - ReturnValue_t setData(uint8_t* pData, size_t maxSize, void* args = nullptr) override; - - /** - * In case data was filled manually (almost never the case). - * @param size Size of source data (without CRC and data filed header!). - */ - void setSourceDataSize(uint16_t size); -}; - -#endif /* FSFW_TMTCPACKET_PUS_TMPACKETPUSC_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketStored.h b/src/fsfw/tmtcpacket/pus/tm/TmPacketStored.h deleted file mode 100644 index de10655f..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketStored.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef FSFW_TMTCPACKET_PUS_TMPACKETSTORED_H_ -#define FSFW_TMTCPACKET_PUS_TMPACKETSTORED_H_ - -#include - -#if FSFW_USE_PUS_C_TELEMETRY == 1 -#include "TmPacketStoredPusC.h" -#else -#include "TmPacketStoredPusA.h" -#endif - -#endif /* FSFW_TMTCPACKET_PUS_TMPACKETSTORED_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredBase.cpp b/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredBase.cpp deleted file mode 100644 index 4d37bf46..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredBase.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include "fsfw/tmtcpacket/pus/tm/TmPacketStoredBase.h" - -#include - -#include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tmtcservices/TmTcMessage.h" - -StorageManagerIF *TmPacketStoredBase::store = nullptr; -InternalErrorReporterIF *TmPacketStoredBase::internalErrorReporter = nullptr; - -TmPacketStoredBase::TmPacketStoredBase(store_address_t setAddress) : storeAddress(setAddress) { - setStoreAddress(storeAddress); -} - -TmPacketStoredBase::TmPacketStoredBase() {} - -TmPacketStoredBase::~TmPacketStoredBase() {} - -store_address_t TmPacketStoredBase::getStoreAddress() { return storeAddress; } - -void TmPacketStoredBase::deletePacket() { - store->deleteData(storeAddress); - storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - setData(nullptr, -1); -} - -void TmPacketStoredBase::setStoreAddress(store_address_t setAddress) { - storeAddress = setAddress; - const uint8_t *tempData = nullptr; - size_t tempSize; - if (not checkAndSetStore()) { - return; - } - ReturnValue_t status = store->getData(storeAddress, &tempData, &tempSize); - if (status == StorageManagerIF::RETURN_OK) { - setData(const_cast(tempData), tempSize); - } else { - setData(nullptr, -1); - storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - } -} - -bool TmPacketStoredBase::checkAndSetStore() { - if (store == nullptr) { - store = ObjectManager::instance()->get(objects::TM_STORE); - if (store == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TmPacketStored::TmPacketStored: TM Store not found!" << std::endl; -#endif - return false; - } - } - return true; -} - -ReturnValue_t TmPacketStoredBase::sendPacket(MessageQueueId_t destination, - MessageQueueId_t sentFrom, bool doErrorReporting) { - if (getAllTmData() == nullptr) { - // SHOULDDO: More decent code. - return HasReturnvaluesIF::RETURN_FAILED; - } - TmTcMessage tmMessage(getStoreAddress()); - ReturnValue_t result = MessageQueueSenderIF::sendMessage(destination, &tmMessage, sentFrom); - if (result != HasReturnvaluesIF::RETURN_OK) { - deletePacket(); - if (doErrorReporting) { - checkAndReportLostTm(); - } - return result; - } - // SHOULDDO: In many cases, some counter is incremented for successfully sent packets. The check - // is often not done, but just incremented. - return HasReturnvaluesIF::RETURN_OK; -} - -void TmPacketStoredBase::checkAndReportLostTm() { - if (internalErrorReporter == nullptr) { - internalErrorReporter = - ObjectManager::instance()->get(objects::INTERNAL_ERROR_REPORTER); - } - if (internalErrorReporter != nullptr) { - internalErrorReporter->lostTm(); - } -} - -void TmPacketStoredBase::handleStoreFailure(const char *const packetType, ReturnValue_t result, - size_t sizeToReserve) { - checkAndReportLostTm(); -#if FSFW_VERBOSE_LEVEL >= 1 - switch (result) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - case (StorageManagerIF::DATA_STORAGE_FULL): { - sif::warning << "TmPacketStoredPus" << packetType << ": " - << "Store full for packet with size" << sizeToReserve << std::endl; - break; - } - case (StorageManagerIF::DATA_TOO_LARGE): { - sif::warning << "TmPacketStoredPus" << packetType << ": Data with size " << sizeToReserve - << " too large" << std::endl; - break; - } -#else - case (StorageManagerIF::DATA_STORAGE_FULL): { - sif::printWarning( - "TmPacketStoredPus%s: Store full for packet with " - "size %d\n", - packetType, sizeToReserve); - break; - } - case (StorageManagerIF::DATA_TOO_LARGE): { - sif::printWarning( - "TmPacketStoredPus%s: Data with size " - "%d too large\n", - packetType, sizeToReserve); - break; - } -#endif - } -#endif -} diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredBase.h b/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredBase.h deleted file mode 100644 index 1732f000..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredBase.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef FSFW_TMTCPACKET_PUS_TMPACKETSTOREDBASE_H_ -#define FSFW_TMTCPACKET_PUS_TMPACKETSTOREDBASE_H_ - -#include "TmPacketBase.h" -#include "TmPacketPusA.h" -#include "TmPacketStoredBase.h" -#include "fsfw/FSFW.h" -#include "fsfw/internalerror/InternalErrorReporterIF.h" -#include "fsfw/ipc/MessageQueueSenderIF.h" -#include "fsfw/serialize/SerializeIF.h" -#include "fsfw/storagemanager/StorageManagerIF.h" - -/** - * This class generates a ECSS PUS Telemetry packet within a given - * intermediate storage. - * As most packets are passed between tasks with the help of a storage - * anyway, it seems logical to create a Packet-In-Storage access class - * which saves the user almost all storage handling operation. - * Packets can both be newly created with the class and be "linked" to - * packets in a store with the help of a storeAddress. - * @ingroup tmtcpackets - */ -class TmPacketStoredBase : virtual public RedirectableDataPointerIF { - public: - /** - * This is a default constructor which does not set the data pointer. - * However, it does try to set the packet store. - */ - TmPacketStoredBase(store_address_t setAddress); - TmPacketStoredBase(); - - virtual ~TmPacketStoredBase(); - - virtual uint8_t* getAllTmData() = 0; - - /** - * This is a getter for the current store address of the packet. - * @return The current store address. The (raw) value is - * @c StorageManagerIF::INVALID_ADDRESS if - * the packet is not linked. - */ - store_address_t getStoreAddress(); - /** - * With this call, the packet is deleted. - * It removes itself from the store and sets its data pointer to NULL. - */ - void deletePacket(); - /** - * With this call, a packet can be linked to another store. This is useful - * if the packet is a class member and used for more than one packet. - * @param setAddress The new packet id to link to. - */ - void setStoreAddress(store_address_t setAddress); - - ReturnValue_t sendPacket(MessageQueueId_t destination, MessageQueueId_t sentFrom, - bool doErrorReporting = true); - - protected: - /** - * This is a pointer to the store all instances of the class use. - * If the store is not yet set (i.e. @c store is NULL), every constructor - * call tries to set it and throws an error message in case of failures. - * The default store is objects::TM_STORE. - */ - static StorageManagerIF* store; - - static InternalErrorReporterIF* internalErrorReporter; - - /** - * The address where the packet data of the object instance is stored. - */ - store_address_t storeAddress; - /** - * A helper method to check if a store is assigned to the class. - * If not, the method tries to retrieve the store from the global - * ObjectManager. - * @return @li @c true if the store is linked or could be created. - * @li @c false otherwise. - */ - bool checkAndSetStore(); - - void checkAndReportLostTm(); - - void handleStoreFailure(const char* const packetType, ReturnValue_t result, size_t sizeToReserve); -}; - -#endif /* FSFW_TMTCPACKET_PUS_TMPACKETSTOREDBASE_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredPusA.cpp b/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredPusA.cpp deleted file mode 100644 index 37ba63f3..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredPusA.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "fsfw/tmtcpacket/pus/tm/TmPacketStoredPusA.h" - -#include - -#include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tmtcservices/TmTcMessage.h" - -TmPacketStoredPusA::TmPacketStoredPusA(store_address_t setAddress) - : TmPacketStoredBase(setAddress), TmPacketPusA(nullptr) {} - -TmPacketStoredPusA::TmPacketStoredPusA(uint16_t apid, uint8_t service, uint8_t subservice, - uint8_t packetSubcounter, const uint8_t *data, uint32_t size, - const uint8_t *headerData, uint32_t headerSize) - : TmPacketPusA(nullptr) { - storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - if (not TmPacketStoredBase::checkAndSetStore()) { - return; - } - uint8_t *pData = nullptr; - size_t sizeToReserve = getPacketMinimumSize() + size + headerSize; - ReturnValue_t returnValue = store->getFreeElement(&storeAddress, sizeToReserve, &pData); - - if (returnValue != store->RETURN_OK) { - handleStoreFailure("A", returnValue, sizeToReserve); - return; - } - setData(pData, sizeToReserve); - initializeTmPacket(apid, service, subservice, packetSubcounter); - memcpy(getSourceData(), headerData, headerSize); - memcpy(getSourceData() + headerSize, data, size); - setPacketDataLength(size + headerSize + sizeof(PUSTmDataFieldHeaderPusA) + CRC_SIZE - 1); -} - -TmPacketStoredPusA::TmPacketStoredPusA(uint16_t apid, uint8_t service, uint8_t subservice, - uint8_t packetSubcounter, SerializeIF *content, - SerializeIF *header) - : TmPacketPusA(nullptr) { - storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - if (not TmPacketStoredBase::checkAndSetStore()) { - return; - } - size_t sourceDataSize = 0; - if (content != nullptr) { - sourceDataSize += content->getSerializedSize(); - } - if (header != nullptr) { - sourceDataSize += header->getSerializedSize(); - } - uint8_t *pData = nullptr; - size_t sizeToReserve = getPacketMinimumSize() + sourceDataSize; - ReturnValue_t returnValue = store->getFreeElement(&storeAddress, sizeToReserve, &pData); - if (returnValue != store->RETURN_OK) { - handleStoreFailure("A", returnValue, sizeToReserve); - return; - } - setData(pData, sizeToReserve); - initializeTmPacket(apid, service, subservice, packetSubcounter); - uint8_t *putDataHere = getSourceData(); - size_t size = 0; - if (header != nullptr) { - header->serialize(&putDataHere, &size, sourceDataSize, SerializeIF::Endianness::BIG); - } - if (content != nullptr) { - content->serialize(&putDataHere, &size, sourceDataSize, SerializeIF::Endianness::BIG); - } - setPacketDataLength(sourceDataSize + sizeof(PUSTmDataFieldHeaderPusA) + CRC_SIZE - 1); -} - -uint8_t *TmPacketStoredPusA::getAllTmData() { return getWholeData(); } - -ReturnValue_t TmPacketStoredPusA::setData(uint8_t *newPointer, size_t maxSize, void *args) { - return TmPacketPusA::setData(newPointer, maxSize); -} diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredPusA.h b/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredPusA.h deleted file mode 100644 index f2db99e9..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredPusA.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef FSFW_TMTCPACKET_PUS_TMPACKETSTORED_PUSA_H_ -#define FSFW_TMTCPACKET_PUS_TMPACKETSTORED_PUSA_H_ - -#include - -#include "TmPacketPusA.h" -#include "TmPacketStoredBase.h" - -/** - * This class generates a ECSS PUS A Telemetry packet within a given - * intermediate storage. - * As most packets are passed between tasks with the help of a storage - * anyway, it seems logical to create a Packet-In-Storage access class - * which saves the user almost all storage handling operation. - * Packets can both be newly created with the class and be "linked" to - * packets in a store with the help of a storeAddress. - * @ingroup tmtcpackets - */ -class TmPacketStoredPusA : public TmPacketStoredBase, public TmPacketPusA { - public: - /** - * This is a default constructor which does not set the data pointer. - * However, it does try to set the packet store. - */ - TmPacketStoredPusA(store_address_t setAddress); - /** - * With this constructor, new space is allocated in the packet store and - * a new PUS Telemetry Packet is created there. - * Packet Application Data passed in data is copied into the packet. - * The Application data is passed in two parts, first a header, then a - * data field. This allows building a Telemetry Packet from two separate - * data sources. - * @param apid Sets the packet's APID field. - * @param service Sets the packet's Service ID field. - * This specifies the source service. - * @param subservice Sets the packet's Service Subtype field. - * This specifies the source sub-service. - * @param packet_counter Sets the Packet counter field of this packet - * @param data The payload data to be copied to the - * Application Data Field - * @param size The amount of data to be copied. - * @param headerData The header Data of the Application field, - * will be copied in front of data - * @param headerSize The size of the headerDataF - */ - TmPacketStoredPusA(uint16_t apid, uint8_t service, uint8_t subservice, uint8_t packet_counter = 0, - const uint8_t* data = nullptr, uint32_t size = 0, - const uint8_t* headerData = nullptr, uint32_t headerSize = 0); - /** - * Another ctor to directly pass structured content and header data to the - * packet to avoid additional buffers. - */ - TmPacketStoredPusA(uint16_t apid, uint8_t service, uint8_t subservice, uint8_t packet_counter, - SerializeIF* content, SerializeIF* header = nullptr); - - uint8_t* getAllTmData() override; - - private: - /** - * Implementation required by base class - * @param newPointer - * @param maxSize - * @param args - * @return - */ - ReturnValue_t setData(uint8_t* newPointer, size_t maxSize, void* args = nullptr) override; -}; - -#endif /* FSFW_TMTCPACKET_PUS_TMPACKETSTORED_PUSA_H_ */ diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredPusC.cpp b/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredPusC.cpp deleted file mode 100644 index 9c170aa3..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredPusC.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "fsfw/tmtcpacket/pus/tm/TmPacketStoredPusC.h" - -#include - -#include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tmtcservices/TmTcMessage.h" - -TmPacketStoredPusC::TmPacketStoredPusC(store_address_t setAddress) - : TmPacketStoredBase(setAddress), TmPacketPusC(nullptr) {} - -TmPacketStoredPusC::TmPacketStoredPusC(uint16_t apid, uint8_t service, uint8_t subservice, - uint16_t packetSubcounter, const uint8_t *data, - uint32_t size, const uint8_t *headerData, - uint32_t headerSize, uint16_t destinationId, - uint8_t timeRefField) - : TmPacketPusC(nullptr) { - storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - if (not TmPacketStoredBase::checkAndSetStore()) { - return; - } - uint8_t *pData = nullptr; - size_t sizeToReserve = getPacketMinimumSize() + size + headerSize; - ReturnValue_t returnValue = store->getFreeElement(&storeAddress, sizeToReserve, &pData); - - if (returnValue != store->RETURN_OK) { - handleStoreFailure("C", returnValue, sizeToReserve); - return; - } - setData(pData, sizeToReserve); - initializeTmPacket(apid, service, subservice, packetSubcounter, destinationId, timeRefField); - memcpy(getSourceData(), headerData, headerSize); - memcpy(getSourceData() + headerSize, data, size); - setPacketDataLength(size + headerSize + sizeof(PUSTmDataFieldHeaderPusC) + CRC_SIZE - 1); -} - -TmPacketStoredPusC::TmPacketStoredPusC(uint16_t apid, uint8_t service, uint8_t subservice, - uint16_t packetSubcounter, SerializeIF *content, - SerializeIF *header, uint16_t destinationId, - uint8_t timeRefField) - : TmPacketPusC(nullptr) { - storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - if (not TmPacketStoredBase::checkAndSetStore()) { - return; - } - size_t sourceDataSize = 0; - if (content != nullptr) { - sourceDataSize += content->getSerializedSize(); - } - if (header != nullptr) { - sourceDataSize += header->getSerializedSize(); - } - uint8_t *pData = nullptr; - size_t sizeToReserve = getPacketMinimumSize() + sourceDataSize; - ReturnValue_t returnValue = store->getFreeElement(&storeAddress, sizeToReserve, &pData); - if (returnValue != store->RETURN_OK) { - handleStoreFailure("C", returnValue, sizeToReserve); - return; - } - TmPacketPusC::setData(pData, sizeToReserve); - initializeTmPacket(apid, service, subservice, packetSubcounter, destinationId, timeRefField); - uint8_t *putDataHere = getSourceData(); - size_t size = 0; - if (header != nullptr) { - header->serialize(&putDataHere, &size, sourceDataSize, SerializeIF::Endianness::BIG); - } - if (content != nullptr) { - content->serialize(&putDataHere, &size, sourceDataSize, SerializeIF::Endianness::BIG); - } - setPacketDataLength(sourceDataSize + sizeof(PUSTmDataFieldHeaderPusC) + CRC_SIZE - 1); -} - -uint8_t *TmPacketStoredPusC::getAllTmData() { return getWholeData(); } - -ReturnValue_t TmPacketStoredPusC::setData(uint8_t *newPointer, size_t maxSize, void *args) { - return TmPacketPusC::setData(newPointer, maxSize); -} diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredPusC.h b/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredPusC.h deleted file mode 100644 index ef84e238..00000000 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredPusC.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef FSFW_TMTCPACKET_PUS_TMPACKETSTOREDPUSC_H_ -#define FSFW_TMTCPACKET_PUS_TMPACKETSTOREDPUSC_H_ - -#include "TmPacketPusC.h" -#include "TmPacketStoredBase.h" - -/** - * This class generates a ECSS PUS C Telemetry packet within a given - * intermediate storage. - * As most packets are passed between tasks with the help of a storage - * anyway, it seems logical to create a Packet-In-Storage access class - * which saves the user almost all storage handling operation. - * Packets can both be newly created with the class and be "linked" to - * packets in a store with the help of a storeAddress. - * @ingroup tmtcpackets - */ -class TmPacketStoredPusC : public TmPacketStoredBase, public TmPacketPusC { - public: - /** - * This is a default constructor which does not set the data pointer. - * However, it does try to set the packet store. - */ - TmPacketStoredPusC(store_address_t setAddress); - /** - * With this constructor, new space is allocated in the packet store and - * a new PUS Telemetry Packet is created there. - * Packet Application Data passed in data is copied into the packet. - * The Application data is passed in two parts, first a header, then a - * data field. This allows building a Telemetry Packet from two separate - * data sources. - * @param apid Sets the packet's APID field. - * @param service Sets the packet's Service ID field. - * This specifies the source service. - * @param subservice Sets the packet's Service Subtype field. - * This specifies the source sub-service. - * @param packet_counter Sets the Packet counter field of this packet - * @param data The payload data to be copied to the - * Application Data Field - * @param size The amount of data to be copied. - * @param headerData The header Data of the Application field, - * will be copied in front of data - * @param headerSize The size of the headerDataF - * @param destinationId Destination ID containing the application process ID as specified - * by PUS C - * @param timeRefField 4 bit time reference field as specified by PUS C - */ - TmPacketStoredPusC(uint16_t apid, uint8_t service, uint8_t subservice, uint16_t packetCounter = 0, - const uint8_t* data = nullptr, uint32_t size = 0, - const uint8_t* headerData = nullptr, uint32_t headerSize = 0, - uint16_t destinationId = 0, uint8_t timeRefField = 0); - /** - * Another ctor to directly pass structured content and header data to the - * packet to avoid additional buffers. - */ - TmPacketStoredPusC(uint16_t apid, uint8_t service, uint8_t subservice, uint16_t packetCounter, - SerializeIF* content, SerializeIF* header = nullptr, - uint16_t destinationId = 0, uint8_t timeRefField = 0); - - uint8_t* getAllTmData() override; - - private: - /** - * Implementation required by base class - * @param newPointer - * @param maxSize - * @param args - * @return - */ - ReturnValue_t setData(uint8_t* newPointer, size_t maxSize, void* args = nullptr) override; -}; - -#endif /* FSFW_TMTCPACKET_PUS_TMPACKETSTOREDPUSC_H_ */ diff --git a/src/fsfw/tmtcservices/AcceptsTelecommandsIF.h b/src/fsfw/tmtcservices/AcceptsTelecommandsIF.h index 4186f4df..6c214b0f 100644 --- a/src/fsfw/tmtcservices/AcceptsTelecommandsIF.h +++ b/src/fsfw/tmtcservices/AcceptsTelecommandsIF.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_TMTCSERVICES_ACCEPTSTELECOMMANDSIF_H_ #define FRAMEWORK_TMTCSERVICES_ACCEPTSTELECOMMANDSIF_H_ -#include "../ipc/MessageQueueSenderIF.h" +#include "fsfw/ipc/MessageQueueSenderIF.h" /** * @brief This interface is implemented by classes that are sinks for @@ -20,21 +20,23 @@ class AcceptsTelecommandsIF { /** * @brief The virtual destructor as it is mandatory for C++ interfaces. */ - virtual ~AcceptsTelecommandsIF() {} + virtual ~AcceptsTelecommandsIF() = default; + [[nodiscard]] virtual const char* getName() const = 0; + /** - * @brief Getter for the service id. - * @details Any receiving service (at least any PUS service) shall have a - * service ID. If the receiver can handle Telecommands, but for - * some reason has no service id, it shall return 0. - * @return The service ID or 0. + * @brief Getter for a generic identifier ID. + * @details Any receiving service (at least any PUS service) shall have an identifier. For + * example, this could be the APID for a receiver expecting generic PUS packets, or a PUS + * service for a component expecting specific PUS service packets. + * @return The identifier. */ - virtual uint16_t getIdentifier() = 0; + [[nodiscard]] virtual uint32_t getIdentifier() const = 0; /** * @brief This method returns the message queue id of the telecommand * receiving message queue. * @return The telecommand reception message queue id. */ - virtual MessageQueueId_t getRequestQueue() = 0; + [[nodiscard]] virtual MessageQueueId_t getRequestQueue() const = 0; }; #endif /* FRAMEWORK_TMTCSERVICES_ACCEPTSTELECOMMANDSIF_H_ */ diff --git a/src/fsfw/tmtcservices/AcceptsTelemetryIF.h b/src/fsfw/tmtcservices/AcceptsTelemetryIF.h index 0e715130..5b421cf9 100644 --- a/src/fsfw/tmtcservices/AcceptsTelemetryIF.h +++ b/src/fsfw/tmtcservices/AcceptsTelemetryIF.h @@ -1,7 +1,7 @@ #ifndef FSFW_TMTCSERVICES_ACCEPTSTELEMETRYIF_H_ #define FSFW_TMTCSERVICES_ACCEPTSTELEMETRYIF_H_ -#include "../ipc/MessageQueueSenderIF.h" +#include "fsfw/ipc/MessageQueueSenderIF.h" /** * @brief This interface is implemented by classes that are sinks for * Telemetry. @@ -13,13 +13,19 @@ class AcceptsTelemetryIF { /** * @brief The virtual destructor as it is mandatory for C++ interfaces. */ - virtual ~AcceptsTelemetryIF() {} + virtual ~AcceptsTelemetryIF() = default; + + [[nodiscard]] virtual const char* getName() const = 0; /** * @brief This method returns the message queue id of the telemetry * receiving message queue. * @return The telemetry reception message queue id. */ - virtual MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) = 0; + [[nodiscard]] virtual MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const = 0; + + [[nodiscard]] virtual MessageQueueId_t getReportReceptionQueue() const { + return getReportReceptionQueue(0); + } }; #endif /* FSFW_TMTCSERVICES_ACCEPTSTELEMETRYIF_H_ */ diff --git a/src/fsfw/tmtcservices/AcceptsVerifyMessageIF.h b/src/fsfw/tmtcservices/AcceptsVerifyMessageIF.h index 7e58187b..daf67080 100644 --- a/src/fsfw/tmtcservices/AcceptsVerifyMessageIF.h +++ b/src/fsfw/tmtcservices/AcceptsVerifyMessageIF.h @@ -1,11 +1,11 @@ #ifndef FSFW_TMTCSERVICES_ACCEPTSVERIFICATIONMESSAGEIF_H_ #define FSFW_TMTCSERVICES_ACCEPTSVERIFICATIONMESSAGEIF_H_ -#include "../ipc/MessageQueueSenderIF.h" +#include "fsfw/ipc/MessageQueueSenderIF.h" class AcceptsVerifyMessageIF { public: - virtual ~AcceptsVerifyMessageIF() {} + virtual ~AcceptsVerifyMessageIF() = default; virtual MessageQueueId_t getVerificationQueue() = 0; }; diff --git a/src/fsfw/tmtcservices/CMakeLists.txt b/src/fsfw/tmtcservices/CMakeLists.txt index 96cf99b5..ca3c887e 100644 --- a/src/fsfw/tmtcservices/CMakeLists.txt +++ b/src/fsfw/tmtcservices/CMakeLists.txt @@ -1,10 +1,14 @@ -target_sources(${LIB_FSFW_NAME} - PRIVATE - CommandingServiceBase.cpp - PusServiceBase.cpp - PusVerificationReport.cpp - TmTcBridge.cpp - TmTcMessage.cpp - VerificationReporter.cpp - SpacePacketParser.cpp -) \ No newline at end of file +target_sources( + ${LIB_FSFW_NAME} + PRIVATE CommandingServiceBase.cpp + PusServiceBase.cpp + PusVerificationReport.cpp + TmTcBridge.cpp + TmTcMessage.cpp + VerificationReporter.cpp + SpacePacketParser.cpp + TmStoreHelper.cpp + TmSendHelper.cpp + TmStoreAndSendHelper.cpp + tcHelpers.cpp + tmHelpers.cpp) diff --git a/src/fsfw/tmtcservices/CommandingServiceBase.cpp b/src/fsfw/tmtcservices/CommandingServiceBase.cpp index bbdf8d2a..1ec5c0d8 100644 --- a/src/fsfw/tmtcservices/CommandingServiceBase.cpp +++ b/src/fsfw/tmtcservices/CommandingServiceBase.cpp @@ -3,33 +3,40 @@ #include "fsfw/ipc/QueueFactory.h" #include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tcdistribution/PUSDistributorIF.h" +#include "fsfw/tcdistribution/PusDistributorIF.h" #include "fsfw/tmtcpacket/pus/tc.h" -#include "fsfw/tmtcpacket/pus/tm.h" #include "fsfw/tmtcservices/AcceptsTelemetryIF.h" #include "fsfw/tmtcservices/TmTcMessage.h" +#include "fsfw/tmtcservices/tcHelpers.h" +#include "fsfw/tmtcservices/tmHelpers.h" object_id_t CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT; object_id_t CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT; CommandingServiceBase::CommandingServiceBase(object_id_t setObjectId, uint16_t apid, - uint8_t service, uint8_t numberOfParallelCommands, - uint16_t commandTimeoutSeconds, size_t queueDepth) + const char* name, uint8_t service, + uint8_t numberOfParallelCommands, + uint16_t commandTimeoutSeconds, size_t queueDepth, + VerificationReporterIF* verificationReporter) : SystemObject(setObjectId), apid(apid), service(service), timeoutSeconds(commandTimeoutSeconds), - commandMap(numberOfParallelCommands) { + tmStoreHelper(apid), + tmHelper(service, tmStoreHelper, tmSendHelper), + verificationReporter(verificationReporter), + commandMap(numberOfParallelCommands), + name(name) { commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth); requestQueue = QueueFactory::instance()->createMessageQueue(queueDepth); } -void CommandingServiceBase::setPacketSource(object_id_t packetSource) { - this->packetSource = packetSource; +void CommandingServiceBase::setPacketSource(object_id_t packetSource_) { + packetSource = packetSource_; } -void CommandingServiceBase::setPacketDestination(object_id_t packetDestination) { - this->packetDestination = packetDestination; +void CommandingServiceBase::setPacketDestination(object_id_t packetDestination_) { + packetDestination = packetDestination_; } CommandingServiceBase::~CommandingServiceBase() { @@ -42,29 +49,28 @@ ReturnValue_t CommandingServiceBase::performOperation(uint8_t opCode) { handleRequestQueue(); checkTimeout(); doPeriodicOperation(); - return RETURN_OK; + return returnvalue::OK; } -uint16_t CommandingServiceBase::getIdentifier() { return service; } +uint32_t CommandingServiceBase::getIdentifier() const { return service; } -MessageQueueId_t CommandingServiceBase::getRequestQueue() { return requestQueue->getId(); } +MessageQueueId_t CommandingServiceBase::getRequestQueue() const { return requestQueue->getId(); } ReturnValue_t CommandingServiceBase::initialize() { ReturnValue_t result = SystemObject::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (packetDestination == objects::NO_OBJECT) { packetDestination = defaultPacketDestination; } - AcceptsTelemetryIF* packetForwarding = - ObjectManager::instance()->get(packetDestination); + auto* packetForwarding = ObjectManager::instance()->get(packetDestination); if (packetSource == objects::NO_OBJECT) { packetSource = defaultPacketSource; } - PUSDistributorIF* distributor = ObjectManager::instance()->get(packetSource); + auto* distributor = ObjectManager::instance()->get(packetSource); if (packetForwarding == nullptr or distributor == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -75,13 +81,13 @@ ReturnValue_t CommandingServiceBase::initialize() { return ObjectManagerIF::CHILD_INIT_FAILED; } - distributor->registerService(this); + distributor->registerService(*this); requestQueue->setDefaultDestination(packetForwarding->getReportReceptionQueue()); - IPCStore = ObjectManager::instance()->get(objects::IPC_STORE); - TCStore = ObjectManager::instance()->get(objects::TC_STORE); + ipcStore = ObjectManager::instance()->get(objects::IPC_STORE); + tcStore = ObjectManager::instance()->get(objects::TC_STORE); - if (IPCStore == nullptr or TCStore == nullptr) { + if (ipcStore == nullptr or tcStore == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "CommandingServiceBase::intialize: IPC store or TC store " "not initialized yet!" @@ -89,16 +95,51 @@ ReturnValue_t CommandingServiceBase::initialize() { #endif return ObjectManagerIF::CHILD_INIT_FAILED; } + if (tmStoreHelper.getTmStore() == nullptr) { + auto* tmStore = ObjectManager::instance()->get(objects::TM_STORE); + if (tmStore == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + tmStoreHelper.setTmStore(*tmStore); + } + // Generally, all TM packets will pass through a layer where the sequence count is set. + // This avoids duplicate calculation of the CRC16 + tmStoreHelper.disableCrcCalculation(); + if (tmTimeStamper == nullptr) { + tmTimeStamper = ObjectManager::instance()->get(objects::TIME_STAMPER); + if (tmTimeStamper == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + } + tmStoreHelper.setTimeStamper(*tmTimeStamper); - return RETURN_OK; + if (errReporter == nullptr) { + errReporter = + ObjectManager::instance()->get(objects::INTERNAL_ERROR_REPORTER); + if (errReporter != nullptr) { + tmSendHelper.setInternalErrorReporter(*errReporter); + } + } else { + tmSendHelper.setInternalErrorReporter(*errReporter); + } + tmSendHelper.setMsgQueue(*requestQueue); + + if (verificationReporter == nullptr) { + verificationReporter = + ObjectManager::instance()->get(objects::VERIFICATION_REPORTER); + if (verificationReporter == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + } + return returnvalue::OK; } void CommandingServiceBase::handleCommandQueue() { CommandMessage reply; - ReturnValue_t result = RETURN_FAILED; + ReturnValue_t result; while (true) { result = commandQueue->receiveMessage(&reply); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { handleCommandMessage(&reply); continue; } else if (result == MessageQueueIF::EMPTY) { @@ -138,18 +179,18 @@ void CommandingServiceBase::handleCommandMessage(CommandMessage* reply) { iter->second.objectId, &isStep); /* If the child implementation does not implement special handling for - * rejected replies (RETURN_FAILED or INVALID_REPLY is returned), a + * rejected replies (returnvalue::FAILED or INVALID_REPLY is returned), a * failure verification will be generated with the reason as the * return code and the initial command as failure parameter 1 */ if ((reply->getCommand() == CommandMessage::REPLY_REJECTED) and - (result == RETURN_FAILED or result == INVALID_REPLY)) { + (result == returnvalue::FAILED or result == INVALID_REPLY)) { result = reply->getReplyRejectedReason(); failureParameter1 = iter->second.command; } switch (result) { case EXECUTION_COMPLETE: - case RETURN_OK: + case returnvalue::OK: case NO_STEP_MESSAGE: // handle result of reply handler implemented by developer. handleReplyHandlerResult(result, iter, &nextCommand, reply, isStep); @@ -160,16 +201,14 @@ void CommandingServiceBase::handleCommandMessage(CommandMessage* reply) { break; default: if (isStep) { - verificationReporter.sendFailureReport( - tc_verification::PROGRESS_FAILURE, iter->second.tcInfo.ackFlags, - iter->second.tcInfo.tcPacketId, iter->second.tcInfo.tcSequenceControl, result, - ++iter->second.step, failureParameter1, failureParameter2); + prepareVerificationFailureWithFullInfo(tcverif::PROGRESS_FAILURE, iter->second.tcInfo, + result, true); + failParams.step = ++iter->second.step; } else { - verificationReporter.sendFailureReport( - tc_verification::COMPLETION_FAILURE, iter->second.tcInfo.ackFlags, - iter->second.tcInfo.tcPacketId, iter->second.tcInfo.tcSequenceControl, result, 0, - failureParameter1, failureParameter2); + prepareVerificationFailureWithFullInfo(tcverif::COMPLETION_FAILURE, iter->second.tcInfo, + result, true); } + verificationReporter->sendFailureReport(failParams); failureParameter1 = 0; failureParameter2 = 0; checkAndExecuteFifo(iter); @@ -185,36 +224,33 @@ void CommandingServiceBase::handleReplyHandlerResult(ReturnValue_t result, Comma // In case a new command is to be sent immediately, this is performed here. // If no new command is sent, only analyse reply result by initializing // sendResult as RETURN_OK - ReturnValue_t sendResult = RETURN_OK; + ReturnValue_t sendResult = returnvalue::OK; if (nextCommand->getCommand() != CommandMessage::CMD_NONE) { sendResult = commandQueue->sendMessage(reply->getSender(), nextCommand); } - if (sendResult == RETURN_OK) { + if (sendResult == returnvalue::OK) { if (isStep and result != NO_STEP_MESSAGE) { - verificationReporter.sendSuccessReport( - tc_verification::PROGRESS_SUCCESS, iter->second.tcInfo.ackFlags, - iter->second.tcInfo.tcPacketId, iter->second.tcInfo.tcSequenceControl, - ++iter->second.step); + prepareVerificationSuccessWithFullInfo(tcverif::PROGRESS_SUCCESS, iter->second.tcInfo); + successParams.step = ++iter->second.step; + verificationReporter->sendSuccessReport(successParams); } else { - verificationReporter.sendSuccessReport( - tc_verification::COMPLETION_SUCCESS, iter->second.tcInfo.ackFlags, - iter->second.tcInfo.tcPacketId, iter->second.tcInfo.tcSequenceControl, 0); + prepareVerificationSuccessWithFullInfo(tcverif::COMPLETION_SUCCESS, iter->second.tcInfo); + verificationReporter->sendSuccessReport(successParams); checkAndExecuteFifo(iter); } } else { if (isStep) { + prepareVerificationFailureWithFullInfo(tcverif::PROGRESS_FAILURE, iter->second.tcInfo, result, + true); + failParams.step = ++iter->second.step; nextCommand->clearCommandMessage(); - verificationReporter.sendFailureReport( - tc_verification::PROGRESS_FAILURE, iter->second.tcInfo.ackFlags, - iter->second.tcInfo.tcPacketId, iter->second.tcInfo.tcSequenceControl, sendResult, - ++iter->second.step, failureParameter1, failureParameter2); + verificationReporter->sendFailureReport(failParams); } else { + prepareVerificationFailureWithFullInfo(tcverif::COMPLETION_FAILURE, iter->second.tcInfo, + result, true); nextCommand->clearCommandMessage(); - verificationReporter.sendFailureReport( - tc_verification::COMPLETION_FAILURE, iter->second.tcInfo.ackFlags, - iter->second.tcInfo.tcPacketId, iter->second.tcInfo.tcSequenceControl, sendResult, 0, - failureParameter1, failureParameter2); + verificationReporter->sendFailureReport(failParams); } failureParameter1 = 0; failureParameter2 = 0; @@ -226,23 +262,26 @@ void CommandingServiceBase::handleRequestQueue() { TmTcMessage message; ReturnValue_t result; store_address_t address; - TcPacketStoredPus packet; MessageQueueId_t queue; object_id_t objectId; - for (result = requestQueue->receiveMessage(&message); result == RETURN_OK; + for (result = requestQueue->receiveMessage(&message); result == returnvalue::OK; result = requestQueue->receiveMessage(&message)) { address = message.getStorageId(); - packet.setStoreAddress(address, &packet); - - if ((packet.getSubService() == 0) or (isValidSubservice(packet.getSubService()) != RETURN_OK)) { - rejectPacket(tc_verification::START_FAILURE, &packet, INVALID_SUBSERVICE); + result = setUpTcReader(address); + if (result != returnvalue::OK) { + rejectPacketInvalidTc(result, address); + continue; + } + if ((tcReader.getSubService() == 0) or + (isValidSubservice(tcReader.getSubService()) != returnvalue::OK)) { + rejectPacket(tcverif::START_FAILURE, address, INVALID_SUBSERVICE); continue; } - result = getMessageQueueAndObject(packet.getSubService(), packet.getApplicationData(), - packet.getApplicationDataSize(), &queue, &objectId); - if (result != HasReturnvaluesIF::RETURN_OK) { - rejectPacket(tc_verification::START_FAILURE, &packet, result); + result = getMessageQueueAndObject(tcReader.getSubService(), tcReader.getUserData(), + tcReader.getUserDataLen(), &queue, &objectId); + if (result != returnvalue::OK) { + rejectPacket(tcverif::START_FAILURE, address, result); continue; } @@ -252,109 +291,74 @@ void CommandingServiceBase::handleRequestQueue() { if (iter != commandMap.end()) { result = iter->second.fifo.insert(address); - if (result != RETURN_OK) { - rejectPacket(tc_verification::START_FAILURE, &packet, OBJECT_BUSY); + if (result != returnvalue::OK) { + rejectPacket(tcverif::START_FAILURE, address, OBJECT_BUSY); } } else { CommandInfo newInfo; // Info will be set by startExecution if neccessary newInfo.objectId = objectId; result = commandMap.insert(queue, newInfo, &iter); - if (result != RETURN_OK) { - rejectPacket(tc_verification::START_FAILURE, &packet, BUSY); + if (result != returnvalue::OK) { + rejectPacket(tcverif::START_FAILURE, address, BUSY); } else { - startExecution(&packet, iter); + startExecution(address, iter); } } } } -ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, const uint8_t* data, - size_t dataLen, const uint8_t* headerData, - size_t headerSize) { -#if FSFW_USE_PUS_C_TELEMETRY == 0 - TmPacketStoredPusA tmPacketStored(this->apid, this->service, subservice, this->tmPacketCounter, - data, dataLen, headerData, headerSize); -#else - TmPacketStoredPusC tmPacketStored(this->apid, this->service, subservice, this->tmPacketCounter, - data, dataLen, headerData, headerSize); -#endif - ReturnValue_t result = - tmPacketStored.sendPacket(requestQueue->getDefaultDestination(), requestQueue->getId()); - if (result == HasReturnvaluesIF::RETURN_OK) { - this->tmPacketCounter++; +ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, const uint8_t* sourceData, + size_t sourceDataLen) { + ReturnValue_t result = tmHelper.prepareTmPacket(subservice, sourceData, sourceDataLen); + if (result != returnvalue::OK) { + return result; } - return result; + return tmHelper.storeAndSendTmPacket(); } ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, object_id_t objectId, const uint8_t* data, size_t dataLen) { - uint8_t buffer[sizeof(object_id_t)]; - uint8_t* pBuffer = buffer; - size_t size = 0; - SerializeAdapter::serialize(&objectId, &pBuffer, &size, sizeof(object_id_t), - SerializeIF::Endianness::BIG); -#if FSFW_USE_PUS_C_TELEMETRY == 0 - TmPacketStoredPusA tmPacketStored(this->apid, this->service, subservice, this->tmPacketCounter, - data, dataLen, buffer, size); -#else - TmPacketStoredPusC tmPacketStored(this->apid, this->service, subservice, this->tmPacketCounter, - data, dataLen, buffer, size); -#endif - ReturnValue_t result = - tmPacketStored.sendPacket(requestQueue->getDefaultDestination(), requestQueue->getId()); - if (result == HasReturnvaluesIF::RETURN_OK) { - this->tmPacketCounter++; + telemetry::DataWithObjectIdPrefix dataWithObjId(objectId, data, dataLen); + ReturnValue_t result = tmHelper.prepareTmPacket(subservice, dataWithObjId); + if (result != returnvalue::OK) { + return result; } - return result; + return tmHelper.storeAndSendTmPacket(); } -ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, SerializeIF* content, - SerializeIF* header) { -#if FSFW_USE_PUS_C_TELEMETRY == 0 - TmPacketStoredPusA tmPacketStored(this->apid, this->service, subservice, this->tmPacketCounter, - content, header); -#else - TmPacketStoredPusC tmPacketStored(this->apid, this->service, subservice, this->tmPacketCounter, - content, header); -#endif - ReturnValue_t result = - tmPacketStored.sendPacket(requestQueue->getDefaultDestination(), requestQueue->getId()); - if (result == HasReturnvaluesIF::RETURN_OK) { - this->tmPacketCounter++; +ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, SerializeIF& sourceData) { + ReturnValue_t result = tmHelper.prepareTmPacket(subservice, sourceData); + if (result != returnvalue::OK) { + return result; } - return result; + return tmHelper.storeAndSendTmPacket(); } -void CommandingServiceBase::startExecution(TcPacketStoredPus* storedPacket, CommandMapIter iter) { - ReturnValue_t result = RETURN_OK; +void CommandingServiceBase::startExecution(store_address_t storeId, CommandMapIter& iter) { CommandMessage command; - // TcPacketPusBase* tcPacketBase = storedPacket->getPacketBase(); - if (storedPacket == nullptr) { - return; - } - iter->second.subservice = storedPacket->getSubService(); - result = prepareCommand(&command, iter->second.subservice, storedPacket->getApplicationData(), - storedPacket->getApplicationDataSize(), &iter->second.state, - iter->second.objectId); + iter->second.subservice = tcReader.getSubService(); + ReturnValue_t result = + prepareCommand(&command, iter->second.subservice, tcReader.getUserData(), + tcReader.getUserDataLen(), &iter->second.state, iter->second.objectId); - ReturnValue_t sendResult = RETURN_OK; + ReturnValue_t sendResult = returnvalue::OK; switch (result) { - case RETURN_OK: + case returnvalue::OK: if (command.getCommand() != CommandMessage::CMD_NONE) { sendResult = commandQueue->sendMessage(iter.value->first, &command); } - if (sendResult == RETURN_OK) { + if (sendResult == returnvalue::OK) { Clock::getUptime(&iter->second.uptimeOfStart); iter->second.step = 0; - iter->second.subservice = storedPacket->getSubService(); + iter->second.subservice = tcReader.getSubService(); iter->second.command = command.getCommand(); - iter->second.tcInfo.ackFlags = storedPacket->getAcknowledgeFlags(); - iter->second.tcInfo.tcPacketId = storedPacket->getPacketId(); - iter->second.tcInfo.tcSequenceControl = storedPacket->getPacketSequenceControl(); - acceptPacket(tc_verification::START_SUCCESS, storedPacket); + iter->second.tcInfo.ackFlags = tcReader.getAcknowledgeFlags(); + iter->second.tcInfo.tcPacketId = tcReader.getPacketIdRaw(); + iter->second.tcInfo.tcSequenceControl = tcReader.getPacketSeqCtrlRaw(); + acceptPacket(tcverif::START_SUCCESS, storeId); } else { command.clearCommandMessage(); - rejectPacket(tc_verification::START_FAILURE, storedPacket, sendResult); + rejectPacket(tcverif::START_FAILURE, storeId, sendResult); checkAndExecuteFifo(iter); } break; @@ -363,43 +367,61 @@ void CommandingServiceBase::startExecution(TcPacketStoredPus* storedPacket, Comm // Fire-and-forget command. sendResult = commandQueue->sendMessage(iter.value->first, &command); } - if (sendResult == RETURN_OK) { - verificationReporter.sendSuccessReport(tc_verification::START_SUCCESS, - storedPacket->getPacketBase()); - acceptPacket(tc_verification::COMPLETION_SUCCESS, storedPacket); + if (sendResult == returnvalue::OK) { + verificationReporter->sendSuccessReport( + VerifSuccessParams(tcverif::START_SUCCESS, tcReader)); + acceptPacket(tcverif::COMPLETION_SUCCESS, storeId); checkAndExecuteFifo(iter); } else { command.clearCommandMessage(); - rejectPacket(tc_verification::START_FAILURE, storedPacket, sendResult); + rejectPacket(tcverif::START_FAILURE, storeId, sendResult); checkAndExecuteFifo(iter); } break; default: - rejectPacket(tc_verification::START_FAILURE, storedPacket, result); + rejectPacket(tcverif::START_FAILURE, storeId, result); checkAndExecuteFifo(iter); break; } } -void CommandingServiceBase::rejectPacket(uint8_t reportId, TcPacketStoredPus* packet, - ReturnValue_t errorCode) { - verificationReporter.sendFailureReport(reportId, dynamic_cast(packet), - errorCode); - packet->deletePacket(); +ReturnValue_t CommandingServiceBase::rejectPacketInvalidTc(ReturnValue_t errorCode, + store_address_t tcStoreId) { + failureParameter1 = INVALID_TC; + prepareVerificationFailureWithNoTcInfo(tcverif::START_FAILURE, errorCode, true); + if (tcStoreId != store_address_t::invalid()) { + tcStore->deleteData(tcStoreId); + } + return verificationReporter->sendFailureReport(failParams); } -void CommandingServiceBase::acceptPacket(uint8_t reportId, TcPacketStoredPus* packet) { - verificationReporter.sendSuccessReport(reportId, dynamic_cast(packet)); - packet->deletePacket(); +ReturnValue_t CommandingServiceBase::rejectPacket(uint8_t reportId, store_address_t tcStoreId, + ReturnValue_t errorCode) { + ReturnValue_t result = + verificationReporter->sendFailureReport(VerifFailureParams(reportId, tcReader, errorCode)); + tcStore->deleteData(tcStoreId); + return result; +} + +ReturnValue_t CommandingServiceBase::acceptPacket(uint8_t reportId, store_address_t tcStoreId) { + ReturnValue_t result = + verificationReporter->sendSuccessReport(VerifSuccessParams(reportId, tcReader)); + tcStore->deleteData(tcStoreId); + return result; } void CommandingServiceBase::checkAndExecuteFifo(CommandMapIter& iter) { store_address_t address; - if (iter->second.fifo.retrieve(&address) != RETURN_OK) { + if (iter->second.fifo.retrieve(&address) != returnvalue::OK) { commandMap.erase(&iter); } else { - TcPacketStoredPus newPacket(address); - startExecution(&newPacket, iter); + ReturnValue_t result = setUpTcReader(address); + if (result == returnvalue::OK) { + startExecution(address, iter); + } else { + // TODO: Warning? + rejectPacket(tcverif::START_FAILURE, address, result); + } } } @@ -417,12 +439,57 @@ void CommandingServiceBase::checkTimeout() { CommandMapIter iter; for (iter = commandMap.begin(); iter != commandMap.end(); ++iter) { if ((iter->second.uptimeOfStart + (timeoutSeconds * 1000)) < uptime) { - verificationReporter.sendFailureReport( - tc_verification::COMPLETION_FAILURE, iter->second.tcInfo.ackFlags, - iter->second.tcInfo.tcPacketId, iter->second.tcInfo.tcSequenceControl, TIMEOUT); + prepareVerificationFailureWithFullInfo(tcverif::COMPLETION_FAILURE, iter->second.tcInfo, + TIMEOUT, false); + verificationReporter->sendFailureReport(failParams); checkAndExecuteFifo(iter); } } } void CommandingServiceBase::setTaskIF(PeriodicTaskIF* task_) { executingTask = task_; } + +void CommandingServiceBase::setCustomTmStore(StorageManagerIF& store) { + tmStoreHelper.setTmStore(store); +} + +ReturnValue_t CommandingServiceBase::setUpTcReader(store_address_t storeId) { + return tc::prepareTcReader(*tcStore, storeId, tcReader); +} + +void CommandingServiceBase::prepareVerificationFailureWithNoTcInfo(uint8_t reportId, + ReturnValue_t errorCode, + bool setCachedFailParams) { + failParams.resetTcFields(); + failParams.resetFailParams(); + failParams.reportId = reportId; + failParams.errorCode = errorCode; + if (setCachedFailParams) { + failParams.errorParam1 = failureParameter1; + failParams.errorParam2 = failureParameter2; + } +} +void CommandingServiceBase::prepareVerificationFailureWithFullInfo(uint8_t reportId, + CommandInfo::TcInfo& tcInfo, + ReturnValue_t errorCode, + bool setCachedFailParams) { + failParams.reportId = reportId; + failParams.tcPacketId = tcInfo.tcPacketId; + failParams.tcPsc = tcInfo.tcSequenceControl; + failParams.ackFlags = tcInfo.ackFlags; + failParams.resetFailParams(); + failParams.errorCode = errorCode; + if (setCachedFailParams) { + failParams.errorParam1 = failureParameter1; + failParams.errorParam2 = failureParameter2; + } +} +void CommandingServiceBase::prepareVerificationSuccessWithFullInfo( + uint8_t reportId, CommandingServiceBase::CommandInfo::TcInfo& tcInfo) { + successParams.reportId = reportId; + successParams.tcPacketId = tcInfo.tcPacketId; + successParams.tcPsc = tcInfo.tcSequenceControl; + successParams.ackFlags = tcInfo.ackFlags; +} + +const char* CommandingServiceBase::getName() const { return name; } diff --git a/src/fsfw/tmtcservices/CommandingServiceBase.h b/src/fsfw/tmtcservices/CommandingServiceBase.h index 0ae19505..92369b58 100644 --- a/src/fsfw/tmtcservices/CommandingServiceBase.h +++ b/src/fsfw/tmtcservices/CommandingServiceBase.h @@ -2,6 +2,8 @@ #define FSFW_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ #include "AcceptsTelecommandsIF.h" +#include "TmSendHelper.h" +#include "TmStoreHelper.h" #include "VerificationReporter.h" #include "fsfw/FSFW.h" #include "fsfw/container/FIFO.h" @@ -12,33 +14,34 @@ #include "fsfw/serialize/SerializeIF.h" #include "fsfw/storagemanager/StorageManagerIF.h" #include "fsfw/tasks/ExecutableObjectIF.h" - -class TcPacketStoredBase; -class TcPacketStoredPus; +#include "fsfw/tmtcservices/TmStoreAndSendHelper.h" namespace Factory { void setStaticFrameworkObjectIds(); -} +}; /** * @brief This class is the basis for all PUS Services, which have to * relay Telecommands to software bus. * * It manages Telecommand reception and the generation of Verification Reports - * similar to PusServiceBase. This class is used if a telecommand can't be + * similar to @PusServiceBase. This class is used if a telecommand can't be * handled immediately and must be relayed to the internal software bus. * - isValidSubservice * - getMessageQueueAndObject * - prepareCommand * - handleReply + * + * Please note that the TM packets generated by this class will not have a valid CRC. It is + * generally assumed that all packets will pass through a layer where the sequence count is set + * and the CRC16 needs to be re-calculated anyway. * @author gaisser * @ingroup pus_services */ class CommandingServiceBase : public SystemObject, public AcceptsTelecommandsIF, - public ExecutableObjectIF, - public HasReturnvaluesIF { - friend void(Factory::setStaticFrameworkObjectIds)(); + public ExecutableObjectIF { + friend void Factory::setStaticFrameworkObjectIds(); public: // We could make this configurable via preprocessor and the FSFWConfig file. @@ -48,7 +51,13 @@ class CommandingServiceBase : public SystemObject, static const ReturnValue_t EXECUTION_COMPLETE = MAKE_RETURN_CODE(1); static const ReturnValue_t NO_STEP_MESSAGE = MAKE_RETURN_CODE(2); + /** + * Target object has too many pending requests + */ static const ReturnValue_t OBJECT_BUSY = MAKE_RETURN_CODE(3); + /** + * Command map is full + */ static const ReturnValue_t BUSY = MAKE_RETURN_CODE(4); static const ReturnValue_t INVALID_TC = MAKE_RETURN_CODE(5); static const ReturnValue_t INVALID_OBJECT = MAKE_RETURN_CODE(6); @@ -66,11 +75,12 @@ class CommandingServiceBase : public SystemObject, * @param setPacketDestination * @param queueDepth */ - CommandingServiceBase(object_id_t setObjectId, uint16_t apid, uint8_t service, + CommandingServiceBase(object_id_t setObjectId, uint16_t apid, const char* name, uint8_t service, uint8_t numberOfParallelCommands, uint16_t commandTimeoutSeconds, - size_t queueDepth = 20); - virtual ~CommandingServiceBase(); + size_t queueDepth = 20, VerificationReporterIF* reporter = nullptr); + ~CommandingServiceBase() override; + void setCustomTmStore(StorageManagerIF& store); /** * This setter can be used to set the packet source individually instead * of using the default static framework ID set in the factory. @@ -91,11 +101,11 @@ class CommandingServiceBase : public SystemObject, * Handle request queue for external commands. * Handle command Queue for internal commands. * @param opCode is unused here at the moment - * @return RETURN_OK + * @return returnvalue::OK */ - virtual ReturnValue_t performOperation(uint8_t opCode) override; + ReturnValue_t performOperation(uint8_t opCode) override; - virtual uint16_t getIdentifier(); + uint32_t getIdentifier() const override; /** * Returns the requestQueue MessageQueueId_t @@ -104,7 +114,7 @@ class CommandingServiceBase : public SystemObject, * * @return requestQueue messageQueueId_t */ - virtual MessageQueueId_t getRequestQueue(); + MessageQueueId_t getRequestQueue() const override; /** * Returns the commandQueue MessageQueueId_t @@ -114,7 +124,7 @@ class CommandingServiceBase : public SystemObject, */ virtual MessageQueueId_t getCommandQueue(); - virtual ReturnValue_t initialize() override; + ReturnValue_t initialize() override; /** * Implementation of ExecutableObjectIF function @@ -122,14 +132,15 @@ class CommandingServiceBase : public SystemObject, * Used to setup the reference of the task, that executes this component * @param task Pointer to the taskIF of this task */ - virtual void setTaskIF(PeriodicTaskIF* task) override; + void setTaskIF(PeriodicTaskIF* task) override; + const char* getName() const override; protected: /** * Check the target subservice * @param subservice[in] * @return - * -@c RETURN_OK Subservice valid, continue message handling + * -@c returnvalue::OK Subservice valid, continue message handling * -@c INVALID_SUBSERVICE if service is not known, rejects packet. */ virtual ReturnValue_t isValidSubservice(uint8_t subservice) = 0; @@ -144,8 +155,8 @@ class CommandingServiceBase : public SystemObject, * @param id MessageQueue ID is stored here * @param objectId Object ID is extracted and stored here * @return - * - @c RETURN_OK Cotinue message handling - * - @c RETURN_FAILED Reject the packet and generates a start failure + * - @c returnvalue::OK Continue message handling + * - @c returnvalue::FAILED Reject the packet and generates a start failure * verification */ virtual ReturnValue_t getMessageQueueAndObject(uint8_t subservice, const uint8_t* tcData, @@ -165,8 +176,8 @@ class CommandingServiceBase : public SystemObject, * communication * @param objectId Target object ID * @return - * - @c RETURN_OK to generate a verification start message - * - @c EXECUTION_COMPELTE Fire-and-forget command. Generate a completion + * - @c returnvalue::OK to generate a verification start message + * - @c EXECUTION_COMPLETE Fire-and-forget command. Generate a completion * verification message. * - @c Anything else rejects the packets and generates a start failure * verification. @@ -190,10 +201,10 @@ class CommandingServiceBase : public SystemObject, * @param objectId Source object ID * @param isStep Flag value to mark steps of command execution * @return - * - @c RETURN_OK, @c EXECUTION_COMPLETE or @c NO_STEP_MESSAGE to + * - @c returnvalue::OK, @c EXECUTION_COMPLETE or @c NO_STEP_MESSAGE to * generate TC verification success * - @c INVALID_REPLY Calls handleUnrequestedReply - * - Anything else triggers a TC verification failure. If RETURN_FAILED or + * - Anything else triggers a TC verification failure. If returnvalue::FAILED or * INVALID_REPLY is returned and the command ID is * CommandMessage::REPLY_REJECTED, a failure verification message with * the reason as the error parameter and the initial command as @@ -217,7 +228,7 @@ class CommandingServiceBase : public SystemObject, virtual void doPeriodicOperation(); struct CommandInfo : public SerializeIF { - struct tcInfo { + struct TcInfo { uint8_t ackFlags; uint16_t tcPacketId; uint16_t tcSequenceControl; @@ -230,16 +241,16 @@ class CommandingServiceBase : public SystemObject, object_id_t objectId; FIFO fifo; - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const override { - return HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override { + return returnvalue::FAILED; }; - virtual size_t getSerializedSize() const override { return 0; }; + [[nodiscard]] size_t getSerializedSize() const override { return 0; }; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) override { - return HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override { + return returnvalue::FAILED; }; }; @@ -251,17 +262,21 @@ class CommandingServiceBase : public SystemObject, const uint16_t timeoutSeconds; - uint8_t tmPacketCounter = 0; + PusTcReader tcReader; + TmStoreHelper tmStoreHelper; + TmSendHelper tmSendHelper; + TmStoreAndSendWrapper tmHelper; - StorageManagerIF* IPCStore = nullptr; - - StorageManagerIF* TCStore = nullptr; + StorageManagerIF* tcStore = nullptr; + StorageManagerIF* ipcStore = nullptr; MessageQueueIF* commandQueue = nullptr; - MessageQueueIF* requestQueue = nullptr; - VerificationReporter verificationReporter; + TimeWriterIF* tmTimeStamper = nullptr; + VerificationReporterIF* verificationReporter; + + InternalErrorReporterIF* errReporter = nullptr; FixedMap commandMap; @@ -269,6 +284,8 @@ class CommandingServiceBase : public SystemObject, uint32_t failureParameter1 = 0; uint32_t failureParameter2 = 0; + const char* name = ""; + static object_id_t defaultPacketSource; object_id_t packetSource = objects::NO_OBJECT; static object_id_t defaultPacketDestination; @@ -280,45 +297,19 @@ class CommandingServiceBase : public SystemObject, */ PeriodicTaskIF* executingTask = nullptr; - /** - * @brief Send TM data from pointer to data. - * If a header is supplied it is added before data - * @param subservice Number of subservice - * @param data Pointer to the data in the Packet - * @param dataLen Lenght of data in the Packet - * @param headerData HeaderData will be placed before data - * @param headerSize Size of HeaderData - */ - ReturnValue_t sendTmPacket(uint8_t subservice, const uint8_t* data, size_t dataLen, - const uint8_t* headerData = nullptr, size_t headerSize = 0); - - /** - * @brief To send TM packets of objects that still need to be serialized - * and consist of an object ID with appended data. - * @param subservice Number of subservice - * @param objectId ObjectId is placed before data - * @param data Data to append to the packet - * @param dataLen Length of Data - */ + ReturnValue_t sendTmPacket(uint8_t subservice, const uint8_t* sourceData, size_t sourceDataLen); ReturnValue_t sendTmPacket(uint8_t subservice, object_id_t objectId, const uint8_t* data, size_t dataLen); - - /** - * @brief To send packets which are contained inside a class implementing - * SerializeIF. - * @param subservice Number of subservice - * @param content This is a pointer to the serialized packet - * @param header Serialize IF header which will be placed before content - */ - ReturnValue_t sendTmPacket(uint8_t subservice, SerializeIF* content, - SerializeIF* header = nullptr); + ReturnValue_t sendTmPacket(uint8_t subservice, SerializeIF& sourceData); void checkAndExecuteFifo(CommandMapIter& iter); + VerifFailureParams failParams; + VerifSuccessParams successParams; private: /** * This method handles internal execution of a command, - * once it has been started by @sa{startExecution()} in the request + * once it has been started by @startExecution in the request * queue handler. * It handles replies generated by the devices and relayed by the specific * service implementation. This means that it determines further course of @@ -338,23 +329,36 @@ class CommandingServiceBase : public SystemObject, * @brief Handler function for request queue * @details * Sequence of request queue handling: - * isValidSubservice -> getMessageQueueAndObject -> startExecution + * @isValidSubservice -> @getMessageQueueAndObject -> @startExecution * Generates a Start Success Reports TM[1,3] in subfunction - * @sa{startExecution()} or a Start Failure Report TM[1,4] by using the + * @startExecution or a Start Failure Report TM[1,4] by using the * TC Verification Service. */ void handleRequestQueue(); - void rejectPacket(uint8_t reportId, TcPacketStoredPus* packet, ReturnValue_t errorCode); + ReturnValue_t setUpTcReader(store_address_t storeId); - void acceptPacket(uint8_t reportId, TcPacketStoredPus* packet); + /** + * The TC format is invalid or there was an issue retrieving a TC packet from the store. + * @param errorCode Result of the failed operation, will be sent with the verification failure + * message + * @return + */ + ReturnValue_t rejectPacketInvalidTc(ReturnValue_t errorCode, store_address_t tcStoreId); + ReturnValue_t rejectPacket(uint8_t reportId, store_address_t tcStoreId, ReturnValue_t errorCode); - void startExecution(TcPacketStoredPus* storedPacket, CommandMapIter iter); + ReturnValue_t acceptPacket(uint8_t reportId, store_address_t tcStoreId); + + void startExecution(store_address_t storeId, CommandMapIter& iter); void handleCommandMessage(CommandMessage* reply); void handleReplyHandlerResult(ReturnValue_t result, CommandMapIter iter, CommandMessage* nextCommand, CommandMessage* reply, bool& isStep); - + void prepareVerificationFailureWithNoTcInfo(uint8_t reportId, ReturnValue_t errorCode, + bool setCachedFailParams); + void prepareVerificationFailureWithFullInfo(uint8_t reportId, CommandInfo::TcInfo& tcInfo, + ReturnValue_t errorCode, bool setCachedFailParams); + void prepareVerificationSuccessWithFullInfo(uint8_t reportId, CommandInfo::TcInfo& tcInfo); void checkTimeout(); }; diff --git a/src/fsfw/tmtcservices/PusServiceBase.cpp b/src/fsfw/tmtcservices/PusServiceBase.cpp index 3af2b82c..9598e536 100644 --- a/src/fsfw/tmtcservices/PusServiceBase.cpp +++ b/src/fsfw/tmtcservices/PusServiceBase.cpp @@ -3,114 +3,204 @@ #include "fsfw/ipc/QueueFactory.h" #include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tcdistribution/PUSDistributorIF.h" +#include "fsfw/tcdistribution/PusDistributorIF.h" +#include "fsfw/timemanager/CdsShortTimeStamper.h" #include "fsfw/tmtcservices/AcceptsTelemetryIF.h" #include "fsfw/tmtcservices/PusVerificationReport.h" #include "fsfw/tmtcservices/TmTcMessage.h" +#include "fsfw/tmtcservices/tcHelpers.h" -object_id_t PusServiceBase::packetSource = 0; -object_id_t PusServiceBase::packetDestination = 0; +object_id_t PusServiceBase::PACKET_DESTINATION = 0; +object_id_t PusServiceBase::PUS_DISTRIBUTOR = 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); +PusServiceBase::PusServiceBase(PsbParams params) + : SystemObject(params.objectId), psbParams(params) {} + +PusServiceBase::~PusServiceBase() { + if (ownedQueue) { + QueueFactory::instance()->deleteMessageQueue(psbParams.reqQueue); + } } -PusServiceBase::~PusServiceBase() { QueueFactory::instance()->deleteMessageQueue(requestQueue); } - ReturnValue_t PusServiceBase::performOperation(uint8_t opCode) { handleRequestQueue(); - ReturnValue_t result = this->performService(); - if (result != RETURN_OK) { + ReturnValue_t result = performService(); + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PusService " << (uint16_t)this->serviceId << ": performService returned with " - << (int16_t)result << std::endl; + sif::error << "PusService " << psbParams.serviceId << ": performService returned with " + << static_cast(result) << std::endl; #endif - return RETURN_FAILED; + return returnvalue::FAILED; } - return RETURN_OK; + return returnvalue::OK; } -void PusServiceBase::setTaskIF(PeriodicTaskIF* taskHandle) { this->taskHandle = taskHandle; } +void PusServiceBase::setTaskIF(PeriodicTaskIF* taskHandle_) { this->taskHandle = taskHandle_; } void PusServiceBase::handleRequestQueue() { TmTcMessage message; - ReturnValue_t result = RETURN_FAILED; + ReturnValue_t result; for (uint8_t count = 0; count < PUS_SERVICE_MAX_RECEPTION; count++) { - ReturnValue_t status = this->requestQueue->receiveMessage(&message); - // if(status != MessageQueueIF::EMPTY) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - // sif::debug << "PusServiceBase::performOperation: Receiving from " - // << "MQ ID: " << std::hex << "0x" << std::setw(8) - // << std::setfill('0') << this->requestQueue->getId() - // << std::dec << " returned: " << status << std::setfill(' ') - // << std::endl; -#endif - // } - - if (status == RETURN_OK) { - this->currentPacket.setStoreAddress(message.getStorageId(), ¤tPacket); - // info << "Service " << (uint16_t) this->serviceId << - // ": new packet!" << std::endl; - - result = this->handleRequest(currentPacket.getSubService()); - - // debug << "Service " << (uint16_t)this->serviceId << - // ": handleRequest returned: " << (int)return_code << std::endl; - if (result == RETURN_OK) { - this->verifyReporter.sendSuccessReport(tc_verification::COMPLETION_SUCCESS, - &this->currentPacket); - } else { - this->verifyReporter.sendFailureReport(tc_verification::COMPLETION_FAILURE, - &this->currentPacket, result, 0, errorParameter1, - errorParameter2); - } - this->currentPacket.deletePacket(); - errorParameter1 = 0; - errorParameter2 = 0; - } else if (status == MessageQueueIF::EMPTY) { - status = RETURN_OK; - // debug << "PusService " << (uint16_t)this->serviceId << - // ": no new packet." << std::endl; + ReturnValue_t status = psbParams.reqQueue->receiveMessage(&message); + if (status == MessageQueueIF::EMPTY) { break; - } else { + } else if (status != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PusServiceBase::performOperation: Service " << this->serviceId + sif::error << "PusServiceBase::performOperation: Service " << psbParams.serviceId << ": Error receiving packet. Code: " << std::hex << status << std::dec << std::endl; +#else + sif::printError( + "PusServiceBase::performOperation: Service %d. Error receiving packet. Code: %04x\n", + psbParams.serviceId, status); #endif + break; } + result = tc::prepareTcReader(*psbParams.tcPool, message.getStorageId(), currentPacket); + if (result != returnvalue::OK) { + // We were not even able to retrieve the TC, so we can not retrieve any TC properties either + // without segfaulting + auto verifParams = VerifFailureParams(tcverif::START_FAILURE, 0, 0, result); + verifParams.errorParam1 = errorParameter1; + verifParams.errorParam2 = errorParameter2; + psbParams.verifReporter->sendFailureReport(verifParams); + continue; + } + result = handleRequest(currentPacket.getSubService()); + if (result == returnvalue::OK) { + psbParams.verifReporter->sendSuccessReport( + VerifSuccessParams(tcverif::COMPLETION_SUCCESS, currentPacket)); + } else { + auto failParams = VerifFailureParams(tcverif::COMPLETION_FAILURE, currentPacket, result); + failParams.errorParam1 = errorParameter1; + failParams.errorParam2 = errorParameter2; + psbParams.verifReporter->sendFailureReport(failParams); + } + psbParams.tcPool->deleteData(message.getStorageId()); + errorParameter1 = 0; + errorParameter2 = 0; } } -uint16_t PusServiceBase::getIdentifier() { return this->serviceId; } +uint32_t PusServiceBase::getIdentifier() const { return psbParams.serviceId; } -MessageQueueId_t PusServiceBase::getRequestQueue() { return this->requestQueue->getId(); } +MessageQueueId_t PusServiceBase::getRequestQueue() const { + if (psbParams.reqQueue == nullptr) { + return MessageQueueIF::NO_QUEUE; + } + return psbParams.reqQueue->getId(); +} ReturnValue_t PusServiceBase::initialize() { ReturnValue_t result = SystemObject::initialize(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } - AcceptsTelemetryIF* destService = - ObjectManager::instance()->get(packetDestination); - PUSDistributorIF* distributor = ObjectManager::instance()->get(packetSource); - if (destService == nullptr or distributor == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PusServiceBase::PusServiceBase: Service " << this->serviceId - << ": Configuration error. Make sure " - << "packetSource and packetDestination are defined correctly" << std::endl; -#endif - return ObjectManagerIF::CHILD_INIT_FAILED; + if (psbParams.reqQueue == nullptr) { + ownedQueue = true; + psbParams.reqQueue = QueueFactory::instance()->createMessageQueue(PSB_DEFAULT_QUEUE_DEPTH); + } else { + ownedQueue = false; } - this->requestQueue->setDefaultDestination(destService->getReportReceptionQueue()); - distributor->registerService(this); - return HasReturnvaluesIF::RETURN_OK; + + if (psbParams.tmReceiver == nullptr) { + psbParams.tmReceiver = ObjectManager::instance()->get(PACKET_DESTINATION); + if (psbParams.tmReceiver != nullptr) { + psbParams.reqQueue->setDefaultDestination(psbParams.tmReceiver->getReportReceptionQueue()); + } + } + + if (psbParams.pusDistributor == nullptr) { + psbParams.pusDistributor = ObjectManager::instance()->get(PUS_DISTRIBUTOR); + if (psbParams.pusDistributor != nullptr) { + registerService(*psbParams.pusDistributor); + } + } + + if (psbParams.tcPool == nullptr) { + psbParams.tcPool = ObjectManager::instance()->get(objects::TC_STORE); + if (psbParams.tcPool == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + } + + if (psbParams.verifReporter == nullptr) { + psbParams.verifReporter = + ObjectManager::instance()->get(objects::VERIFICATION_REPORTER); + if (psbParams.verifReporter == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + } + return returnvalue::OK; } -ReturnValue_t PusServiceBase::initializeAfterTaskCreation() { - // If task parameters, for example task frequency are required, this - // function should be overriden and the system object task IF can - // be used to get those parameters. - return HasReturnvaluesIF::RETURN_OK; +void PusServiceBase::setTcPool(StorageManagerIF& tcPool) { psbParams.tcPool = &tcPool; } + +void PusServiceBase::setErrorReporter(InternalErrorReporterIF& errReporter_) { + psbParams.errReporter = &errReporter_; } + +ReturnValue_t PusServiceBase::initializeTmHelpers(TmSendHelper& tmSendHelper, + TmStoreHelper& tmStoreHelper) { + ReturnValue_t result = initializeTmSendHelper(tmSendHelper); + if (result != returnvalue::OK) { + return result; + } + return initializeTmStoreHelper(tmStoreHelper); +} + +ReturnValue_t PusServiceBase::initializeTmSendHelper(TmSendHelper& tmSendHelper) { + if (psbParams.reqQueue != nullptr) { + tmSendHelper.setMsgQueue(*psbParams.reqQueue); + tmSendHelper.setDefaultDestination(psbParams.reqQueue->getDefaultDestination()); + } + + if (psbParams.errReporter == nullptr) { + psbParams.errReporter = + ObjectManager::instance()->get(objects::INTERNAL_ERROR_REPORTER); + if (psbParams.errReporter != nullptr) { + tmSendHelper.setInternalErrorReporter(*psbParams.errReporter); + } + } else { + tmSendHelper.setInternalErrorReporter(*psbParams.errReporter); + } + return returnvalue::OK; +} + +ReturnValue_t PusServiceBase::initializeTmStoreHelper(TmStoreHelper& tmStoreHelper) const { + tmStoreHelper.setApid(psbParams.apid); + if (tmStoreHelper.getTmStore() == nullptr) { + auto* tmStore = ObjectManager::instance()->get(objects::TM_STORE); + if (tmStore == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + tmStoreHelper.setTmStore(*tmStore); + } + + if (psbParams.timeStamper == nullptr) { + auto timerStamper = ObjectManager::instance()->get(objects::TIME_STAMPER); + if (timerStamper != nullptr) { + tmStoreHelper.setTimeStamper(*timerStamper); + } + } + // Generally, all TM packets will pass through a layer where the sequence count is set. + // This avoids duplicate calculation of the CRC16 + tmStoreHelper.disableCrcCalculation(); + return returnvalue::OK; +} + +void PusServiceBase::setVerificationReporter(VerificationReporterIF& reporter) { + psbParams.verifReporter = &reporter; +} + +ReturnValue_t PusServiceBase::registerService(PusDistributorIF& distributor) { + return distributor.registerService(*this); +} + +void PusServiceBase::setTmReceiver(AcceptsTelemetryIF& tmReceiver_) { + psbParams.tmReceiver = &tmReceiver_; +} + +void PusServiceBase::setRequestQueue(MessageQueueIF& reqQueue) { psbParams.reqQueue = &reqQueue; } + +const char* PusServiceBase::getName() const { return psbParams.name; } diff --git a/src/fsfw/tmtcservices/PusServiceBase.h b/src/fsfw/tmtcservices/PusServiceBase.h index 9db1bef0..92ce0d99 100644 --- a/src/fsfw/tmtcservices/PusServiceBase.h +++ b/src/fsfw/tmtcservices/PusServiceBase.h @@ -2,14 +2,75 @@ #define FSFW_TMTCSERVICES_PUSSERVICEBASE_H_ #include "AcceptsTelecommandsIF.h" +#include "AcceptsTelemetryIF.h" +#include "TmSendHelper.h" +#include "TmStoreHelper.h" #include "VerificationCodes.h" #include "VerificationReporter.h" #include "fsfw/ipc/MessageQueueIF.h" #include "fsfw/objectmanager/ObjectManagerIF.h" #include "fsfw/objectmanager/SystemObject.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/tasks/ExecutableObjectIF.h" -#include "fsfw/tmtcpacket/pus/tc.h" +#include "fsfw/tcdistribution/PusDistributorIF.h" + +class StorageManagerIF; + +/** + * Configuration parameters for the PUS Service Base + */ +struct PsbParams { + PsbParams() = default; + PsbParams(uint16_t apid, AcceptsTelemetryIF* tmReceiver) : apid(apid), tmReceiver(tmReceiver) {} + PsbParams(const char* name, uint16_t apid, AcceptsTelemetryIF* tmReceiver) + : name(name), apid(apid), tmReceiver(tmReceiver) {} + PsbParams(object_id_t objectId, uint16_t apid, uint8_t serviceId) + : objectId(objectId), apid(apid), serviceId(serviceId) {} + PsbParams(const char* name, object_id_t objectId, uint16_t apid, uint8_t serviceId) + : name(name), objectId(objectId), apid(apid), serviceId(serviceId) {} + const char* name = ""; + object_id_t objectId = objects::NO_OBJECT; + uint16_t apid = 0; + uint8_t serviceId = 0; + /** + * The default destination ID for generated telemetry. If this is not set, @initialize of PSB + * will attempt to find a suitable object with the object ID @PusServiceBase::packetDestination + */ + AcceptsTelemetryIF* tmReceiver = nullptr; + /** + * An instance of the VerificationReporter class, that simplifies + * sending any kind of verification message to the TC Verification Service. If this is not set, + * @initialize of PSB will attempt to find a suitable global object with the ID + * @objects::TC_VERIFICATOR + */ + VerificationReporterIF* verifReporter = nullptr; + /** + * This is a complete instance of the telecommand reception queue + * of the class. It is initialized on construction of the class. + */ + MessageQueueIF* reqQueue = nullptr; + /** + * The internal error reporter which will be used if there are issues sending telemetry. + * If this is not set, and the TM send or store helpers are initialized with the PSB, + * the class will attempt to find a suitable global object with the ID + * @objects::INTERNAL_ERROR_REPORTER + */ + InternalErrorReporterIF* errReporter = nullptr; + /** + * The storage manager which will be used to retrieve any TC packet using the store ID + * received via a message. If this is not set, the class will attempt to find a suitable global + * object with the ID @objects::TC_STORE + */ + StorageManagerIF* tcPool = nullptr; + /** + * Usually, packets are sent via a dedicated PUS distributor. If this distributor is set, + * the PUS service will register itself there. Otherwise, the base class will try to find + * a suitable global distributor with the static ID @PusServiceBase::pusDistributor and + * register itself at that object. + */ + PusDistributorIF* pusDistributor = nullptr; + TimeWriterIF* timeStamper = nullptr; +}; namespace Factory { void setStaticFrameworkObjectIds(); @@ -35,26 +96,59 @@ void setStaticFrameworkObjectIds(); */ class PusServiceBase : public ExecutableObjectIF, public AcceptsTelecommandsIF, - public SystemObject, - public HasReturnvaluesIF { - friend void(Factory::setStaticFrameworkObjectIds)(); + public SystemObject { + friend void Factory::setStaticFrameworkObjectIds(); public: + /** + * This constant sets the maximum number of packets accepted per call. + * Remember that one packet must be completely handled in one + * #handleRequest call. + */ + static constexpr uint8_t PUS_SERVICE_MAX_RECEPTION = 10; + static constexpr uint8_t PSB_DEFAULT_QUEUE_DEPTH = 10; + /** * @brief The passed values are set, but inter-object initialization is * done in the initialize method. - * @param setObjectId - * The system object identifier of this Service instance. - * @param setApid - * The APID the Service is instantiated for. - * @param setServiceId - * The Service Identifier as specified in ECSS PUS. + * @param params All configuration parameters for the PUS Service Base */ - PusServiceBase(object_id_t setObjectId, uint16_t setApid, uint8_t setServiceId); + explicit PusServiceBase(PsbParams params); /** * The destructor is empty. */ - virtual ~PusServiceBase(); + ~PusServiceBase() override; + + ReturnValue_t registerService(PusDistributorIF& distributor); + /** + * Set the request queue which is used to receive requests. If none is set, the initialize + * function will create one + * @param reqQueue + */ + void setRequestQueue(MessageQueueIF& reqQueue); + void setTmReceiver(AcceptsTelemetryIF& tmReceiver); + void setTcPool(StorageManagerIF& tcStore); + void setVerificationReporter(VerificationReporterIF& reporter); + void setErrorReporter(InternalErrorReporterIF& errReporter); + + /** + * Helper methods if the implementing class wants to send telemetry + * @param tmSendHelper + */ + ReturnValue_t initializeTmSendHelper(TmSendHelper& tmSendHelper); + /** + * Helper methods if the implementing class wants to store telemetry. It will set the correct APID + * and it will also attempt to set a valid time stamper. If the manually specified time stamper is + * null, it will attempt to find a suitable one using @objects::TIME_STAMPER + * @param tmSendHelper + */ + ReturnValue_t initializeTmStoreHelper(TmStoreHelper& tmStoreHelper) const; + /** + * Helper methods if the implementing class wants to both send and store telemetry + * @param tmSendHelper + */ + ReturnValue_t initializeTmHelpers(TmSendHelper& tmSendHelper, TmStoreHelper& tmStoreHelper); + /** * @brief The handleRequest method shall handle any kind of Telecommand * Request immediately. @@ -76,14 +170,14 @@ class PusServiceBase : public ExecutableObjectIF, * * @return The returned status_code is directly taken as main error code * in the Verification Report. - * On success, RETURN_OK shall be returned. + * On success, returnvalue::OK shall be returned. */ virtual ReturnValue_t handleRequest(uint8_t subservice) = 0; /** * In performService, implementations can handle periodic, * non-TC-triggered activities. * The performService method is always called. - * @return Currently, everything other that RETURN_OK only triggers + * @return Currently, everything other that returnvalue::OK only triggers * diagnostic output. */ virtual ReturnValue_t performService() = 0; @@ -93,16 +187,16 @@ class PusServiceBase : public ExecutableObjectIF, * completion verification messages and deletes * the TC requests afterwards. * performService is always executed afterwards. - * @return @c RETURN_OK if the periodic performService was successful. - * @c RETURN_FAILED else. + * @return @c returnvalue::OK if the periodic performService was successful. + * @c returnvalue::FAILED else. */ ReturnValue_t performOperation(uint8_t opCode) override; - virtual uint16_t getIdentifier() override; - MessageQueueId_t getRequestQueue() override; - virtual ReturnValue_t initialize() override; + uint32_t getIdentifier() const override; + MessageQueueId_t getRequestQueue() const override; + ReturnValue_t initialize() override; - virtual void setTaskIF(PeriodicTaskIF* taskHandle) override; - virtual ReturnValue_t initializeAfterTaskCreation() override; + void setTaskIF(PeriodicTaskIF* taskHandle) override; + [[nodiscard]] const char* getName() const override; protected: /** @@ -111,14 +205,7 @@ class PusServiceBase : public ExecutableObjectIF, * Will be set by setTaskIF(), which is called on task creation. */ PeriodicTaskIF* taskHandle = nullptr; - /** - * The APID of this instance of the Service. - */ - uint16_t apid; - /** - * The Service Identifier. - */ - uint8_t serviceId; + /** * One of two error parameters for additional error information. */ @@ -127,34 +214,18 @@ class PusServiceBase : public ExecutableObjectIF, * One of two error parameters for additional error information. */ uint32_t errorParameter2 = 0; - /** - * This is a complete instance of the telecommand reception queue - * of the class. It is initialized on construction of the class. - */ - MessageQueueIF* requestQueue = nullptr; - /** - * An instance of the VerificationReporter class, that simplifies - * sending any kind of verification message to the TC Verification Service. - */ - VerificationReporter verifyReporter; + PsbParams psbParams; /** * The current Telecommand to be processed. * It is deleted after handleRequest was executed. */ - TcPacketStoredPus currentPacket; + PusTcReader currentPacket; + bool ownedQueue = true; - static object_id_t packetSource; - - static object_id_t packetDestination; + static object_id_t PACKET_DESTINATION; + static object_id_t PUS_DISTRIBUTOR; private: - /** - * This constant sets the maximum number of packets accepted per call. - * Remember that one packet must be completely handled in one - * #handleRequest call. - */ - static const uint8_t PUS_SERVICE_MAX_RECEPTION = 10; - void handleRequestQueue(); }; diff --git a/src/fsfw/tmtcservices/PusVerificationReport.h b/src/fsfw/tmtcservices/PusVerificationReport.h index 60c01d55..f0cad337 100644 --- a/src/fsfw/tmtcservices/PusVerificationReport.h +++ b/src/fsfw/tmtcservices/PusVerificationReport.h @@ -3,8 +3,8 @@ #include "VerificationCodes.h" #include "fsfw/ipc/MessageQueueMessage.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" -#include "fsfw/tmtcpacket/pus/tc/TcPacketPusBase.h" +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/tmtcpacket/pus/tc/PusTcReader.h" class PusVerificationMessage : public MessageQueueMessage { private: diff --git a/src/fsfw/tmtcservices/SourceSequenceCounter.h b/src/fsfw/tmtcservices/SourceSequenceCounter.h index e981a945..f530b444 100644 --- a/src/fsfw/tmtcservices/SourceSequenceCounter.h +++ b/src/fsfw/tmtcservices/SourceSequenceCounter.h @@ -1,24 +1,32 @@ #ifndef FSFW_TMTCSERVICES_SOURCESEQUENCECOUNTER_H_ #define FSFW_TMTCSERVICES_SOURCESEQUENCECOUNTER_H_ -#include "../tmtcpacket/SpacePacketBase.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" class SourceSequenceCounter { private: - uint16_t sequenceCount; + uint16_t sequenceCount = 0; public: - SourceSequenceCounter() : sequenceCount(0) {} - void increment() { - sequenceCount = (sequenceCount + 1) % (SpacePacketBase::LIMIT_SEQUENCE_COUNT); + SourceSequenceCounter(uint16_t initialSequenceCount = 0) : sequenceCount(initialSequenceCount) {} + void increment() { sequenceCount = (sequenceCount + 1) % (ccsds::LIMIT_SEQUENCE_COUNT); } + void decrement() { sequenceCount = (sequenceCount - 1) % (ccsds::LIMIT_SEQUENCE_COUNT); } + uint16_t get() const { return this->sequenceCount; } + void reset(uint16_t toValue = 0) { sequenceCount = toValue % (ccsds::LIMIT_SEQUENCE_COUNT); } + SourceSequenceCounter& operator++(int) { + this->increment(); + return *this; } - void decrement() { - sequenceCount = (sequenceCount - 1) % (SpacePacketBase::LIMIT_SEQUENCE_COUNT); + SourceSequenceCounter& operator--(int) { + this->decrement(); + return *this; } - uint16_t get() { return this->sequenceCount; } - void reset(uint16_t toValue = 0) { - sequenceCount = toValue % (SpacePacketBase::LIMIT_SEQUENCE_COUNT); + SourceSequenceCounter& operator=(const uint16_t& newCount) { + sequenceCount = newCount; + return *this; } + + operator uint16_t() { return this->get(); } }; #endif /* FSFW_TMTCSERVICES_SOURCESEQUENCECOUNTER_H_ */ diff --git a/src/fsfw/tmtcservices/SpacePacketParser.cpp b/src/fsfw/tmtcservices/SpacePacketParser.cpp index 4c10ae9e..75db7a4e 100644 --- a/src/fsfw/tmtcservices/SpacePacketParser.cpp +++ b/src/fsfw/tmtcservices/SpacePacketParser.cpp @@ -6,55 +6,44 @@ SpacePacketParser::SpacePacketParser(std::vector validPacketIds) : validPacketIds(validPacketIds) {} -ReturnValue_t SpacePacketParser::parseSpacePackets(const uint8_t* buffer, const size_t maxSize, - size_t& startIndex, size_t& foundSize) { - const uint8_t** tempPtr = &buffer; - size_t readLen = 0; - return parseSpacePackets(tempPtr, maxSize, startIndex, foundSize, readLen); -} - ReturnValue_t SpacePacketParser::parseSpacePackets(const uint8_t** buffer, const size_t maxSize, - size_t& startIndex, size_t& foundSize, - size_t& readLen) { - if (buffer == nullptr or maxSize < 5) { + FoundPacketInfo& packetInfo) { + if (buffer == nullptr or nextStartIdx > maxSize) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "SpacePacketParser::parseSpacePackets: Frame invalid" << std::endl; #else sif::printWarning("SpacePacketParser::parseSpacePackets: Frame invalid\n"); #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } const uint8_t* bufPtr = *buffer; - auto verifyLengthField = [&](size_t idx) { - uint16_t lengthField = bufPtr[idx + 4] << 8 | bufPtr[idx + 5]; + auto verifyLengthField = [&](size_t localIdx) { + uint16_t lengthField = (bufPtr[localIdx + 4] << 8) | bufPtr[localIdx + 5]; size_t packetSize = lengthField + 7; - startIndex = idx; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - if (lengthField == 0) { - // Skip whole header for now - foundSize = 6; - result = NO_PACKET_FOUND; - } else if (packetSize + idx > maxSize) { + ReturnValue_t result = returnvalue::OK; + if (packetSize + localIdx + amountRead > maxSize) { // Don't increment buffer and read length here, user has to decide what to do - foundSize = packetSize; + packetInfo.sizeFound = packetSize; return SPLIT_PACKET; } else { - foundSize = packetSize; + packetInfo.sizeFound = packetSize; } - *buffer += foundSize; - readLen += idx + foundSize; + *buffer += packetInfo.sizeFound; + packetInfo.startIdx = localIdx + amountRead; + nextStartIdx = localIdx + amountRead + packetInfo.sizeFound; + amountRead = nextStartIdx; return result; }; size_t idx = 0; // Space packet ID as start marker if (validPacketIds.size() > 0) { - while (idx < maxSize - 5) { - uint16_t currentPacketId = bufPtr[idx] << 8 | bufPtr[idx + 1]; + while (idx + amountRead < maxSize - 5) { + uint16_t currentPacketId = (bufPtr[idx] << 8) | bufPtr[idx + 1]; if (std::find(validPacketIds.begin(), validPacketIds.end(), currentPacketId) != validPacketIds.end()) { - if (idx + 5 >= maxSize) { + if (idx + amountRead >= maxSize - 5) { return SPLIT_PACKET; } return verifyLengthField(idx); @@ -62,10 +51,10 @@ ReturnValue_t SpacePacketParser::parseSpacePackets(const uint8_t** buffer, const idx++; } } - startIndex = 0; - foundSize = maxSize; - *buffer += foundSize; - readLen += foundSize; + nextStartIdx = maxSize; + packetInfo.sizeFound = maxSize; + amountRead = maxSize; + *buffer += maxSize; return NO_PACKET_FOUND; } // Assume that the user verified a valid start of a space packet diff --git a/src/fsfw/tmtcservices/SpacePacketParser.h b/src/fsfw/tmtcservices/SpacePacketParser.h index f0a9e8e2..ea0a2feb 100644 --- a/src/fsfw/tmtcservices/SpacePacketParser.h +++ b/src/fsfw/tmtcservices/SpacePacketParser.h @@ -17,9 +17,10 @@ */ class SpacePacketParser { public: - //! The first entry is the index inside the buffer while the second index - //! is the size of the PUS packet starting at that index. - using IndexSizePair = std::pair; + struct FoundPacketInfo { + size_t startIdx = 0; + size_t sizeFound = 0; + }; static constexpr uint8_t INTERFACE_ID = CLASS_ID::SPACE_PACKET_PARSER; static constexpr ReturnValue_t NO_PACKET_FOUND = MAKE_RETURN_CODE(0x00); @@ -36,44 +37,30 @@ class SpacePacketParser { SpacePacketParser(std::vector validPacketIds); /** - * Parse a given frame for space packets but also increment the given buffer and assign the - * total number of bytes read so far + * Parse a given frame for space packets but also increments the given buffer. * @param buffer Parser will look for space packets in this buffer * @param maxSize Maximum size of the buffer - * @param startIndex Start index of a found space packet - * @param foundSize Found size of the space packet - * @param readLen Length read so far. This value is incremented by the number of parsed - * bytes which also includes the size of a found packet - * -@c NO_PACKET_FOUND if no packet was found in the given buffer or the length field is - * invalid. foundSize will be set to the size of the space packet header. buffer and - * readLen will be incremented accordingly. - * -@c SPLIT_PACKET if a packet was found but the detected size exceeds maxSize. foundSize - * will be set to the detected packet size and startIndex will be set to the start of the - * detected packet. buffer and read length will not be incremented but the found length - * will be assigned. - * -@c RETURN_OK if a packet was found + * @param packetInfo Information about packets found. + * -@c NO_PACKET_FOUND if no packet was found in the given buffer + * -@c SPLIT_PACKET if a packet was found but the detected size exceeds maxSize. packetInfo + * will contain the detected packet size and start index. + * -@c returnvalue::OK if a packet was found. Packet size and start index will be set in + * packetInfo */ - ReturnValue_t parseSpacePackets(const uint8_t** buffer, const size_t maxSize, size_t& startIndex, - size_t& foundSize, size_t& readLen); + ReturnValue_t parseSpacePackets(const uint8_t** buffer, const size_t maxSize, + FoundPacketInfo& packetInfo); - /** - * Parse a given frame for space packets - * @param buffer Parser will look for space packets in this buffer - * @param maxSize Maximum size of the buffer - * @param startIndex Start index of a found space packet - * @param foundSize Found size of the space packet - * -@c NO_PACKET_FOUND if no packet was found in the given buffer or the length field is - * invalid. foundSize will be set to the size of the space packet header - * -@c SPLIT_PACKET if a packet was found but the detected size exceeds maxSize. foundSize - * will be set to the detected packet size and startIndex will be set to the start of the - * detected packet - * -@c RETURN_OK if a packet was found - */ - ReturnValue_t parseSpacePackets(const uint8_t* buffer, const size_t maxSize, size_t& startIndex, - size_t& foundSize); + size_t getAmountRead() { return amountRead; } + + void reset() { + nextStartIdx = 0; + amountRead = 0; + } private: std::vector validPacketIds; + size_t nextStartIdx = 0; + size_t amountRead = 0; }; #endif /* FRAMEWORK_TMTCSERVICES_PUSPARSER_H_ */ diff --git a/src/fsfw/tmtcservices/TmSendHelper.cpp b/src/fsfw/tmtcservices/TmSendHelper.cpp new file mode 100644 index 00000000..210ed5f6 --- /dev/null +++ b/src/fsfw/tmtcservices/TmSendHelper.cpp @@ -0,0 +1,61 @@ +#include "TmSendHelper.h" + +#include "fsfw/ipc/MessageQueueSenderIF.h" + +TmSendHelper::TmSendHelper() = default; + +TmSendHelper::TmSendHelper(MessageQueueIF &queue, InternalErrorReporterIF &reporter, + MessageQueueId_t defaultDest) + : queue(&queue), errReporter(&reporter) { + queue.setDefaultDestination(defaultDest); +} + +TmSendHelper::TmSendHelper(MessageQueueIF &queue, InternalErrorReporterIF &reporter) + : queue(&queue), errReporter(&reporter) {} + +TmSendHelper::TmSendHelper(InternalErrorReporterIF &reporter) : errReporter(&reporter) {} + +ReturnValue_t TmSendHelper::sendPacket(const store_address_t &storeId) { + return sendPacket(getDefaultDestination(), storeId); +} + +void TmSendHelper::setDefaultDestination(MessageQueueId_t msgDest) { + if (queue != nullptr) { + queue->setDefaultDestination(msgDest); + }; +} + +void TmSendHelper::setInternalErrorReporter(InternalErrorReporterIF &reporter) { + errReporter = &reporter; +} +void TmSendHelper::setMsgQueue(MessageQueueIF &queue_) { queue = &queue_; } + +ReturnValue_t TmSendHelper::sendPacket(MessageQueueId_t dest, const store_address_t &storeId) { + if (queue == nullptr) { + return returnvalue::FAILED; + } + TmTcMessage message(storeId); + ReturnValue_t result = queue->sendMessage(dest, &message, ignoreFault); + if (result != returnvalue::OK) { + if (errReporter != nullptr and not ignoreFault) { + errReporter->lostTm(); + } + return result; + } + return result; +} + +MessageQueueId_t TmSendHelper::getDefaultDestination() const { + if (queue != nullptr) { + return queue->getDefaultDestination(); + }; + return MessageQueueIF::NO_QUEUE; +} + +bool TmSendHelper::areFaultsIgnored() const { return ignoreFault; } +void TmSendHelper::ignoreFaults() { ignoreFault = true; } +void TmSendHelper::dontIgnoreFaults() { ignoreFault = false; } + +InternalErrorReporterIF *TmSendHelper::getInternalErrorReporter() const { return errReporter; } + +MessageQueueIF *TmSendHelper::getMsgQueue() const { return queue; } diff --git a/src/fsfw/tmtcservices/TmSendHelper.h b/src/fsfw/tmtcservices/TmSendHelper.h new file mode 100644 index 00000000..9fee84c4 --- /dev/null +++ b/src/fsfw/tmtcservices/TmSendHelper.h @@ -0,0 +1,37 @@ +#ifndef FSFW_TMTCPACKET_TMSENDHELPER_H +#define FSFW_TMTCPACKET_TMSENDHELPER_H + +#include "TmTcMessage.h" +#include "fsfw/internalerror/InternalErrorReporterIF.h" +#include "fsfw/ipc/MessageQueueIF.h" +#include "fsfw/ipc/messageQueueDefinitions.h" +#include "fsfw/returnvalues/returnvalue.h" + +class TmSendHelper { + public: + TmSendHelper(); + TmSendHelper(MessageQueueIF& queue, InternalErrorReporterIF& reporter, + MessageQueueId_t tmtcMsgDest); + TmSendHelper(MessageQueueIF& queue, InternalErrorReporterIF& reporter); + explicit TmSendHelper(InternalErrorReporterIF& reporter); + + void setMsgQueue(MessageQueueIF& queue); + [[nodiscard]] MessageQueueIF* getMsgQueue() const; + + void setDefaultDestination(MessageQueueId_t msgDest); + [[nodiscard]] MessageQueueId_t getDefaultDestination() const; + [[nodiscard]] bool areFaultsIgnored() const; + void ignoreFaults(); + void dontIgnoreFaults(); + void setInternalErrorReporter(InternalErrorReporterIF& reporter); + [[nodiscard]] InternalErrorReporterIF* getInternalErrorReporter() const; + ReturnValue_t sendPacket(MessageQueueId_t dest, const store_address_t& storeId); + ReturnValue_t sendPacket(const store_address_t& storeId); + + private: + bool ignoreFault = false; + MessageQueueIF* queue = nullptr; + InternalErrorReporterIF* errReporter = nullptr; +}; + +#endif // FSFW_TMTCPACKET_TMSENDHELPER_H diff --git a/src/fsfw/tmtcservices/TmStoreAndSendHelper.cpp b/src/fsfw/tmtcservices/TmStoreAndSendHelper.cpp new file mode 100644 index 00000000..3057800a --- /dev/null +++ b/src/fsfw/tmtcservices/TmStoreAndSendHelper.cpp @@ -0,0 +1,65 @@ +#include "TmStoreAndSendHelper.h" + +#include "tmHelpers.h" + +TmStoreAndSendWrapper::TmStoreAndSendWrapper(uint8_t defaultService, TmStoreHelper& storeHelper, + TmSendHelper& sendHelper) + : storeHelper(storeHelper), sendHelper(sendHelper), defaultService(defaultService) {} + +/** + * Helper wrapper which stores the TM packet into the store and then sends it. + * @return + * - StorageManagerIF returnvalue if storage fails + * - MessageQueueIF returnvalue if sending fails + */ +ReturnValue_t TmStoreAndSendWrapper::storeAndSendTmPacket() { + ReturnValue_t result = storeHelper.addPacketToStore(); + if (result != returnvalue::OK) { + return result; + } + result = sendHelper.sendPacket(storeHelper.getCurrentAddr()); + if (result != returnvalue::OK) { + if (delOnFailure) { + storeHelper.deletePacket(); + } + return result; + } + if (incrementSendCounter) { + sendCounter++; + } + return result; +} + +ReturnValue_t TmStoreAndSendWrapper::prepareTmPacket(uint8_t subservice, const uint8_t* sourceData, + size_t sourceDataLen) { + ReturnValue_t result = storeHelper.preparePacket(defaultService, subservice, sendCounter); + if (result != returnvalue::OK) { + return result; + } + return storeHelper.setSourceDataRaw(sourceData, sourceDataLen); +} + +ReturnValue_t TmStoreAndSendWrapper::prepareTmPacket( + uint8_t subservice, telemetry::DataWithObjectIdPrefix& dataWithObjectId) { + ReturnValue_t result = storeHelper.preparePacket(defaultService, subservice, sendCounter); + if (result != returnvalue::OK) { + return result; + } + return storeHelper.setSourceDataSerializable(dataWithObjectId); +} + +ReturnValue_t TmStoreAndSendWrapper::prepareTmPacket(uint8_t subservice, SerializeIF& sourceData) { + ReturnValue_t result = storeHelper.preparePacket(defaultService, subservice, sendCounter); + if (result != returnvalue::OK) { + return result; + } + return storeHelper.setSourceDataSerializable(sourceData); +} + +ReturnValue_t TmStoreAndSendWrapper::prepareTmPacket(uint8_t subservice) { + ReturnValue_t result = storeHelper.preparePacket(defaultService, subservice, sendCounter); + if (result != returnvalue::OK) { + return result; + } + return storeHelper.setSourceDataRaw(nullptr, 0); +} diff --git a/src/fsfw/tmtcservices/TmStoreAndSendHelper.h b/src/fsfw/tmtcservices/TmStoreAndSendHelper.h new file mode 100644 index 00000000..eef3a373 --- /dev/null +++ b/src/fsfw/tmtcservices/TmStoreAndSendHelper.h @@ -0,0 +1,60 @@ +#ifndef FSFW_TMTCSERVICES_TMSTOREANDSENDHELPER_H +#define FSFW_TMTCSERVICES_TMSTOREANDSENDHELPER_H + +#include "TmSendHelper.h" +#include "TmStoreHelper.h" +#include "tmHelpers.h" + +/** + * Wrapper class intended to help with PUS TM handling. This wrapper class also caches the current + * packet count and the service ID + */ +class TmStoreAndSendWrapper { + public: + TmStoreAndSendWrapper(uint8_t defaultService, TmStoreHelper& storeHelper, + TmSendHelper& sendHelper); + + /** + * Prepares a TM packet with the given parameters. It will also set the default service. + * @param subservice + * @return + */ + ReturnValue_t prepareTmPacket(uint8_t subservice); + /** + * Prepares a TM packet with the given parameters. It will also set the default service. + * @param subservice Number of subservice + * @param sourceData Custom source data + * @param sourceDataLen Lenght of data in the Packet + */ + ReturnValue_t prepareTmPacket(uint8_t subservice, const uint8_t* sourceData, + size_t sourceDataLen); + + /** + * Prepares a TM packet with the given parameters. It will also set the default service. + * @param subservice Number of subservice + * @param objectId ObjectId is placed before data + * @param data Data to append to the packet + * @param dataLen Length of Data + */ + ReturnValue_t prepareTmPacket(uint8_t subservice, + telemetry::DataWithObjectIdPrefix& dataWithObjectId); + + /** + * Prepares a TM packet with the given parameters. It will also set the default service. + * @param subservice Number of subservice + * @param content This is a pointer to the serialized packet + * @param header Serialize IF header which will be placed before content + */ + ReturnValue_t prepareTmPacket(uint8_t subservice, SerializeIF& sourceData); + + ReturnValue_t storeAndSendTmPacket(); + + bool incrementSendCounter = true; + TmStoreHelper& storeHelper; + TmSendHelper& sendHelper; + bool delOnFailure = true; + uint8_t defaultService = 0; + uint16_t sendCounter = 0; +}; + +#endif // FSFW_TMTCSERVICES_TMSTOREANDSENDHELPER_H diff --git a/src/fsfw/tmtcservices/TmStoreHelper.cpp b/src/fsfw/tmtcservices/TmStoreHelper.cpp new file mode 100644 index 00000000..1c8e0a92 --- /dev/null +++ b/src/fsfw/tmtcservices/TmStoreHelper.cpp @@ -0,0 +1,80 @@ +#include "TmStoreHelper.h" + +#include "TmTcMessage.h" + +TmStoreHelper::TmStoreHelper(uint16_t defaultApid) : tmStore(nullptr) { + creator.setApid(defaultApid); +} + +TmStoreHelper::TmStoreHelper(uint16_t defaultApid, StorageManagerIF& tmStore) : tmStore(&tmStore) { + creator.setApid(defaultApid); +} + +TmStoreHelper::TmStoreHelper(uint16_t defaultApid, StorageManagerIF& tmStore, + TimeWriterIF& timeStamper) + : tmStore(&tmStore) { + creator.setApid(defaultApid); + creator.setTimeStamper(timeStamper); +} + +ReturnValue_t TmStoreHelper::preparePacket(uint8_t service, uint8_t subservice, uint16_t counter) { + creator.setService(service); + creator.setSubservice(subservice); + creator.setMessageTypeCounter(counter); + return returnvalue::OK; +} + +StorageManagerIF* TmStoreHelper::getTmStore() const { return tmStore; } + +void TmStoreHelper::setTmStore(StorageManagerIF& store) { tmStore = &store; } + +const store_address_t& TmStoreHelper::getCurrentAddr() const { return currentAddr; } + +ReturnValue_t TmStoreHelper::deletePacket() { + ReturnValue_t result = tmStore->deleteData(currentAddr); + if (result == returnvalue::OK) { + currentAddr = store_address_t::invalid(); + } + return result; +} + +ReturnValue_t TmStoreHelper::setSourceDataRaw(const uint8_t* data, size_t len) { + return creator.setRawUserData(data, len); +} + +ReturnValue_t TmStoreHelper::setSourceDataSerializable(SerializeIF& serializable) { + return creator.setSerializableUserData(serializable); +} + +ReturnValue_t TmStoreHelper::addPacketToStore() { + creator.updateSpLengthField(); + uint8_t* dataPtr; + ReturnValue_t result = + tmStore->getFreeElement(¤tAddr, creator.getSerializedSize(), &dataPtr); + if (result != returnvalue::OK) { + return result; + } + size_t serLen = 0; + return creator.serialize(&dataPtr, &serLen, creator.getSerializedSize(), + SerializeIF::Endianness::NETWORK); +} + +void TmStoreHelper::setTimeStamper(TimeWriterIF& timeStamper_) { + creator.setTimeStamper(timeStamper_); +} + +void TmStoreHelper::setApid(uint16_t apid) { creator.setApid(apid); } + +PusTmCreator& TmStoreHelper::getCreatorRef() { return creator; } + +TimeWriterIF* TmStoreHelper::getTimeStamper() const { return creator.getTimestamper(); } + +uint16_t TmStoreHelper::getApid() const { return creator.getApid(); } + +void TmStoreHelper::setService(uint8_t service) { creator.setService(service); } + +void TmStoreHelper::setSubservice(uint8_t subservice) { creator.setSubservice(subservice); } + +void TmStoreHelper::disableCrcCalculation() { creator.disableCrcCalculation(); } + +bool TmStoreHelper::crcCalculationEnabled() const { return creator.crcCalculationEnabled(); } diff --git a/src/fsfw/tmtcservices/TmStoreHelper.h b/src/fsfw/tmtcservices/TmStoreHelper.h new file mode 100644 index 00000000..f73d0c8b --- /dev/null +++ b/src/fsfw/tmtcservices/TmStoreHelper.h @@ -0,0 +1,46 @@ +#ifndef FSFW_TMTCSERVICES_STOREHELPER_H +#define FSFW_TMTCSERVICES_STOREHELPER_H + +#include "fsfw/internalerror/InternalErrorReporterIF.h" +#include "fsfw/ipc/MessageQueueMessageIF.h" +#include "fsfw/storagemanager/StorageManagerIF.h" +#include "fsfw/timemanager/TimeWriterIF.h" +#include "fsfw/tmtcpacket/pus/tm/PusTmCreator.h" + +class TmStoreHelper { + public: + explicit TmStoreHelper(uint16_t defaultApid); + TmStoreHelper(uint16_t defaultApid, StorageManagerIF& tmStore); + TmStoreHelper(uint16_t defaultApid, StorageManagerIF& tmStore, TimeWriterIF& timeStamper); + + void disableCrcCalculation(); + [[nodiscard]] bool crcCalculationEnabled() const; + + ReturnValue_t preparePacket(uint8_t service, uint8_t subservice, uint16_t counter); + + PusTmCreator& getCreatorRef(); + + void setTimeStamper(TimeWriterIF& timeStamper); + [[nodiscard]] TimeWriterIF* getTimeStamper() const; + + [[nodiscard]] StorageManagerIF* getTmStore() const; + void setTmStore(StorageManagerIF& store); + + void setApid(uint16_t apid); + [[nodiscard]] uint16_t getApid() const; + + [[nodiscard]] const store_address_t& getCurrentAddr() const; + void setService(uint8_t service); + void setSubservice(uint8_t subservice); + ReturnValue_t setSourceDataRaw(const uint8_t* data, size_t len); + ReturnValue_t setSourceDataSerializable(SerializeIF& serializable); + + ReturnValue_t addPacketToStore(); + ReturnValue_t deletePacket(); + + private: + PusTmCreator creator; + store_address_t currentAddr{}; + StorageManagerIF* tmStore; +}; +#endif // FSFW_TMTCSERVICES_STOREHELPER_H diff --git a/src/fsfw/tmtcservices/TmTcBridge.cpp b/src/fsfw/tmtcservices/TmTcBridge.cpp index 8ea67119..f098103e 100644 --- a/src/fsfw/tmtcservices/TmTcBridge.cpp +++ b/src/fsfw/tmtcservices/TmTcBridge.cpp @@ -7,15 +7,18 @@ #define TMTCBRIDGE_WIRETAPPING 0 -TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId, - object_id_t tcStoreId) +TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination, + uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId) : SystemObject(objectId), + name(name), tmStoreId(tmStoreId), tcStoreId(tcStoreId), tcDestination(tcDestination) { - tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH); + auto mqArgs = MqArgs(objectId, static_cast(this)); + tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue( + msgQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs); } TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); } @@ -23,28 +26,28 @@ TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcRec ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle(uint8_t sentPacketsPerCycle) { if (sentPacketsPerCycle <= LIMIT_STORED_DATA_SENT_PER_CYCLE) { this->sentPacketsPerCycle = sentPacketsPerCycle; - return RETURN_OK; + return returnvalue::OK; } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "TmTcBridge::setNumberOfSentPacketsPerCycle: Number of " << "packets sent per cycle exceeds limits. " << "Keeping default value." << std::endl; #endif - return RETURN_FAILED; + return returnvalue::FAILED; } } -ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored) { +ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored) { if (maxNumberOfPacketsStored <= LIMIT_DOWNLINK_PACKETS_STORED) { this->maxNumberOfPacketsStored = maxNumberOfPacketsStored; - return RETURN_OK; + return returnvalue::OK; } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "TmTcBridge::setMaxNumberOfPacketsStored: Number of " << "packets stored exceeds limits. " << "Keeping default value." << std::endl; #endif - return RETURN_FAILED; + return returnvalue::FAILED; } } @@ -67,8 +70,7 @@ ReturnValue_t TmTcBridge::initialize() { #endif return ObjectManagerIF::CHILD_INIT_FAILED; } - AcceptsTelecommandsIF* tcDistributor = - ObjectManager::instance()->get(tcDestination); + auto* tcDistributor = ObjectManager::instance()->get(tcDestination); if (tcDistributor == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "TmTcBridge::initialize: TC Distributor invalid" << std::endl; @@ -79,20 +81,20 @@ ReturnValue_t TmTcBridge::initialize() { tmFifo = new DynamicFIFO(maxNumberOfPacketsStored); tmTcReceptionQueue->setDefaultDestination(tcDistributor->getRequestQueue()); - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t TmTcBridge::performOperation(uint8_t operationCode) { ReturnValue_t result; result = handleTc(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::debug << "TmTcBridge::performOperation: " << "Error handling TCs" << std::endl; #endif } result = handleTm(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::debug << "TmTcBridge::performOperation: " << "Error handling TMs" << std::endl; @@ -101,12 +103,12 @@ ReturnValue_t TmTcBridge::performOperation(uint8_t operationCode) { return result; } -ReturnValue_t TmTcBridge::handleTc() { return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t TmTcBridge::handleTc() { return returnvalue::OK; } ReturnValue_t TmTcBridge::handleTm() { - ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t status = returnvalue::OK; ReturnValue_t result = handleTmQueue(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "TmTcBridge::handleTm: Error handling TM queue with error code 0x" << std::hex << result << std::dec << "!" << std::endl; @@ -116,7 +118,7 @@ ReturnValue_t TmTcBridge::handleTm() { if (tmStored and communicationLinkUp and (packetSentCounter < sentPacketsPerCycle)) { result = handleStoredTm(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "TmTcBridge::handleTm: Error handling stored TMs!" << std::endl; #endif @@ -131,10 +133,9 @@ ReturnValue_t TmTcBridge::handleTmQueue() { TmTcMessage message; const uint8_t* data = nullptr; size_t size = 0; - ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t status = returnvalue::OK; for (ReturnValue_t result = tmTcReceptionQueue->receiveMessage(&message); - result == HasReturnvaluesIF::RETURN_OK; - result = tmTcReceptionQueue->receiveMessage(&message)) { + result == returnvalue::OK; result = tmTcReceptionQueue->receiveMessage(&message)) { #if FSFW_VERBOSE_LEVEL >= 3 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "Sent packet counter: " << static_cast(packetSentCounter) << std::endl; @@ -144,59 +145,66 @@ ReturnValue_t TmTcBridge::handleTmQueue() { #endif /* FSFW_VERBOSE_LEVEL >= 3 */ if (communicationLinkUp == false or packetSentCounter >= sentPacketsPerCycle) { - storeDownlinkData(&message); + ReturnValue_t result = storeDownlinkData(&message); + if (result != returnvalue::OK) { + tmStore->deleteData(message.getStorageId()); + } continue; } result = tmStore->getData(message.getStorageId(), &data, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { status = result; + tmStore->deleteData(message.getStorageId()); continue; } result = sendTm(data, size); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { status = result; } else { - tmStore->deleteData(message.getStorageId()); packetSentCounter++; } + tmStore->deleteData(message.getStorageId()); } return status; } ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage* message) { - store_address_t storeId = 0; + store_address_t storeId; if (tmFifo == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } 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 = false; + } if (overwriteOld) { tmFifo->retrieve(&storeId); tmStore->deleteData(storeId); } else { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } storeId = message->getStorageId(); tmFifo->insert(storeId); tmStored = true; - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t TmTcBridge::handleStoredTm() { - ReturnValue_t status = RETURN_OK; + ReturnValue_t status = returnvalue::OK; while (not tmFifo->empty() and packetSentCounter < sentPacketsPerCycle) { #if FSFW_CPP_OSTREAM_ENABLED == 1 // sif::info << "TMTC Bridge: Sending stored TM data. There are " @@ -208,12 +216,12 @@ ReturnValue_t TmTcBridge::handleStoredTm() { size_t size = 0; tmFifo->retrieve(&storeId); ReturnValue_t result = tmStore->getData(storeId, &data, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { status = result; } result = sendTm(data, size); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "TMTC Bridge: Could not send stored downlink data" << std::endl; #endif @@ -222,6 +230,7 @@ ReturnValue_t TmTcBridge::handleStoredTm() { packetSentCounter++; if (tmFifo->empty()) { + warningSwitch = true; tmStored = false; } tmStore->deleteData(storeId); @@ -241,20 +250,22 @@ void TmTcBridge::registerCommDisconnect() { } } -MessageQueueId_t TmTcBridge::getReportReceptionQueue(uint8_t virtualChannel) { +MessageQueueId_t TmTcBridge::getReportReceptionQueue(uint8_t virtualChannel) const { return tmTcReceptionQueue->getId(); } void TmTcBridge::printData(uint8_t* data, size_t dataLen) { arrayprinter::print(data, dataLen); } -uint16_t TmTcBridge::getIdentifier() { +uint32_t TmTcBridge::getIdentifier() const { // This is no PUS service, so we just return 0 return 0; } -MessageQueueId_t TmTcBridge::getRequestQueue() { +MessageQueueId_t TmTcBridge::getRequestQueue() const { // Default implementation: Relay TC messages to TC distributor directly. return tmTcReceptionQueue->getDefaultDestination(); } void TmTcBridge::setFifoToOverwriteOldData(bool overwriteOld) { this->overwriteOld = overwriteOld; } + +const char* TmTcBridge::getName() const { return name; } diff --git a/src/fsfw/tmtcservices/TmTcBridge.h b/src/fsfw/tmtcservices/TmTcBridge.h index 237f1f3e..858793cc 100644 --- a/src/fsfw/tmtcservices/TmTcBridge.h +++ b/src/fsfw/tmtcservices/TmTcBridge.h @@ -13,26 +13,24 @@ class TmTcBridge : public AcceptsTelemetryIF, public AcceptsTelecommandsIF, public ExecutableObjectIF, - public HasReturnvaluesIF, public SystemObject { public: - static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20; static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15; - static constexpr uint8_t LIMIT_DOWNLINK_PACKETS_STORED = 200; + static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 500; static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5; static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10; - TmTcBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId, - object_id_t tcStoreId); - virtual ~TmTcBridge(); + TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination, + uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId); + ~TmTcBridge() override; /** * Set number of packets sent per performOperation().Please note that this * value must be smaller than MAX_STORED_DATA_SENT_PER_CYCLE * @param sentPacketsPerCycle - * @return -@c RETURN_OK if value was set successfully - * -@c RETURN_FAILED otherwise, stored value stays the same + * @return -@c returnvalue::OK if value was set successfully + * -@c returnvalue::FAILED otherwise, stored value stays the same */ ReturnValue_t setNumberOfSentPacketsPerCycle(uint8_t sentPacketsPerCycle); @@ -40,10 +38,10 @@ class TmTcBridge : public AcceptsTelemetryIF, * Set number of packets sent per performOperation().Please note that this * value must be smaller than MAX_DOWNLINK_PACKETS_STORED * @param sentPacketsPerCycle - * @return -@c RETURN_OK if value was set successfully - * -@c RETURN_FAILED otherwise, stored value stays the same + * @return -@c returnvalue::OK if value was set successfully + * -@c returnvalue::FAILED otherwise, stored value stays the same */ - ReturnValue_t setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored); + ReturnValue_t setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored); /** * This will set up the bridge to overwrite old data in the FIFO. @@ -58,21 +56,24 @@ class TmTcBridge : public AcceptsTelemetryIF, * Initializes necessary FSFW components for the TMTC Bridge * @return */ - virtual ReturnValue_t initialize() override; + ReturnValue_t initialize() override; /** * @brief Handles TMTC reception */ - virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; + ReturnValue_t performOperation(uint8_t operationCode = 0) override; /** AcceptsTelemetryIF override */ - virtual MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) override; + MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override; /** AcceptsTelecommandsIF override */ - virtual uint16_t getIdentifier() override; - virtual MessageQueueId_t getRequestQueue() override; + uint32_t getIdentifier() const override; + MessageQueueId_t getRequestQueue() const override; + const char* getName() const override; protected: + const char* name = ""; + //! Cached for initialize function. object_id_t tmStoreId = objects::NO_OBJECT; object_id_t tcStoreId = objects::NO_OBJECT; @@ -89,6 +90,7 @@ class TmTcBridge : public AcceptsTelemetryIF, //! by default, so telemetry will be handled immediately. bool communicationLinkUp = true; bool tmStored = false; + bool warningSwitch = true; bool overwriteOld = true; uint8_t packetSentCounter = 0; @@ -150,7 +152,7 @@ class TmTcBridge : public AcceptsTelemetryIF, */ DynamicFIFO* tmFifo = nullptr; uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE; - uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED; + unsigned int maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED; }; #endif /* FSFW_TMTCSERVICES_TMTCBRIDGE_H_ */ diff --git a/src/fsfw/tmtcservices/TmTcMessage.cpp b/src/fsfw/tmtcservices/TmTcMessage.cpp index ca76760f..bd071b5b 100644 --- a/src/fsfw/tmtcservices/TmTcMessage.cpp +++ b/src/fsfw/tmtcservices/TmTcMessage.cpp @@ -4,7 +4,7 @@ TmTcMessage::TmTcMessage() { this->messageSize += sizeof(store_address_t); } -TmTcMessage::~TmTcMessage() {} +TmTcMessage::~TmTcMessage() = default; store_address_t TmTcMessage::getStorageId() { store_address_t temp_id; @@ -18,9 +18,9 @@ TmTcMessage::TmTcMessage(store_address_t storeId) { } size_t TmTcMessage::getMinimumMessageSize() const { - return this->HEADER_SIZE + sizeof(store_address_t); + return TmTcMessage::HEADER_SIZE + sizeof(store_address_t); } void TmTcMessage::setStorageId(store_address_t storeId) { - memcpy(this->getData(), &storeId, sizeof(store_address_t)); + std::memcpy(this->getData(), &storeId, sizeof(store_address_t)); } diff --git a/src/fsfw/tmtcservices/TmTcMessage.h b/src/fsfw/tmtcservices/TmTcMessage.h index a0f67894..3fba6d7a 100644 --- a/src/fsfw/tmtcservices/TmTcMessage.h +++ b/src/fsfw/tmtcservices/TmTcMessage.h @@ -18,7 +18,7 @@ class TmTcMessage : public MessageQueueMessage { * @brief This call always returns the same fixed size of the message. * @return Returns HEADER_SIZE + @c sizeof(store_address_t). */ - size_t getMinimumMessageSize() const override; + [[nodiscard]] size_t getMinimumMessageSize() const override; public: /** @@ -30,11 +30,11 @@ class TmTcMessage : public MessageQueueMessage { * into the message. * @param packet_id The packet id to put into the message. */ - TmTcMessage(store_address_t packetId); + explicit TmTcMessage(store_address_t packetId); /** * @brief The class's destructor is empty. */ - ~TmTcMessage(); + ~TmTcMessage() override; /** * @brief This getter returns the packet id in the correct format. * @return Returns the packet id. diff --git a/src/fsfw/tmtcservices/VerificationCodes.h b/src/fsfw/tmtcservices/VerificationCodes.h index 73edbc1d..479074eb 100644 --- a/src/fsfw/tmtcservices/VerificationCodes.h +++ b/src/fsfw/tmtcservices/VerificationCodes.h @@ -1,9 +1,11 @@ #ifndef VERIFICATIONCODES_H_ #define VERIFICATIONCODES_H_ -namespace tc_verification { +#include -enum verification_flags { +namespace tcverif { + +enum VerificationFlags : uint8_t { NONE = 0b0000, ACCEPTANCE = 0b0001, START = 0b0010, @@ -11,7 +13,7 @@ enum verification_flags { COMPLETION = 0b1000 }; -enum subservice_ids { +enum Subservices : uint8_t { NOTHING_TO_REPORT = 0, ACCEPTANCE_SUCCESS = 1, ACCEPTANCE_FAILURE = 2, @@ -23,6 +25,6 @@ enum subservice_ids { COMPLETION_FAILURE = 8, }; -} // namespace tc_verification +} // namespace tcverif #endif /* VERIFICATIONCODES_H_ */ diff --git a/src/fsfw/tmtcservices/VerificationReporter.cpp b/src/fsfw/tmtcservices/VerificationReporter.cpp index 9d06adc4..1d229183 100644 --- a/src/fsfw/tmtcservices/VerificationReporter.cpp +++ b/src/fsfw/tmtcservices/VerificationReporter.cpp @@ -1,112 +1,71 @@ #include "fsfw/tmtcservices/VerificationReporter.h" -#include "fsfw/ipc/MessageQueueIF.h" -#include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/objectmanager/frameworkObjects.h" +#include "fsfw/objectmanager.h" #include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tmtcservices/AcceptsVerifyMessageIF.h" #include "fsfw/tmtcservices/PusVerificationReport.h" -object_id_t VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION; +object_id_t VerificationReporter::DEFAULT_RECEIVER = objects::PUS_SERVICE_1_VERIFICATION; +object_id_t VerificationReporter::DEFAULT_REPORTER = objects::VERIFICATION_REPORTER; -VerificationReporter::VerificationReporter() : acknowledgeQueue(MessageQueueIF::NO_QUEUE) {} - -VerificationReporter::~VerificationReporter() {} - -void VerificationReporter::sendSuccessReport(uint8_t set_report_id, TcPacketPusBase* currentPacket, - uint8_t set_step) { - if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) { - this->initialize(); +VerificationReporter::VerificationReporter(object_id_t objectId, AcceptsVerifyMessageIF* receiver) + : SystemObject(objectId) { + if (receiver != nullptr) { + acknowledgeQueue = receiver->getVerificationQueue(); } - if (currentPacket == nullptr) { - return; - } - PusVerificationMessage message(set_report_id, currentPacket->getAcknowledgeFlags(), - currentPacket->getPacketId(), - currentPacket->getPacketSequenceControl(), 0, set_step); +} + +VerificationReporter::~VerificationReporter() = default; + +void VerificationReporter::setReceiver(AcceptsVerifyMessageIF& receiver) { + acknowledgeQueue = receiver.getVerificationQueue(); +} + +ReturnValue_t VerificationReporter::sendFailureReport(VerifFailureParams params) { + PusVerificationMessage message(params.reportId, params.ackFlags, params.tcPacketId, params.tcPsc, + params.errorCode, params.step, params.errorParam1, + params.errorParam2); ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); - if (status != HasReturnvaluesIF::RETURN_OK) { + if (status != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "VerificationReporter::sendSuccessReport: Error writing " << "to queue. Code: " << std::hex << status << std::dec << std::endl; #endif } + return status; } -void VerificationReporter::sendSuccessReport(uint8_t set_report_id, uint8_t ackFlags, - uint16_t tcPacketId, uint16_t tcSequenceControl, - uint8_t set_step) { - if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) { - this->initialize(); - } - PusVerificationMessage message(set_report_id, ackFlags, tcPacketId, tcSequenceControl, 0, - set_step); +ReturnValue_t VerificationReporter::sendSuccessReport(VerifSuccessParams params) { + PusVerificationMessage message(params.reportId, params.ackFlags, params.tcPacketId, params.tcPsc, + returnvalue::OK, params.step); ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); - if (status != HasReturnvaluesIF::RETURN_OK) { + if (status != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "VerificationReporter::sendSuccessReport: Error writing " << "to queue. Code: " << std::hex << status << std::dec << std::endl; #endif } + return status; } -void VerificationReporter::sendFailureReport(uint8_t report_id, TcPacketPusBase* currentPacket, - ReturnValue_t error_code, uint8_t step, - uint32_t parameter1, uint32_t parameter2) { +ReturnValue_t VerificationReporter::initialize() { if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) { - this->initialize(); - } - if (currentPacket == nullptr) { - return; - } - PusVerificationMessage message( - report_id, currentPacket->getAcknowledgeFlags(), currentPacket->getPacketId(), - currentPacket->getPacketSequenceControl(), error_code, step, parameter1, parameter2); - ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); - if (status != HasReturnvaluesIF::RETURN_OK) { + auto* receiver = ObjectManager::instance()->get(DEFAULT_RECEIVER); + if (receiver != nullptr) { + acknowledgeQueue = receiver->getVerificationQueue(); + } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "VerificationReporter::sendFailureReport: Error writing " - << "to queue. Code: " << std::hex << "0x" << status << std::dec << std::endl; + sif::error + << "Could not find a suitable verification message receiver. Please ensure that it is set" + " via the constructor or creating a global one with the ID " + "VerificationReporter::DEFAULT_RECEIVER" + << std::endl; +#else + sif::printError( + "Could not find a suitable verification message receiver. Please ensure " + "that it is set via the constructor or creating a global one with the ID " + "VerificationReporter::DEFAULT_RECEIVER\n"); #endif + } } -} - -void VerificationReporter::sendFailureReport(uint8_t report_id, uint8_t ackFlags, - uint16_t tcPacketId, uint16_t tcSequenceControl, - ReturnValue_t error_code, uint8_t step, - uint32_t parameter1, uint32_t parameter2) { - if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) { - this->initialize(); - } - PusVerificationMessage message(report_id, ackFlags, tcPacketId, tcSequenceControl, error_code, - step, parameter1, parameter2); - ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); - if (status != HasReturnvaluesIF::RETURN_OK) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "VerificationReporter::sendFailureReport: Error writing " - << "to queue. Code: " << std::hex << "0x" << status << std::dec << std::endl; -#endif - } -} - -void VerificationReporter::initialize() { - if (messageReceiver == objects::NO_OBJECT) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "VerificationReporter::initialize: Verification message" - " receiver object ID not set yet in Factory!" - << std::endl; -#endif - return; - } - AcceptsVerifyMessageIF* temp = - ObjectManager::instance()->get(messageReceiver); - if (temp == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "VerificationReporter::initialize: Message " - << "receiver invalid. Make sure it is set up properly and " - << "implementsAcceptsVerifyMessageIF" << std::endl; -#endif - return; - } - this->acknowledgeQueue = temp->getVerificationQueue(); + return SystemObject::initialize(); } diff --git a/src/fsfw/tmtcservices/VerificationReporter.h b/src/fsfw/tmtcservices/VerificationReporter.h index c29afd60..f6152614 100644 --- a/src/fsfw/tmtcservices/VerificationReporter.h +++ b/src/fsfw/tmtcservices/VerificationReporter.h @@ -2,7 +2,11 @@ #define FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_ #include "PusVerificationReport.h" +#include "VerificationReporterIF.h" #include "fsfw/objectmanager/ObjectManagerIF.h" +#include "fsfw/objectmanager/SystemObject.h" +#include "fsfw/tmtcpacket/pus/tc/PusTcCreator.h" +#include "fsfw/tmtcservices/AcceptsVerifyMessageIF.h" namespace Factory { void setStaticFrameworkObjectIds(); @@ -19,30 +23,25 @@ void setStaticFrameworkObjectIds(); * to the PUS standard. * */ -class VerificationReporter { - friend void(Factory::setStaticFrameworkObjectIds)(); +class VerificationReporter : public SystemObject, public VerificationReporterIF { + friend void Factory::setStaticFrameworkObjectIds(); public: - VerificationReporter(); - virtual ~VerificationReporter(); + explicit VerificationReporter(object_id_t objectId = DEFAULT_REPORTER, + AcceptsVerifyMessageIF* receiver = nullptr); + ~VerificationReporter() override; - void sendSuccessReport(uint8_t set_report_id, TcPacketPusBase* current_packet, - uint8_t set_step = 0); - void sendSuccessReport(uint8_t set_report_id, uint8_t ackFlags, uint16_t tcPacketId, - uint16_t tcSequenceControl, uint8_t set_step = 0); + void setReceiver(AcceptsVerifyMessageIF& receiver); - void sendFailureReport(uint8_t report_id, TcPacketPusBase* current_packet, - ReturnValue_t error_code = 0, uint8_t step = 0, uint32_t parameter1 = 0, - uint32_t parameter2 = 0); - void sendFailureReport(uint8_t report_id, uint8_t ackFlags, uint16_t tcPacketId, - uint16_t tcSequenceControl, ReturnValue_t error_code = 0, uint8_t step = 0, - uint32_t parameter1 = 0, uint32_t parameter2 = 0); + ReturnValue_t sendSuccessReport(VerifSuccessParams params) override; + ReturnValue_t sendFailureReport(VerifFailureParams params) override; - void initialize(); + static object_id_t DEFAULT_REPORTER; + static object_id_t DEFAULT_RECEIVER; + ReturnValue_t initialize() override; private: - static object_id_t messageReceiver; - MessageQueueId_t acknowledgeQueue; + MessageQueueId_t acknowledgeQueue = MessageQueueIF::NO_QUEUE; }; #endif /* FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_ */ diff --git a/src/fsfw/tmtcservices/VerificationReporterIF.h b/src/fsfw/tmtcservices/VerificationReporterIF.h new file mode 100644 index 00000000..d2330b88 --- /dev/null +++ b/src/fsfw/tmtcservices/VerificationReporterIF.h @@ -0,0 +1,69 @@ +#ifndef FSFW_TMTCSERVICES_VERIFICATIONREPORTERIF_H +#define FSFW_TMTCSERVICES_VERIFICATIONREPORTERIF_H + +#include "fsfw/retval.h" +#include "fsfw/tmtcpacket/pus/tc.h" + +struct VerifParamsBase { + VerifParamsBase() : reportId(0), tcPacketId(0), tcPsc(0) {} + VerifParamsBase(uint8_t reportId, uint16_t tcPacketId, uint16_t tcPsc) + : reportId(reportId), tcPacketId(tcPacketId), tcPsc(tcPsc) {} + uint8_t reportId; + uint16_t tcPacketId; + uint16_t tcPsc; + uint8_t ackFlags = ecss::ACK_ALL; + uint8_t step = 0; + + void resetTcFields() { + tcPacketId = 0; + tcPsc = 0; + ackFlags = 0; + } +}; + +struct VerifSuccessParams : public VerifParamsBase { + VerifSuccessParams() = default; + VerifSuccessParams(uint8_t reportId, uint16_t tcPacketId, uint16_t tcPsc) + : VerifParamsBase(reportId, tcPacketId, tcPsc) {} + VerifSuccessParams(uint8_t reportId, PusTcIF& tc) + : VerifParamsBase(reportId, tc.getPacketIdRaw(), tc.getPacketSeqCtrlRaw()) {} +}; + +struct VerifFailureParams : public VerifParamsBase { + VerifFailureParams() = default; + VerifFailureParams(uint8_t reportId, uint16_t tcPacketId, uint16_t tcPsc, ReturnValue_t errorCode, + uint32_t errorParam1, uint32_t errorParams2) + : VerifParamsBase(reportId, tcPacketId, tcPsc), + errorCode(errorCode), + errorParam1(errorParam1), + errorParam2(errorParams2) {} + VerifFailureParams(uint8_t reportId, uint16_t tcPacketId, uint16_t tcPsc, ReturnValue_t errorCode) + : VerifParamsBase(reportId, tcPacketId, tcPsc), errorCode(errorCode) {} + VerifFailureParams(uint8_t reportId, uint16_t tcPacketId, uint16_t tcPsc) + : VerifParamsBase(reportId, tcPacketId, tcPsc) {} + VerifFailureParams(uint8_t reportId, PusTcIF& tc, ReturnValue_t errorCode) + : VerifParamsBase(reportId, tc.getPacketIdRaw(), tc.getPacketSeqCtrlRaw()), + errorCode(errorCode) {} + VerifFailureParams(uint8_t reportId, PusTcIF& tc) + : VerifParamsBase(reportId, tc.getPacketIdRaw(), tc.getPacketSeqCtrlRaw()) {} + + void resetFailParams() { + errorCode = returnvalue::FAILED; + errorParam1 = 0; + errorParam2 = 0; + } + + ReturnValue_t errorCode = returnvalue::FAILED; + uint8_t step = 0; + uint32_t errorParam1 = 0; + uint32_t errorParam2 = 0; +}; +class VerificationReporterIF { + public: + virtual ~VerificationReporterIF() = default; + + virtual ReturnValue_t sendSuccessReport(VerifSuccessParams params) = 0; + virtual ReturnValue_t sendFailureReport(VerifFailureParams params) = 0; +}; + +#endif // FSFW_TMTCSERVICES_VERIFICATIONREPORTERIF_H diff --git a/src/fsfw/tmtcservices/tcHelpers.cpp b/src/fsfw/tmtcservices/tcHelpers.cpp new file mode 100644 index 00000000..c497979b --- /dev/null +++ b/src/fsfw/tmtcservices/tcHelpers.cpp @@ -0,0 +1,16 @@ +#include "tcHelpers.h" + +ReturnValue_t tc::prepareTcReader(StorageManagerIF &tcStore, store_address_t storeId, + PusTcReader &tcReader) { + const uint8_t *dataPtr; + size_t dataLen = 0; + ReturnValue_t result = tcStore.getData(storeId, &dataPtr, &dataLen); + if (result != returnvalue::OK) { + return result; + } + result = tcReader.setReadOnlyData(dataPtr, dataLen); + if (result != returnvalue::OK) { + return result; + } + return tcReader.parseDataWithoutCrcCheck(); +} diff --git a/src/fsfw/tmtcservices/tcHelpers.h b/src/fsfw/tmtcservices/tcHelpers.h new file mode 100644 index 00000000..9b1e1fdb --- /dev/null +++ b/src/fsfw/tmtcservices/tcHelpers.h @@ -0,0 +1,15 @@ +#ifndef FSFW_TMTCSERVICES_TCHELPERS_H +#define FSFW_TMTCSERVICES_TCHELPERS_H + +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/storagemanager/StorageManagerIF.h" +#include "fsfw/tmtcpacket/pus/tc.h" + +namespace tc { + +ReturnValue_t prepareTcReader(StorageManagerIF& tcStore, store_address_t storeId, + PusTcReader& tcReader); + +} // namespace tc + +#endif // FSFW_TMTCSERVICES_TCHELPERS_H diff --git a/src/fsfw/tmtcservices/tmHelpers.cpp b/src/fsfw/tmtcservices/tmHelpers.cpp new file mode 100644 index 00000000..abe2ae78 --- /dev/null +++ b/src/fsfw/tmtcservices/tmHelpers.cpp @@ -0,0 +1 @@ +#include "tmHelpers.h" diff --git a/src/fsfw/tmtcservices/tmHelpers.h b/src/fsfw/tmtcservices/tmHelpers.h new file mode 100644 index 00000000..be93f5ec --- /dev/null +++ b/src/fsfw/tmtcservices/tmHelpers.h @@ -0,0 +1,57 @@ +#ifndef FSFW_TMTCSERVICES_TMHELPERS_H_ +#define FSFW_TMTCSERVICES_TMHELPERS_H_ + +#include "TmSendHelper.h" +#include "TmStoreHelper.h" + +// I'd prefer to use tm, but there have been nameclashes with the tm struct +namespace telemetry { + +class DataWithObjectIdPrefix : public SerializeIF { + public: + DataWithObjectIdPrefix(object_id_t objectId, const uint8_t* srcData, size_t srcDataLen) + : objectId(objectId), bufAdapter(srcData, srcDataLen), userData(&bufAdapter) {} + + DataWithObjectIdPrefix(object_id_t objectId, const SerializeIF& serializable) + : objectId(objectId), userData(&serializable) {} + + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override { + if (*size + getSerializedSize() > maxSize) { + return SerializeIF::BUFFER_TOO_SHORT; + } + ReturnValue_t result = + SerializeAdapter::serialize(&objectId, buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + if (userData != nullptr) { + return userData->serialize(buffer, size, maxSize, streamEndianness); + } + return returnvalue::OK; + } + + [[nodiscard]] size_t getSerializedSize() const override { + size_t len = 0; + if (userData != nullptr) { + len += userData->getSerializedSize(); + } + return len; + } + + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override { + // As long as there is no way to know how long the expected data will be, this function + // does not make sense + return returnvalue::FAILED; + } + + private: + object_id_t objectId; + SerialBufferAdapter bufAdapter; + const SerializeIF* userData = nullptr; +}; + +} // namespace telemetry + +#endif // FSFW_TMTCSERVICES_TMHELPERS_H_ diff --git a/src/fsfw/util/UnsignedByteField.h b/src/fsfw/util/UnsignedByteField.h new file mode 100644 index 00000000..3f4ee791 --- /dev/null +++ b/src/fsfw/util/UnsignedByteField.h @@ -0,0 +1,47 @@ +#ifndef FSFW_UTIL_UNSIGNEDBYTEFIELD_H +#define FSFW_UTIL_UNSIGNEDBYTEFIELD_H + +#include "fsfw/serialize.h" + +template +class UnsignedByteField : public SerializeIF { + public: + static_assert(std::is_unsigned::value); + + explicit UnsignedByteField(T value) : value(value) {} + [[nodiscard]] ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override { + return SerializeAdapter::serialize(&value, buffer, size, maxSize, streamEndianness); + } + + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override { + return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness); + } + + [[nodiscard]] size_t getSerializedSize() const override { return sizeof(T); } + + [[nodiscard]] T getValue() const { return value; } + + void setValue(T value_) { value = value_; } + + private: + T value; +}; + +class U32ByteField : public UnsignedByteField { + public: + explicit U32ByteField(uint32_t value) : UnsignedByteField(value) {} +}; + +class U16ByteField : public UnsignedByteField { + public: + explicit U16ByteField(uint16_t value) : UnsignedByteField(value) {} +}; + +class U8ByteField : public UnsignedByteField { + public: + explicit U8ByteField(uint8_t value) : UnsignedByteField(value) {} +}; + +#endif // FSFW_UTIL_UNSIGNEDBYTEFIELD_H diff --git a/src/fsfw/version.cpp b/src/fsfw/version.cpp index e4a62002..27d44c03 100644 --- a/src/fsfw/version.cpp +++ b/src/fsfw/version.cpp @@ -1,6 +1,7 @@ #include "version.h" #include +#include #include "fsfw/FSFWVersion.h" @@ -13,11 +14,28 @@ #endif const fsfw::Version fsfw::FSFW_VERSION = {FSFW_VERSION_MAJOR, FSFW_VERSION_MINOR, - FSFW_VERSION_REVISION}; + FSFW_VERSION_REVISION, FSFW_VCS_INFO}; -fsfw::Version::Version(uint32_t major, uint32_t minor, uint32_t revision) - : major(major), minor(minor), revision(revision) {} +fsfw::Version::Version(int major, int minor, int revision, const char* addInfo) + : major(major), minor(minor), revision(revision), addInfo(addInfo) {} void fsfw::Version::getVersion(char* str, size_t maxLen) const { - snprintf(str, maxLen, "%d.%d.%d", major, minor, revision); + size_t len = snprintf(str, maxLen, "%d.%d.%d", major, minor, revision); + if (addInfo != nullptr and std::strcmp(addInfo, "") != 0) { + snprintf(str + len, maxLen - len, "-%s", addInfo); + } } + +namespace fsfw { + +#if FSFW_CPP_OSTREAM_ENABLED == 1 +std::ostream& operator<<(std::ostream& os, const Version& v) { + os << v.major << "." << v.minor << "." << v.revision; + if (v.addInfo != nullptr and std::strcmp(v.addInfo, "") != 0) { + os << "-" << v.addInfo; + } + return os; +} +#endif + +} // namespace fsfw diff --git a/src/fsfw/version.h b/src/fsfw/version.h index bb4d0399..a538c39a 100644 --- a/src/fsfw/version.h +++ b/src/fsfw/version.h @@ -12,10 +12,13 @@ namespace fsfw { class Version { public: - Version(uint32_t major, uint32_t minor, uint32_t revision); - uint32_t major = 0; - uint32_t minor = 0; - uint32_t revision = 0; + Version(int major, int minor, int revision, const char* addInfo = nullptr); + int major = -1; + int minor = -1; + int revision = -1; + + // Additional information, e.g. a git SHA hash + const char* addInfo = nullptr; friend bool operator==(const Version& v1, const Version& v2) { return (v1.major == v2.major and v1.minor == v2.minor and v1.revision == v2.revision); @@ -43,10 +46,7 @@ class Version { * @param v * @return */ - friend std::ostream& operator<<(std::ostream& os, const Version& v) { - os << v.major << "." << v.minor << "." << v.revision; - return os; - } + friend std::ostream& operator<<(std::ostream& os, const Version& v); #endif /** @@ -57,7 +57,7 @@ class Version { void getVersion(char* str, size_t maxLen) const; }; -extern const fsfw::Version FSFW_VERSION; +extern const Version FSFW_VERSION; } // namespace fsfw diff --git a/hal/src/fsfw_hal/CMakeLists.txt b/src/fsfw_hal/CMakeLists.txt similarity index 58% rename from hal/src/fsfw_hal/CMakeLists.txt rename to src/fsfw_hal/CMakeLists.txt index b7559d4b..24d712aa 100644 --- a/hal/src/fsfw_hal/CMakeLists.txt +++ b/src/fsfw_hal/CMakeLists.txt @@ -1,10 +1,11 @@ add_subdirectory(devicehandlers) add_subdirectory(common) +add_subdirectory(host) if(UNIX) - add_subdirectory(linux) + add_subdirectory(linux) endif() if(FSFW_HAL_ADD_STM32H7) - add_subdirectory(stm32h7) + add_subdirectory(stm32h7) endif() diff --git a/src/fsfw_hal/common/CMakeLists.txt b/src/fsfw_hal/common/CMakeLists.txt new file mode 100644 index 00000000..2f4608f8 --- /dev/null +++ b/src/fsfw_hal/common/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(gpio) + +target_sources(${LIB_FSFW_NAME} PRIVATE printChar.c) diff --git a/src/fsfw_hal/common/gpio/CMakeLists.txt b/src/fsfw_hal/common/gpio/CMakeLists.txt new file mode 100644 index 00000000..5c81d9cc --- /dev/null +++ b/src/fsfw_hal/common/gpio/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE GpioCookie.cpp) diff --git a/hal/src/fsfw_hal/common/gpio/GpioCookie.cpp b/src/fsfw_hal/common/gpio/GpioCookie.cpp similarity index 88% rename from hal/src/fsfw_hal/common/gpio/GpioCookie.cpp rename to src/fsfw_hal/common/gpio/GpioCookie.cpp index 4c4b4d14..f75ba4e8 100644 --- a/hal/src/fsfw_hal/common/gpio/GpioCookie.cpp +++ b/src/fsfw_hal/common/gpio/GpioCookie.cpp @@ -11,7 +11,7 @@ ReturnValue_t GpioCookie::addGpio(gpioId_t gpioId, GpioBase* gpioConfig) { #else sif::printWarning("GpioCookie::addGpio: gpioConfig is nullpointer\n"); #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } auto gpioMapIter = gpioMap.find(gpioId); if (gpioMapIter == gpioMap.end()) { @@ -25,9 +25,9 @@ ReturnValue_t GpioCookie::addGpio(gpioId_t gpioId, GpioBase* gpioConfig) { sif::printWarning("GpioCookie::addGpio: Failed to add GPIO %d to GPIO map\n", gpioId); #endif #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -36,7 +36,7 @@ ReturnValue_t GpioCookie::addGpio(gpioId_t gpioId, GpioBase* gpioConfig) { sif::printWarning("GpioCookie::addGpio: GPIO already exists in GPIO map\n"); #endif #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } GpioMap GpioCookie::getGpioMap() const { return gpioMap; } diff --git a/hal/src/fsfw_hal/common/gpio/GpioCookie.h b/src/fsfw_hal/common/gpio/GpioCookie.h similarity index 94% rename from hal/src/fsfw_hal/common/gpio/GpioCookie.h rename to src/fsfw_hal/common/gpio/GpioCookie.h index cf836eae..709af9a5 100644 --- a/hal/src/fsfw_hal/common/gpio/GpioCookie.h +++ b/src/fsfw_hal/common/gpio/GpioCookie.h @@ -2,7 +2,7 @@ #define COMMON_GPIO_GPIOCOOKIE_H_ #include -#include +#include #include "GpioIF.h" #include "gpioDefinitions.h" diff --git a/hal/src/fsfw_hal/common/gpio/GpioIF.h b/src/fsfw_hal/common/gpio/GpioIF.h similarity index 89% rename from hal/src/fsfw_hal/common/gpio/GpioIF.h rename to src/fsfw_hal/common/gpio/GpioIF.h index 5cca1481..a8abb126 100644 --- a/hal/src/fsfw_hal/common/gpio/GpioIF.h +++ b/src/fsfw_hal/common/gpio/GpioIF.h @@ -2,7 +2,7 @@ #define COMMON_GPIO_GPIOIF_H_ #include -#include +#include #include "gpioDefinitions.h" @@ -13,7 +13,7 @@ class GpioCookie; * over GPIOs. * @author J. Meier */ -class GpioIF : public HasReturnvaluesIF { +class GpioIF { public: virtual ~GpioIF(){}; @@ -29,7 +29,7 @@ class GpioIF : public HasReturnvaluesIF { * functionality to pull a certain GPIO to high logic level. * * @param gpioId A unique number which specifies the GPIO to drive. - * @return Returns RETURN_OK for success. This should never return RETURN_FAILED. + * @return Returns returnvalue::OK for success. This should never return returnvalue::FAILED. */ virtual ReturnValue_t pullHigh(gpioId_t gpioId) = 0; diff --git a/hal/src/fsfw_hal/common/gpio/gpioDefinitions.h b/src/fsfw_hal/common/gpio/gpioDefinitions.h similarity index 96% rename from hal/src/fsfw_hal/common/gpio/gpioDefinitions.h rename to src/fsfw_hal/common/gpio/gpioDefinitions.h index eb90629e..9f8b5e32 100644 --- a/hal/src/fsfw_hal/common/gpio/gpioDefinitions.h +++ b/src/fsfw_hal/common/gpio/gpioDefinitions.h @@ -5,6 +5,14 @@ #include #include +#ifdef PLATFORM_WIN +// Defined in Windows header for whatever reason, and leads to nameclash issues with +// class enums which have entries of the same name. +#undef IN +#undef OUT +#undef CALLBACK +#endif + using gpioId_t = uint16_t; namespace gpio { diff --git a/src/fsfw_hal/common/printChar.c b/src/fsfw_hal/common/printChar.c new file mode 100644 index 00000000..24fba5c8 --- /dev/null +++ b/src/fsfw_hal/common/printChar.c @@ -0,0 +1,10 @@ +#include +#include + +void __attribute__((weak)) printChar(const char* character, bool errStream) { + if (errStream) { + fprintf(stderr, "%c", *character); + } else { + printf("%c", *character); + } +} diff --git a/hal/src/fsfw_hal/common/spi/spiCommon.h b/src/fsfw_hal/common/spi/spiCommon.h similarity index 100% rename from hal/src/fsfw_hal/common/spi/spiCommon.h rename to src/fsfw_hal/common/spi/spiCommon.h diff --git a/src/fsfw_hal/devicehandlers/CMakeLists.txt b/src/fsfw_hal/devicehandlers/CMakeLists.txt new file mode 100644 index 00000000..17139416 --- /dev/null +++ b/src/fsfw_hal/devicehandlers/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources( + ${LIB_FSFW_NAME} PRIVATE GyroL3GD20Handler.cpp MgmRM3100Handler.cpp + MgmLIS3MDLHandler.cpp) diff --git a/hal/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.cpp b/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.cpp similarity index 96% rename from hal/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.cpp rename to src/fsfw_hal/devicehandlers/GyroL3GD20Handler.cpp index 94e1331c..1ffc60f1 100644 --- a/hal/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.cpp +++ b/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.cpp @@ -70,9 +70,9 @@ ReturnValue_t GyroHandlerL3GD20H::buildTransitionDeviceCommand(DeviceCommandId_t "GyroL3GD20Handler::buildTransitionDeviceCommand: " "Unknown internal state!\n"); #endif - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t GyroHandlerL3GD20H::buildNormalDeviceCommand(DeviceCommandId_t *id) { @@ -135,7 +135,7 @@ ReturnValue_t GyroHandlerL3GD20H::buildCommandFromCommand(DeviceCommandId_t devi default: return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t GyroHandlerL3GD20H::scanForReply(const uint8_t *start, size_t len, @@ -144,12 +144,12 @@ ReturnValue_t GyroHandlerL3GD20H::scanForReply(const uint8_t *start, size_t len, *foundId = this->getPendingCommand(); *foundLen = this->rawPacketLen; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; switch (id) { case (L3GD20H::CONFIGURE_CTRL_REGS): { commandExecuted = true; @@ -207,7 +207,7 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id, } PoolReadGuard readSet(&dataset); - if (readSet.getReadResult() == HasReturnvaluesIF::RETURN_OK) { + if (readSet.getReadResult() == returnvalue::OK) { if (std::abs(angVelocX) < this->absLimitX) { dataset.angVelocX = angVelocX; dataset.angVelocX.setValid(true); @@ -252,7 +252,7 @@ ReturnValue_t GyroHandlerL3GD20H::initializeLocalDataPool(localpool::DataPool &l localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Y, new PoolEntry({0.0})); localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Z, new PoolEntry({0.0})); localDataPoolMap.emplace(L3GD20H::TEMPERATURE, new PoolEntry({0.0})); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void GyroHandlerL3GD20H::fillCommandAndReplyMap() { diff --git a/hal/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.h b/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.h similarity index 100% rename from hal/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.h rename to src/fsfw_hal/devicehandlers/GyroL3GD20Handler.h diff --git a/hal/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp b/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp similarity index 92% rename from hal/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp rename to src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp index 52b6dc07..9cb16c35 100644 --- a/hal/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp +++ b/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp @@ -1,9 +1,9 @@ #include "MgmLIS3MDLHandler.h" -#include "fsfw/datapool/PoolReadGuard.h" - #include +#include "fsfw/datapool/PoolReadGuard.h" + MgmLIS3MDLHandler::MgmLIS3MDLHandler(object_id_t objectId, object_id_t deviceCommunication, CookieIF *comCookie, uint32_t transitionDelay) : DeviceHandlerBase(objectId, deviceCommunication, comCookie), @@ -82,7 +82,7 @@ ReturnValue_t MgmLIS3MDLHandler::buildTransitionDeviceCommand(DeviceCommandId_t #else sif::printWarning("GyroHandler::buildTransitionDeviceCommand: Unknown internal state!\n"); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } } return buildCommandFromCommand(*id, NULL, 0); @@ -137,7 +137,7 @@ ReturnValue_t MgmLIS3MDLHandler::buildCommandFromCommand(DeviceCommandId_t devic rawPacket = commandBuffer; rawPacketLen = MGMLIS3MDL::NR_OF_DATA_AND_CFG_REGISTERS + 1; - return RETURN_OK; + return returnvalue::OK; } case (MGMLIS3MDL::READ_TEMPERATURE): { std::memset(commandBuffer, 0, 3); @@ -145,7 +145,7 @@ ReturnValue_t MgmLIS3MDLHandler::buildCommandFromCommand(DeviceCommandId_t devic rawPacket = commandBuffer; rawPacketLen = 3; - return RETURN_OK; + return returnvalue::OK; } case (MGMLIS3MDL::IDENTIFY_DEVICE): { return identifyDevice(); @@ -155,7 +155,7 @@ ReturnValue_t MgmLIS3MDLHandler::buildCommandFromCommand(DeviceCommandId_t devic } case (MGMLIS3MDL::SETUP_MGM): { setupMgm(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } case (MGMLIS3MDL::ACCURACY_OP_MODE_SET): { return setOperatingMode(commandData, commandDataLen); @@ -163,7 +163,7 @@ ReturnValue_t MgmLIS3MDLHandler::buildCommandFromCommand(DeviceCommandId_t devic default: return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; } - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } ReturnValue_t MgmLIS3MDLHandler::identifyDevice() { @@ -174,7 +174,7 @@ ReturnValue_t MgmLIS3MDLHandler::identifyDevice() { rawPacket = commandBuffer; rawPacketLen = size; - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t MgmLIS3MDLHandler::scanForReply(const uint8_t *start, size_t len, @@ -234,7 +234,7 @@ ReturnValue_t MgmLIS3MDLHandler::scanForReply(const uint8_t *start, size_t len, /* Data with SPI Interface always has this answer */ if (start[0] == 0b11111111) { - return RETURN_OK; + return returnvalue::OK; } else { return DeviceHandlerIF::INVALID_DATA; } @@ -285,27 +285,23 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons } PoolReadGuard readHelper(&dataset); - if (readHelper.getReadResult() == HasReturnvaluesIF::RETURN_OK) { + if (readHelper.getReadResult() == returnvalue::OK) { + if (std::abs(mgmX) > absLimitX or std::abs(mgmY) > absLimitY or + std::abs(mgmZ) > absLimitZ) { + dataset.fieldStrengths.setValid(false); + } if (std::abs(mgmX) < absLimitX) { - dataset.fieldStrengthX = mgmX; - dataset.fieldStrengthX.setValid(true); - } else { - dataset.fieldStrengthX.setValid(false); + dataset.fieldStrengths[0] = mgmX; } if (std::abs(mgmY) < absLimitY) { - dataset.fieldStrengthY = mgmY; - dataset.fieldStrengthY.setValid(true); - } else { - dataset.fieldStrengthY.setValid(false); + dataset.fieldStrengths[1] = mgmY; } if (std::abs(mgmZ) < absLimitZ) { - dataset.fieldStrengthZ = mgmZ; - dataset.fieldStrengthZ.setValid(true); - } else { - dataset.fieldStrengthZ.setValid(false); + dataset.fieldStrengths[2] = mgmZ; } + dataset.fieldStrengths.setValid(true); } break; } @@ -324,7 +320,7 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons } ReturnValue_t result = dataset.read(); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { dataset.temperature = tempValue; dataset.commit(); } @@ -335,7 +331,7 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY; } } - return RETURN_OK; + return returnvalue::OK; } MGMLIS3MDL::Sensitivies MgmLIS3MDLHandler::getSensitivity(uint8_t ctrlRegister2) { @@ -398,7 +394,7 @@ ReturnValue_t MgmLIS3MDLHandler::enableTemperatureSensor(const uint8_t *commandD rawPacket = commandBuffer; rawPacketLen = size; - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t MgmLIS3MDLHandler::setOperatingMode(const uint8_t *commandData, @@ -455,7 +451,7 @@ ReturnValue_t MgmLIS3MDLHandler::prepareCtrlRegisterWrite() { rawPacketLen = MGMLIS3MDL::NR_OF_CTRL_REGISTERS + 1; // We dont have to check if this is working because we just did i - return RETURN_OK; + return returnvalue::OK; } void MgmLIS3MDLHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) { @@ -468,11 +464,10 @@ void MgmLIS3MDLHandler::modeChanged(void) { internalState = InternalState::STATE ReturnValue_t MgmLIS3MDLHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTH_X, new PoolEntry({0.0})); - localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTH_Y, new PoolEntry({0.0})); - localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTH_Z, new PoolEntry({0.0})); - localDataPoolMap.emplace(MGMLIS3MDL::TEMPERATURE_CELCIUS, new PoolEntry({0.0})); - return HasReturnvaluesIF::RETURN_OK; + localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTHS, &mgmXYZ); + localDataPoolMap.emplace(MGMLIS3MDL::TEMPERATURE_CELCIUS, &temperature); + poolManager.subscribeForRegularPeriodicPacket({dataset.getSid(), false, 10.0}); + return returnvalue::OK; } void MgmLIS3MDLHandler::setAbsoluteLimits(float xLimit, float yLimit, float zLimit) { diff --git a/hal/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h b/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h similarity index 98% rename from hal/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h rename to src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h index 42bd5d4c..3626a2b0 100644 --- a/hal/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h +++ b/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h @@ -2,7 +2,6 @@ #define MISSION_DEVICES_MGMLIS3MDLHANDLER_H_ #include "devicedefinitions/MgmLIS3HandlerDefs.h" -#include "events/subsystemIdRanges.h" #include "fsfw/devicehandlers/DeviceHandlerBase.h" #include "fsfw/globalfunctions/PeriodicOperationDivider.h" @@ -103,6 +102,8 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase { CommunicationStep communicationStep = CommunicationStep::DATA; bool commandExecuted = false; + PoolEntry mgmXYZ = PoolEntry(3); + PoolEntry temperature = PoolEntry(); /*------------------------------------------------------------------------*/ /* Device specific commands and variables */ /*------------------------------------------------------------------------*/ diff --git a/hal/src/fsfw_hal/devicehandlers/MgmRM3100Handler.cpp b/src/fsfw_hal/devicehandlers/MgmRM3100Handler.cpp similarity index 91% rename from hal/src/fsfw_hal/devicehandlers/MgmRM3100Handler.cpp rename to src/fsfw_hal/devicehandlers/MgmRM3100Handler.cpp index f9929d63..307d0a55 100644 --- a/hal/src/fsfw_hal/devicehandlers/MgmRM3100Handler.cpp +++ b/src/fsfw_hal/devicehandlers/MgmRM3100Handler.cpp @@ -4,7 +4,7 @@ #include "fsfw/devicehandlers/DeviceHandlerMessage.h" #include "fsfw/globalfunctions/bitutility.h" #include "fsfw/objectmanager/SystemObjectIF.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" MgmRM3100Handler::MgmRM3100Handler(object_id_t objectId, object_id_t deviceCommunication, CookieIF *comCookie, uint32_t transitionDelay) @@ -93,7 +93,7 @@ ReturnValue_t MgmRM3100Handler::buildTransitionDeviceCommand(DeviceCommandId_t * "Unknown internal state\n"); #endif #endif - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } return buildCommandFromCommand(*id, commandBuffer, commandLen); @@ -146,7 +146,7 @@ ReturnValue_t MgmRM3100Handler::buildCommandFromCommand(DeviceCommandId_t device default: return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t MgmRM3100Handler::buildNormalDeviceCommand(DeviceCommandId_t *id) { @@ -159,11 +159,11 @@ ReturnValue_t MgmRM3100Handler::scanForReply(const uint8_t *start, size_t len, // For SPI, ID will always be the one of the last sent command *foundId = this->getPendingCommand(); *foundLen = len; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; switch (id) { case (RM3100::CONFIGURE_CMM): case (RM3100::CONFIGURE_CYCLE_COUNT): @@ -250,7 +250,7 @@ ReturnValue_t MgmRM3100Handler::handleCycleCountConfigCommand(DeviceCommandId_t std::memcpy(commandBuffer + 5, &cycleCountRegValueZ, 2); rawPacketLen = 7; rawPacket = commandBuffer; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t MgmRM3100Handler::handleCycleCommand(bool oneCycleValue, const uint8_t *commandData, @@ -258,7 +258,7 @@ ReturnValue_t MgmRM3100Handler::handleCycleCommand(bool oneCycleValue, const uin RM3100::CycleCountCommand command(oneCycleValue); ReturnValue_t result = command.deSerialize(&commandData, &commandDataLen, SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -274,7 +274,7 @@ ReturnValue_t MgmRM3100Handler::handleCycleCommand(bool oneCycleValue, const uin cycleCountRegValueX = command.cycleCountX; cycleCountRegValueY = command.cycleCountY; cycleCountRegValueZ = command.cycleCountZ; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t MgmRM3100Handler::handleTmrcConfigCommand(DeviceCommandId_t deviceCommand, @@ -289,7 +289,7 @@ ReturnValue_t MgmRM3100Handler::handleTmrcConfigCommand(DeviceCommandId_t device tmrcRegValue = commandData[0]; rawPacketLen = 2; rawPacket = commandBuffer; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void MgmRM3100Handler::fillCommandAndReplyMap() { @@ -305,14 +305,13 @@ void MgmRM3100Handler::fillCommandAndReplyMap() { insertInCommandAndReplyMap(RM3100::READ_DATA, 3, &primaryDataset); } -void MgmRM3100Handler::modeChanged(void) { internalState = InternalState::NONE; } +void MgmRM3100Handler::modeChanged() { internalState = InternalState::NONE; } ReturnValue_t MgmRM3100Handler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(RM3100::FIELD_STRENGTH_X, new PoolEntry({0.0})); - localDataPoolMap.emplace(RM3100::FIELD_STRENGTH_Y, new PoolEntry({0.0})); - localDataPoolMap.emplace(RM3100::FIELD_STRENGTH_Z, new PoolEntry({0.0})); - return HasReturnvaluesIF::RETURN_OK; + localDataPoolMap.emplace(RM3100::FIELD_STRENGTHS, &mgmXYZ); + poolManager.subscribeForRegularPeriodicPacket({primaryDataset.getSid(), false, 10.0}); + return returnvalue::OK; } uint32_t MgmRM3100Handler::getTransitionDelayMs(Mode_t from, Mode_t to) { @@ -326,12 +325,12 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) { // trickery here to calculate the raw values first int32_t fieldStrengthRawX = ((packet[1] << 24) | (packet[2] << 16) | (packet[3] << 8)) >> 8; int32_t fieldStrengthRawY = ((packet[4] << 24) | (packet[5] << 16) | (packet[6] << 8)) >> 8; - int32_t fieldStrengthRawZ = ((packet[7] << 24) | (packet[8] << 16) | (packet[3] << 8)) >> 8; + int32_t fieldStrengthRawZ = ((packet[7] << 24) | (packet[8] << 16) | (packet[9] << 8)) >> 8; // Now scale to physical value in microtesla float fieldStrengthX = fieldStrengthRawX * scaleFactorX; - float fieldStrengthY = fieldStrengthRawY * scaleFactorX; - float fieldStrengthZ = fieldStrengthRawZ * scaleFactorX; + float fieldStrengthY = fieldStrengthRawY * scaleFactorY; + float fieldStrengthZ = fieldStrengthRawZ * scaleFactorZ; if (periodicPrintout) { if (debugDivider.checkAndIncrement()) { @@ -353,13 +352,13 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) { // TODO: Sanity check on values? PoolReadGuard readGuard(&primaryDataset); - if (readGuard.getReadResult() == HasReturnvaluesIF::RETURN_OK) { - primaryDataset.fieldStrengthX = fieldStrengthX; - primaryDataset.fieldStrengthY = fieldStrengthY; - primaryDataset.fieldStrengthZ = fieldStrengthZ; + if (readGuard.getReadResult() == returnvalue::OK) { + primaryDataset.fieldStrengths[0] = fieldStrengthX; + primaryDataset.fieldStrengths[1] = fieldStrengthY; + primaryDataset.fieldStrengths[2] = fieldStrengthZ; primaryDataset.setValidity(true, true); } - return RETURN_OK; + return returnvalue::OK; } void MgmRM3100Handler::enablePeriodicPrintouts(bool enable, uint8_t divider) { diff --git a/hal/src/fsfw_hal/devicehandlers/MgmRM3100Handler.h b/src/fsfw_hal/devicehandlers/MgmRM3100Handler.h similarity index 98% rename from hal/src/fsfw_hal/devicehandlers/MgmRM3100Handler.h rename to src/fsfw_hal/devicehandlers/MgmRM3100Handler.h index d1048cb6..d45b2404 100644 --- a/hal/src/fsfw_hal/devicehandlers/MgmRM3100Handler.h +++ b/src/fsfw_hal/devicehandlers/MgmRM3100Handler.h @@ -85,6 +85,7 @@ class MgmRM3100Handler : public DeviceHandlerBase { bool goToNormalModeAtStartup = false; uint32_t transitionDelay; + PoolEntry mgmXYZ = PoolEntry(3); ReturnValue_t handleCycleCountConfigCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData, size_t commandDataLen); diff --git a/hal/src/fsfw_hal/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h b/src/fsfw_hal/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h similarity index 100% rename from hal/src/fsfw_hal/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h rename to src/fsfw_hal/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h diff --git a/hal/src/fsfw_hal/devicehandlers/devicedefinitions/MgmLIS3HandlerDefs.h b/src/fsfw_hal/devicehandlers/devicedefinitions/MgmLIS3HandlerDefs.h similarity index 94% rename from hal/src/fsfw_hal/devicehandlers/devicedefinitions/MgmLIS3HandlerDefs.h rename to src/fsfw_hal/devicehandlers/devicedefinitions/MgmLIS3HandlerDefs.h index 3d78c5c9..34237637 100644 --- a/hal/src/fsfw_hal/devicehandlers/devicedefinitions/MgmLIS3HandlerDefs.h +++ b/src/fsfw_hal/devicehandlers/devicedefinitions/MgmLIS3HandlerDefs.h @@ -139,12 +139,7 @@ static const uint8_t CTRL_REG5_DEFAULT = 0; static const uint32_t MGM_DATA_SET_ID = READ_CONFIG_AND_DATA; -enum MgmPoolIds : lp_id_t { - FIELD_STRENGTH_X, - FIELD_STRENGTH_Y, - FIELD_STRENGTH_Z, - TEMPERATURE_CELCIUS -}; +enum MgmPoolIds : lp_id_t { FIELD_STRENGTHS, TEMPERATURE_CELCIUS }; class MgmPrimaryDataset : public StaticLocalDataSet<4> { public: @@ -152,9 +147,10 @@ class MgmPrimaryDataset : public StaticLocalDataSet<4> { MgmPrimaryDataset(object_id_t mgmId) : StaticLocalDataSet(sid_t(mgmId, MGM_DATA_SET_ID)) {} - lp_var_t fieldStrengthX = lp_var_t(sid.objectId, FIELD_STRENGTH_X, this); - lp_var_t fieldStrengthY = lp_var_t(sid.objectId, FIELD_STRENGTH_Y, this); - lp_var_t fieldStrengthZ = lp_var_t(sid.objectId, FIELD_STRENGTH_Z, this); + /** + * Field strenghts in uT + */ + lp_vec_t fieldStrengths = lp_vec_t(sid.objectId, FIELD_STRENGTHS, this); lp_var_t temperature = lp_var_t(sid.objectId, TEMPERATURE_CELCIUS, this); }; diff --git a/hal/src/fsfw_hal/devicehandlers/devicedefinitions/MgmRM3100HandlerDefs.h b/src/fsfw_hal/devicehandlers/devicedefinitions/MgmRM3100HandlerDefs.h similarity index 91% rename from hal/src/fsfw_hal/devicehandlers/devicedefinitions/MgmRM3100HandlerDefs.h rename to src/fsfw_hal/devicehandlers/devicedefinitions/MgmRM3100HandlerDefs.h index e3eaff22..a2aa8ab0 100644 --- a/hal/src/fsfw_hal/devicehandlers/devicedefinitions/MgmRM3100HandlerDefs.h +++ b/src/fsfw_hal/devicehandlers/devicedefinitions/MgmRM3100HandlerDefs.h @@ -101,11 +101,7 @@ class CycleCountCommand : public SerialLinkedListAdapter { static constexpr uint32_t MGM_DATASET_ID = READ_DATA; -enum MgmPoolIds : lp_id_t { - FIELD_STRENGTH_X, - FIELD_STRENGTH_Y, - FIELD_STRENGTH_Z, -}; +enum MgmPoolIds : lp_id_t { FIELD_STRENGTHS }; class Rm3100PrimaryDataset : public StaticLocalDataSet<3> { public: @@ -113,10 +109,10 @@ class Rm3100PrimaryDataset : public StaticLocalDataSet<3> { Rm3100PrimaryDataset(object_id_t mgmId) : StaticLocalDataSet(sid_t(mgmId, MGM_DATASET_ID)) {} - // Field strengths in micro Tesla. - lp_var_t fieldStrengthX = lp_var_t(sid.objectId, FIELD_STRENGTH_X, this); - lp_var_t fieldStrengthY = lp_var_t(sid.objectId, FIELD_STRENGTH_Y, this); - lp_var_t fieldStrengthZ = lp_var_t(sid.objectId, FIELD_STRENGTH_Z, this); + /** + * Field strenghts in uT + */ + lp_vec_t fieldStrengths = lp_vec_t(sid.objectId, FIELD_STRENGTHS, this); }; } // namespace RM3100 diff --git a/src/fsfw_hal/host/CMakeLists.txt b/src/fsfw_hal/host/CMakeLists.txt new file mode 100644 index 00000000..95b79675 --- /dev/null +++ b/src/fsfw_hal/host/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PUBLIC HostFilesystem.cpp) diff --git a/src/fsfw_hal/host/HostFilesystem.cpp b/src/fsfw_hal/host/HostFilesystem.cpp new file mode 100644 index 00000000..fe593f27 --- /dev/null +++ b/src/fsfw_hal/host/HostFilesystem.cpp @@ -0,0 +1,162 @@ +#include "HostFilesystem.h" + +#include +#include + +#include "fsfw/serialize.h" + +using namespace std::filesystem; +using namespace std; + +HostFilesystem::HostFilesystem() = default; + +ReturnValue_t HostFilesystem::writeToFile(FileOpParams params, const uint8_t *data) { + if (params.path() == nullptr) { + return returnvalue::FAILED; + } + path path(params.path()); + if (not exists(path)) { + return HasFileSystemIF::FILE_DOES_NOT_EXIST; + } + // This is equivalent to "r+" mode, which is what we need here. Only using ::out would truncate + // the file + ofstream file(path, ios::binary | ios::out | ios::in); + if (file.fail()) { + return HasFileSystemIF::GENERIC_FILE_ERROR; + } + file.seekp(static_cast(params.offset)); + file.write(reinterpret_cast(data), static_cast(params.size)); + return returnvalue::OK; +} + +ReturnValue_t HostFilesystem::readFromFile(FileOpParams params, uint8_t **buffer, size_t &readSize, + size_t maxSize) { + if (params.path() == nullptr) { + return returnvalue::FAILED; + } + path path(params.path()); + if (not exists(path)) { + return HasFileSystemIF::FILE_DOES_NOT_EXIST; + } + ifstream file(path); + if (file.fail()) { + return HasFileSystemIF::GENERIC_FILE_ERROR; + } + auto sizeToRead = static_cast(params.size); + file.seekg(static_cast(params.offset)); + if (readSize + sizeToRead > maxSize) { + return SerializeIF::BUFFER_TOO_SHORT; + } + file.read(reinterpret_cast(*buffer), sizeToRead); + readSize += sizeToRead; + *buffer += sizeToRead; + return returnvalue::OK; +} + +ReturnValue_t HostFilesystem::createFile(FilesystemParams params, const uint8_t *data, + size_t size) { + if (params.path == nullptr) { + return returnvalue::FAILED; + } + path path(params.path); + if (exists(path)) { + return HasFileSystemIF::FILE_ALREADY_EXISTS; + } + ofstream file(path); + if (file.fail()) { + return HasFileSystemIF::GENERIC_FILE_ERROR; + } + return returnvalue::OK; +} + +ReturnValue_t HostFilesystem::removeFile(const char *path_, FileSystemArgsIF *args) { + if (path_ == nullptr) { + return returnvalue::FAILED; + } + path path(path_); + if (not exists(path)) { + return HasFileSystemIF::FILE_DOES_NOT_EXIST; + } + if (remove(path, errorCode)) { + return returnvalue::OK; + } + return HasFileSystemIF::GENERIC_FILE_ERROR; +} + +ReturnValue_t HostFilesystem::createDirectory(FilesystemParams params, bool createParentDirs) { + if (params.path == nullptr) { + return returnvalue::FAILED; + } + path dirPath(params.path); + + if (exists(dirPath)) { + return HasFileSystemIF::DIRECTORY_ALREADY_EXISTS; + } + + if (createParentDirs) { + if (create_directories(dirPath, errorCode)) { + return returnvalue::OK; + } + return HasFileSystemIF::GENERIC_DIR_ERROR; + } + if (create_directory(dirPath, errorCode)) { + return returnvalue::OK; + } + return HasFileSystemIF::GENERIC_DIR_ERROR; +} + +ReturnValue_t HostFilesystem::removeDirectory(FilesystemParams params, bool deleteRecurively) { + if (params.path == nullptr) { + return returnvalue::FAILED; + } + path dirPath(params.path); + if (not exists(dirPath)) { + return HasFileSystemIF::DIRECTORY_DOES_NOT_EXIST; + } + if (is_regular_file(dirPath)) { + return HasFileSystemIF::NOT_A_DIRECTORY; + } + if (deleteRecurively) { + if (remove_all(dirPath, errorCode)) { + return returnvalue::OK; + } + } else { + if (remove(dirPath, errorCode)) { + return returnvalue::OK; + } + } + // Error handling + if (errorCode == std::errc::directory_not_empty) { + return HasFileSystemIF::DIRECTORY_NOT_EMPTY; + } + return HasFileSystemIF::GENERIC_DIR_ERROR; +} + +ReturnValue_t HostFilesystem::rename(const char *oldPath_, const char *newPath_, + FileSystemArgsIF *args) { + if (oldPath_ == nullptr or newPath_ == nullptr) { + return returnvalue::FAILED; + } + path oldPath(oldPath_); + path newPath(newPath_); + errorCode.clear(); + std::filesystem::rename(oldPath, newPath, errorCode); + if (errorCode) { + return HasFileSystemIF::GENERIC_RENAME_ERROR; + } + return returnvalue::OK; +} + +bool HostFilesystem::fileExists(FilesystemParams params) { + path path(params.path); + return filesystem::exists(path); +} + +ReturnValue_t HostFilesystem::truncateFile(FilesystemParams params) { + path path(params.path); + if (not filesystem::exists(path)) { + return FILE_DOES_NOT_EXIST; + } + ofstream of(path); + return returnvalue::OK; +} diff --git a/src/fsfw_hal/host/HostFilesystem.h b/src/fsfw_hal/host/HostFilesystem.h new file mode 100644 index 00000000..7b865e2d --- /dev/null +++ b/src/fsfw_hal/host/HostFilesystem.h @@ -0,0 +1,32 @@ +#ifndef FSFW_HAL_HOSTFILESYSTEM_H +#define FSFW_HAL_HOSTFILESYSTEM_H + +#include + +#include "fsfw/filesystem/HasFileSystemIF.h" + +class HostFilesystem : public HasFileSystemIF { + public: + HostFilesystem(); + + bool fileExists(FilesystemParams params) override; + ReturnValue_t truncateFile(FilesystemParams params) override; + ReturnValue_t writeToFile(FileOpParams params, const uint8_t *data) override; + ReturnValue_t readFromFile(FileOpParams fileOpInfo, uint8_t **buffer, size_t &readSize, + size_t maxSize) override; + ReturnValue_t createFile(FilesystemParams params, const uint8_t *data, size_t size) override; + ReturnValue_t removeFile(const char *path, FileSystemArgsIF *args) override; + ReturnValue_t createDirectory(FilesystemParams params, bool createParentDirs) override; + ReturnValue_t removeDirectory(FilesystemParams params, bool deleteRecurively) override; + ReturnValue_t rename(const char *oldPath, const char *newPath, FileSystemArgsIF *args) override; + + std::error_code errorCode; + using HasFileSystemIF::createDirectory; + using HasFileSystemIF::createFile; + using HasFileSystemIF::removeDirectory; + using HasFileSystemIF::removeFile; + using HasFileSystemIF::rename; + + private: +}; +#endif // FSFW_HAL_HOSTFILESYSTEM_H diff --git a/src/fsfw_hal/linux/CMakeLists.txt b/src/fsfw_hal/linux/CMakeLists.txt new file mode 100644 index 00000000..d22d7ff1 --- /dev/null +++ b/src/fsfw_hal/linux/CMakeLists.txt @@ -0,0 +1,24 @@ +if(FSFW_HAL_ADD_RASPBERRY_PI) + add_subdirectory(rpi) +endif() + +target_sources(${LIB_FSFW_NAME} PRIVATE UnixFileGuard.cpp CommandExecutor.cpp + utility.cpp) + +if(FSFW_HAL_LINUX_ADD_LIBGPIOD) + add_subdirectory(gpio) +endif() +if(FSFW_HAL_LINUX_ADD_SERIAL_DRIVERS) + add_subdirectory(serial) +endif() + +if(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS) + # Adding those does not really make sense on Apple systems which are generally + # host systems. It won't even compile as the headers are missing + if(NOT APPLE) + add_subdirectory(i2c) + add_subdirectory(spi) + endif() +endif() + +add_subdirectory(uio) diff --git a/hal/src/fsfw_hal/linux/CommandExecutor.cpp b/src/fsfw_hal/linux/CommandExecutor.cpp similarity index 92% rename from hal/src/fsfw_hal/linux/CommandExecutor.cpp rename to src/fsfw_hal/linux/CommandExecutor.cpp index 49c44ebf..27cf8aca 100644 --- a/hal/src/fsfw_hal/linux/CommandExecutor.cpp +++ b/src/fsfw_hal/linux/CommandExecutor.cpp @@ -23,7 +23,7 @@ ReturnValue_t CommandExecutor::load(std::string command, bool blocking, bool pri if (state == States::IDLE) { state = States::COMMAND_LOADED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t CommandExecutor::execute() { @@ -32,10 +32,12 @@ ReturnValue_t CommandExecutor::execute() { } else if (state == States::PENDING) { return COMMAND_PENDING; } + // Reset data in read vector + std::memset(readVec.data(), 0, readVec.size()); currentCmdFile = popen(currentCmd.c_str(), "r"); if (currentCmdFile == nullptr) { lastError = errno; - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (blocking) { ReturnValue_t result = executeBlocking(); @@ -46,7 +48,7 @@ ReturnValue_t CommandExecutor::execute() { waiter.fd = currentFd; } state = States::PENDING; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t CommandExecutor::close() { @@ -56,7 +58,7 @@ ReturnValue_t CommandExecutor::close() { pclose(currentCmdFile); } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void CommandExecutor::printLastError(std::string funcName) const { @@ -79,7 +81,7 @@ void CommandExecutor::setRingBuffer(SimpleRingBuffer* ringBuffer, ReturnValue_t CommandExecutor::check(bool& replyReceived) { if (blocking) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } switch (state) { case (States::IDLE): @@ -94,7 +96,7 @@ ReturnValue_t CommandExecutor::check(bool& replyReceived) { int result = poll(&waiter, 1, 0); switch (result) { case (0): { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; break; } case (1): { @@ -151,7 +153,7 @@ ReturnValue_t CommandExecutor::check(bool& replyReceived) { ReturnValue_t retval = EXECUTION_FINISHED; if (result != 0) { lastError = result; - retval = HasReturnvaluesIF::RETURN_FAILED; + retval = returnvalue::FAILED; } state = States::IDLE; currentCmdFile = nullptr; @@ -161,7 +163,7 @@ ReturnValue_t CommandExecutor::check(bool& replyReceived) { break; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void CommandExecutor::reset() { @@ -201,7 +203,9 @@ ReturnValue_t CommandExecutor::executeBlocking() { int result = pclose(currentCmdFile); if (result != 0) { lastError = result; - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } + +const std::vector& CommandExecutor::getReadVector() const { return readVec; } diff --git a/hal/src/fsfw_hal/linux/CommandExecutor.h b/src/fsfw_hal/linux/CommandExecutor.h similarity index 78% rename from hal/src/fsfw_hal/linux/CommandExecutor.h rename to src/fsfw_hal/linux/CommandExecutor.h index 90662c0f..80996bae 100644 --- a/hal/src/fsfw_hal/linux/CommandExecutor.h +++ b/src/fsfw_hal/linux/CommandExecutor.h @@ -7,7 +7,7 @@ #include #include "fsfw/returnvalues/FwClassIds.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" class SimpleRingBuffer; template @@ -31,27 +31,25 @@ class CommandExecutor { static constexpr uint8_t CLASS_ID = CLASS_ID::LINUX_OSAL; //! [EXPORT] : [COMMENT] Execution of the current command has finished - static constexpr ReturnValue_t EXECUTION_FINISHED = - HasReturnvaluesIF::makeReturnCode(CLASS_ID, 0); + static constexpr ReturnValue_t EXECUTION_FINISHED = returnvalue::makeCode(CLASS_ID, 0); //! [EXPORT] : [COMMENT] Command is pending. This will also be returned if the user tries //! to load another command but a command is still pending - static constexpr ReturnValue_t COMMAND_PENDING = HasReturnvaluesIF::makeReturnCode(CLASS_ID, 1); + static constexpr ReturnValue_t COMMAND_PENDING = returnvalue::makeCode(CLASS_ID, 1); //! [EXPORT] : [COMMENT] Some bytes have been read from the executing process - static constexpr ReturnValue_t BYTES_READ = HasReturnvaluesIF::makeReturnCode(CLASS_ID, 2); + static constexpr ReturnValue_t BYTES_READ = returnvalue::makeCode(CLASS_ID, 2); //! [EXPORT] : [COMMENT] Command execution failed - static constexpr ReturnValue_t COMMAND_ERROR = HasReturnvaluesIF::makeReturnCode(CLASS_ID, 3); + static constexpr ReturnValue_t COMMAND_ERROR = returnvalue::makeCode(CLASS_ID, 3); //! [EXPORT] : [COMMENT] - static constexpr ReturnValue_t NO_COMMAND_LOADED_OR_PENDING = - HasReturnvaluesIF::makeReturnCode(CLASS_ID, 4); - static constexpr ReturnValue_t PCLOSE_CALL_ERROR = HasReturnvaluesIF::makeReturnCode(CLASS_ID, 6); + static constexpr ReturnValue_t NO_COMMAND_LOADED_OR_PENDING = returnvalue::makeCode(CLASS_ID, 4); + static constexpr ReturnValue_t PCLOSE_CALL_ERROR = returnvalue::makeCode(CLASS_ID, 6); /** * Constructor. Is initialized with maximum size of internal buffer to read data from the * executed process. * @param maxSize */ - CommandExecutor(const size_t maxSize); + explicit CommandExecutor(size_t maxSize); /** * Load a new command which should be executed @@ -64,11 +62,11 @@ class CommandExecutor { /** * Execute the loaded command. * @return - * - In blocking mode, it will return RETURN_FAILED if + * - In blocking mode, it will return returnvalue::FAILED if * the result of the system call was not 0. The error value can be accessed using * getLastError * - In non-blocking mode, this call will start - * the execution and then return RETURN_OK + * the execution and then return returnvalue::OK */ ReturnValue_t execute(); /** @@ -77,8 +75,8 @@ class CommandExecutor { * @return * - BYTES_READ if bytes have been read from the executing process. It is recommended to call * check again after this - * - RETURN_OK execution is pending, but no bytes have been read from the executing process - * - RETURN_FAILED if execution has failed, error value can be accessed using getLastError + * - returnvalue::OK execution is pending, but no bytes have been read from the executing process + * - returnvalue::FAILED if execution has failed, error value can be accessed using getLastError * - EXECUTION_FINISHED if the process was executed successfully * - NO_COMMAND_LOADED_OR_PENDING self-explanatory * - COMMAND_ERROR internal poll error @@ -87,7 +85,7 @@ class CommandExecutor { /** * Abort the current command. Should normally not be necessary, check can be used to find * out whether command execution was successful - * @return RETURN_OK + * @return returnvalue::OK */ ReturnValue_t close(); @@ -109,6 +107,8 @@ class CommandExecutor { */ void reset(); + const std::vector& getReadVector() const; + private: std::string currentCmd; bool blocking = true; diff --git a/hal/src/fsfw_hal/linux/UnixFileGuard.cpp b/src/fsfw_hal/linux/UnixFileGuard.cpp similarity index 100% rename from hal/src/fsfw_hal/linux/UnixFileGuard.cpp rename to src/fsfw_hal/linux/UnixFileGuard.cpp diff --git a/hal/src/fsfw_hal/linux/UnixFileGuard.h b/src/fsfw_hal/linux/UnixFileGuard.h similarity index 86% rename from hal/src/fsfw_hal/linux/UnixFileGuard.h rename to src/fsfw_hal/linux/UnixFileGuard.h index d94234b6..3e4ddca8 100644 --- a/hal/src/fsfw_hal/linux/UnixFileGuard.h +++ b/src/fsfw_hal/linux/UnixFileGuard.h @@ -2,7 +2,7 @@ #define LINUX_UTILITY_UNIXFILEGUARD_H_ #include -#include +#include #include #include @@ -24,7 +24,7 @@ class UnixFileGuard { private: int* fileDescriptor = nullptr; - ReturnValue_t openStatus = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t openStatus = returnvalue::OK; }; #endif /* LINUX_UTILITY_UNIXFILEGUARD_H_ */ diff --git a/src/fsfw_hal/linux/gpio/CMakeLists.txt b/src/fsfw_hal/linux/gpio/CMakeLists.txt new file mode 100644 index 00000000..f6e7f2b0 --- /dev/null +++ b/src/fsfw_hal/linux/gpio/CMakeLists.txt @@ -0,0 +1,12 @@ +# This abstraction layer requires the gpiod library. You can install this +# library with "sudo apt-get install -y libgpiod-dev". If you are +# cross-compiling, you need to install the package before syncing the sysroot to +# your host computer. +find_library(LIB_GPIO gpiod) + +if(${LIB_GPIO} MATCHES LIB_GPIO-NOTFOUND) + message(STATUS "gpiod library not found, not linking against it") +else() + target_sources(${LIB_FSFW_NAME} PRIVATE LinuxLibgpioIF.cpp) + target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${LIB_GPIO}) +endif() diff --git a/hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.cpp b/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.cpp similarity index 91% rename from hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.cpp rename to src/fsfw_hal/linux/gpio/LinuxLibgpioIF.cpp index 3b9a21f7..cecc1f3f 100644 --- a/hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.cpp +++ b/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.cpp @@ -20,30 +20,33 @@ LinuxLibgpioIF::~LinuxLibgpioIF() { ReturnValue_t LinuxLibgpioIF::addGpios(GpioCookie* gpioCookie) { ReturnValue_t result; if (gpioCookie == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "LinuxLibgpioIF::addGpios: Invalid cookie" << std::endl; - return RETURN_FAILED; +#endif + return returnvalue::FAILED; } GpioMap mapToAdd = gpioCookie->getGpioMap(); /* Check whether this ID already exists in the map and remove duplicates */ result = checkForConflicts(mapToAdd); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = configureGpios(mapToAdd); - if (result != RETURN_OK) { - return RETURN_FAILED; + if (result != returnvalue::OK) { + return returnvalue::FAILED; } /* Register new GPIOs in gpioMap */ gpioMap.insert(mapToAdd.begin(), mapToAdd.end()); - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) { + ReturnValue_t result = returnvalue::OK; for (auto& gpioConfig : mapToAdd) { auto& gpioType = gpioConfig.second->gpioType; switch (gpioType) { @@ -55,7 +58,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) { if (regularGpio == nullptr) { return GPIO_INVALID_INSTANCE; } - configureGpioByChip(gpioConfig.first, *regularGpio); + result = configureGpioByChip(gpioConfig.first, *regularGpio); break; } case (gpio::GpioTypes::GPIO_REGULAR_BY_LABEL): { @@ -63,7 +66,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) { if (regularGpio == nullptr) { return GPIO_INVALID_INSTANCE; } - configureGpioByLabel(gpioConfig.first, *regularGpio); + result = configureGpioByLabel(gpioConfig.first, *regularGpio); break; } case (gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME): { @@ -71,7 +74,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) { if (regularGpio == nullptr) { return GPIO_INVALID_INSTANCE; } - configureGpioByLineName(gpioConfig.first, *regularGpio); + result = configureGpioByLineName(gpioConfig.first, *regularGpio); break; } case (gpio::GpioTypes::CALLBACK): { @@ -83,8 +86,11 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) { gpioCallback->initValue, gpioCallback->callbackArgs); } } + if (result != returnvalue::OK) { + return GPIO_INIT_FAILED; + } } - return RETURN_OK; + return result; } ReturnValue_t LinuxLibgpioIF::configureGpioByLabel(gpioId_t gpioId, @@ -92,9 +98,11 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByLabel(gpioId_t gpioId, std::string& label = gpioByLabel.label; struct gpiod_chip* chip = gpiod_chip_open_by_label(label.c_str()); if (chip == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "LinuxLibgpioIF::configureGpioByLabel: Failed to open gpio from gpio " << "group with label " << label << ". Gpio ID: " << gpioId << std::endl; - return RETURN_FAILED; +#endif + return returnvalue::FAILED; } std::string failOutput = "label: " + label; return configureRegularGpio(gpioId, chip, gpioByLabel, failOutput); @@ -104,9 +112,11 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByChip(gpioId_t gpioId, GpiodRegularB std::string& chipname = gpioByChip.chipname; struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname.c_str()); if (chip == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "LinuxLibgpioIF::configureGpioByChip: Failed to open chip " << chipname << ". Gpio ID: " << gpioId << std::endl; - return RETURN_FAILED; +#endif + return returnvalue::FAILED; } std::string failOutput = "chipname: " + chipname; return configureRegularGpio(gpioId, chip, gpioByChip, failOutput); @@ -122,16 +132,18 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByLineName(gpioId_t gpioId, gpiod_ctxless_find_line(lineName.c_str(), chipname, MAX_CHIPNAME_LENGTH, &lineOffset); if (result != LINE_FOUND) { parseFindeLineResult(result, lineName); - return RETURN_FAILED; + return returnvalue::FAILED; } gpioByLineName.lineNum = static_cast(lineOffset); struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname); if (chip == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "LinuxLibgpioIF::configureGpioByLineName: Failed to open chip " << chipname << ". callback(gpioMapIter->first, gpio::GpioOperation::WRITE, gpio::Levels::HIGH, gpioCallback->callbackArgs); - return RETURN_OK; + return returnvalue::OK; } return GPIO_TYPE_FAILURE; } @@ -252,7 +270,7 @@ ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) { } gpioCallback->callback(gpioMapIter->first, gpio::GpioOperation::WRITE, gpio::Levels::LOW, gpioCallback->callbackArgs); - return RETURN_OK; + return returnvalue::OK; } return GPIO_TYPE_FAILURE; } @@ -273,7 +291,7 @@ ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId, GpiodRegularBase& regul return DRIVE_GPIO_FAILURE; } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, int* gpioState) { @@ -303,14 +321,14 @@ ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, int* gpioState) { } gpioCallback->callback(gpioMapIter->first, gpio::GpioOperation::READ, gpio::Levels::NONE, gpioCallback->callbackArgs); - return RETURN_OK; + return returnvalue::OK; } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t LinuxLibgpioIF::checkForConflicts(GpioMap& mapToAdd) { - ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t status = returnvalue::OK; + ReturnValue_t result = returnvalue::OK; for (auto& gpioConfig : mapToAdd) { switch (gpioConfig.second->gpioType) { case (gpio::GpioTypes::GPIO_REGULAR_BY_CHIP): @@ -322,7 +340,7 @@ ReturnValue_t LinuxLibgpioIF::checkForConflicts(GpioMap& mapToAdd) { } // Check for conflicts and remove duplicates if necessary result = checkForConflictsById(gpioConfig.first, gpioConfig.second->gpioType, mapToAdd); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { status = result; } break; @@ -334,7 +352,7 @@ ReturnValue_t LinuxLibgpioIF::checkForConflicts(GpioMap& mapToAdd) { } // Check for conflicts and remove duplicates if necessary result = checkForConflictsById(gpioConfig.first, gpioConfig.second->gpioType, mapToAdd); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { status = result; } break; @@ -408,7 +426,7 @@ ReturnValue_t LinuxLibgpioIF::checkForConflictsById(gpioId_t gpioIdToCheck, mapToAdd.erase(gpioIdToCheck); return GPIO_DUPLICATE_DETECTED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void LinuxLibgpioIF::parseFindeLineResult(int result, std::string& lineName) { diff --git a/hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.h b/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.h similarity index 80% rename from hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.h rename to src/fsfw_hal/linux/gpio/LinuxLibgpioIF.h index 7d49e6e2..bb8e890d 100644 --- a/hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.h +++ b/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.h @@ -19,16 +19,12 @@ class LinuxLibgpioIF : public GpioIF, public SystemObject { public: static const uint8_t gpioRetvalId = CLASS_ID::HAL_GPIO; - static constexpr ReturnValue_t UNKNOWN_GPIO_ID = - HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 1); - static constexpr ReturnValue_t DRIVE_GPIO_FAILURE = - HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 2); - static constexpr ReturnValue_t GPIO_TYPE_FAILURE = - HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 3); - static constexpr ReturnValue_t GPIO_INVALID_INSTANCE = - HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 4); - static constexpr ReturnValue_t GPIO_DUPLICATE_DETECTED = - HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 5); + static constexpr ReturnValue_t UNKNOWN_GPIO_ID = returnvalue::makeCode(gpioRetvalId, 1); + static constexpr ReturnValue_t DRIVE_GPIO_FAILURE = returnvalue::makeCode(gpioRetvalId, 2); + static constexpr ReturnValue_t GPIO_TYPE_FAILURE = returnvalue::makeCode(gpioRetvalId, 3); + static constexpr ReturnValue_t GPIO_INVALID_INSTANCE = returnvalue::makeCode(gpioRetvalId, 4); + static constexpr ReturnValue_t GPIO_DUPLICATE_DETECTED = returnvalue::makeCode(gpioRetvalId, 5); + static constexpr ReturnValue_t GPIO_INIT_FAILED = returnvalue::makeCode(gpioRetvalId, 6); LinuxLibgpioIF(object_id_t objectId); virtual ~LinuxLibgpioIF(); @@ -69,7 +65,7 @@ class LinuxLibgpioIF : public GpioIF, public SystemObject { * * @param mapToAdd The GPIOs which shall be added to the gpioMap. * - * @return RETURN_OK if successful, otherwise RETURN_FAILED + * @return returnvalue::OK if successful, otherwise returnvalue::FAILED */ ReturnValue_t checkForConflicts(GpioMap& mapToAdd); diff --git a/src/fsfw_hal/linux/i2c/CMakeLists.txt b/src/fsfw_hal/linux/i2c/CMakeLists.txt new file mode 100644 index 00000000..b94bdc99 --- /dev/null +++ b/src/fsfw_hal/linux/i2c/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PUBLIC I2cComIF.cpp I2cCookie.cpp) diff --git a/hal/src/fsfw_hal/linux/i2c/I2cComIF.cpp b/src/fsfw_hal/linux/i2c/I2cComIF.cpp similarity index 76% rename from hal/src/fsfw_hal/linux/i2c/I2cComIF.cpp rename to src/fsfw_hal/linux/i2c/I2cComIF.cpp index 4f53dc1f..e3e50040 100644 --- a/hal/src/fsfw_hal/linux/i2c/I2cComIF.cpp +++ b/src/fsfw_hal/linux/i2c/I2cComIF.cpp @@ -41,7 +41,7 @@ ReturnValue_t I2cComIF::initializeInterface(CookieIF* cookie) { i2cAddress = i2cCookie->getAddress(); - i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); + auto i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); if (i2cDeviceMapIter == i2cDeviceMap.end()) { size_t maxReplyLen = i2cCookie->getMaxReplyLen(); I2cInstance i2cInstance = {std::vector(maxReplyLen), 0}; @@ -52,16 +52,16 @@ ReturnValue_t I2cComIF::initializeInterface(CookieIF* cookie) { << i2cAddress << "to I2C device " << "map" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "I2cComIF::initializeInterface: Device with address " << i2cAddress << "already in use" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) { @@ -73,11 +73,11 @@ ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, s #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "I2cComIF::sendMessage: Send Data is nullptr" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } if (sendLen == 0) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } I2cCookie* i2cCookie = dynamic_cast(cookie); @@ -89,22 +89,22 @@ ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, s } address_t i2cAddress = i2cCookie->getAddress(); - i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); + auto i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); if (i2cDeviceMapIter == i2cDeviceMap.end()) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "I2cComIF::sendMessage: i2cAddress of Cookie not " << "registered in i2cDeviceMap" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } deviceFile = i2cCookie->getDeviceFile(); UnixFileGuard fileHelper(deviceFile, &fd, O_RDWR, "I2cComIF::sendMessage"); - if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) { + if (fileHelper.getOpenResult() != returnvalue::OK) { return fileHelper.getOpenResult(); } result = openDevice(deviceFile, i2cAddress, &fd); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -114,17 +114,17 @@ ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, s "device with error code " << errno << ". Error description: " << strerror(errno) << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } #if FSFW_HAL_I2C_WIRETAPPING == 1 sif::info << "Sent I2C data to bus " << deviceFile << ":" << std::endl; arrayprinter::print(sendData, sendLen); #endif - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } -ReturnValue_t I2cComIF::getSendSuccess(CookieIF* cookie) { return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t I2cComIF::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; } ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLen) { ReturnValue_t result; @@ -132,7 +132,7 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe std::string deviceFile; if (requestLen == 0) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } I2cCookie* i2cCookie = dynamic_cast(cookie); @@ -140,29 +140,27 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "I2cComIF::requestReceiveMessage: Invalid I2C Cookie!" << std::endl; #endif - i2cDeviceMapIter->second.replyLen = 0; return NULLPOINTER; } address_t i2cAddress = i2cCookie->getAddress(); - i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); + auto i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); if (i2cDeviceMapIter == i2cDeviceMap.end()) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "I2cComIF::requestReceiveMessage: i2cAddress of Cookie not " << "registered in i2cDeviceMap" << std::endl; #endif - i2cDeviceMapIter->second.replyLen = 0; - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } + i2cDeviceMapIter->second.replyLen = 0; deviceFile = i2cCookie->getDeviceFile(); UnixFileGuard fileHelper(deviceFile, &fd, O_RDWR, "I2cComIF::requestReceiveMessage"); - if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) { + if (fileHelper.getOpenResult() != returnvalue::OK) { return fileHelper.getOpenResult(); } result = openDevice(deviceFile, i2cAddress, &fd); - if (result != HasReturnvaluesIF::RETURN_OK) { - i2cDeviceMapIter->second.replyLen = 0; + if (result != returnvalue::OK) { return result; } @@ -170,19 +168,20 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe int readLen = read(fd, replyBuffer, requestLen); if (readLen != static_cast(requestLen)) { -#if FSFW_VERBOSE_LEVEL >= 1 and FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "I2cComIF::requestReceiveMessage: Reading from I2C " - << "device failed with error code " << errno << ". Description" - << " of error: " << strerror(errno) << std::endl; - sif::error << "I2cComIF::requestReceiveMessage: Read only " << readLen << " from " << requestLen - << " bytes" << std::endl; -#endif - i2cDeviceMapIter->second.replyLen = 0; +#if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "I2cComIF::requestReceiveMessage: Read " << readLen << " of " << requestLen - << " bytes" << std::endl; + if (readLen < 0) { + sif::warning << "I2cComIF::requestReceiveMessage: Reading from I2C " + << "device failed with error code " << errno << " | " << strerror(errno) + << std::endl; + } else { + sif::warning << "I2cComIF::requestReceiveMessage: Read only " << readLen << " from " + << requestLen << " bytes" << std::endl; + } +#else #endif - return HasReturnvaluesIF::RETURN_FAILED; +#endif + return returnvalue::FAILED; } #if FSFW_HAL_I2C_WIRETAPPING == 1 @@ -191,7 +190,7 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe #endif i2cDeviceMapIter->second.replyLen = requestLen; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t I2cComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) { @@ -204,18 +203,18 @@ ReturnValue_t I2cComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, } address_t i2cAddress = i2cCookie->getAddress(); - i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); + auto i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); if (i2cDeviceMapIter == i2cDeviceMap.end()) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "I2cComIF::readReceivedMessage: i2cAddress of Cookie not " << "found in i2cDeviceMap" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } *buffer = i2cDeviceMapIter->second.replyBuffer.data(); *size = i2cDeviceMapIter->second.replyLen; - - return HasReturnvaluesIF::RETURN_OK; + i2cDeviceMapIter->second.replyLen = 0; + return returnvalue::OK; } ReturnValue_t I2cComIF::openDevice(std::string deviceFile, address_t i2cAddress, @@ -231,7 +230,7 @@ ReturnValue_t I2cComIF::openDevice(std::string deviceFile, address_t i2cAddress, sif::printWarning("Error description: %s\n", strerror(errno)); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/hal/src/fsfw_hal/linux/i2c/I2cComIF.h b/src/fsfw_hal/linux/i2c/I2cComIF.h similarity index 92% rename from hal/src/fsfw_hal/linux/i2c/I2cComIF.h rename to src/fsfw_hal/linux/i2c/I2cComIF.h index cf3bbe49..8c44cee0 100644 --- a/hal/src/fsfw_hal/linux/i2c/I2cComIF.h +++ b/src/fsfw_hal/linux/i2c/I2cComIF.h @@ -36,12 +36,10 @@ class I2cComIF : public DeviceCommunicationIF, public SystemObject { }; using I2cDeviceMap = std::unordered_map; - using I2cDeviceMapIter = I2cDeviceMap::iterator; /* In this map all i2c devices will be registered with their address and * the appropriate file descriptor will be stored */ I2cDeviceMap i2cDeviceMap; - I2cDeviceMapIter i2cDeviceMapIter; /** * @brief This function opens an I2C device and binds the opened file @@ -49,7 +47,7 @@ class I2cComIF : public DeviceCommunicationIF, public SystemObject { * @param deviceFile The name of the device file. E.g. i2c-0 * @param i2cAddress The address of the i2c slave device. * @param fileDescriptor Pointer to device descriptor. - * @return RETURN_OK if successful, otherwise RETURN_FAILED. + * @return returnvalue::OK if successful, otherwise returnvalue::FAILED. */ ReturnValue_t openDevice(std::string deviceFile, address_t i2cAddress, int *fileDescriptor); }; diff --git a/hal/src/fsfw_hal/linux/i2c/I2cCookie.cpp b/src/fsfw_hal/linux/i2c/I2cCookie.cpp similarity index 100% rename from hal/src/fsfw_hal/linux/i2c/I2cCookie.cpp rename to src/fsfw_hal/linux/i2c/I2cCookie.cpp diff --git a/hal/src/fsfw_hal/linux/i2c/I2cCookie.h b/src/fsfw_hal/linux/i2c/I2cCookie.h similarity index 100% rename from hal/src/fsfw_hal/linux/i2c/I2cCookie.h rename to src/fsfw_hal/linux/i2c/I2cCookie.h diff --git a/src/fsfw_hal/linux/rpi/CMakeLists.txt b/src/fsfw_hal/linux/rpi/CMakeLists.txt new file mode 100644 index 00000000..3a865037 --- /dev/null +++ b/src/fsfw_hal/linux/rpi/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE GpioRPi.cpp) diff --git a/hal/src/fsfw_hal/linux/rpi/GpioRPi.cpp b/src/fsfw_hal/linux/rpi/GpioRPi.cpp similarity index 90% rename from hal/src/fsfw_hal/linux/rpi/GpioRPi.cpp rename to src/fsfw_hal/linux/rpi/GpioRPi.cpp index d3c0a577..a6b097bf 100644 --- a/hal/src/fsfw_hal/linux/rpi/GpioRPi.cpp +++ b/src/fsfw_hal/linux/rpi/GpioRPi.cpp @@ -9,7 +9,7 @@ ReturnValue_t gpio::createRpiGpioConfig(GpioCookie* cookie, gpioId_t gpioId, int std::string consumer, gpio::Direction direction, gpio::Levels initValue) { if (cookie == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } auto config = new GpiodRegularByChip(); @@ -30,9 +30,9 @@ ReturnValue_t gpio::createRpiGpioConfig(GpioCookie* cookie, gpioId_t gpioId, int sif::printError("createRpiGpioConfig: BCM pin %d invalid!\n", bcmPin); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } config->lineNum = bcmPin; cookie->addGpio(gpioId, config); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/hal/src/fsfw_hal/linux/rpi/GpioRPi.h b/src/fsfw_hal/linux/rpi/GpioRPi.h similarity index 94% rename from hal/src/fsfw_hal/linux/rpi/GpioRPi.h rename to src/fsfw_hal/linux/rpi/GpioRPi.h index 8ca7065a..bec4c33d 100644 --- a/hal/src/fsfw_hal/linux/rpi/GpioRPi.h +++ b/src/fsfw_hal/linux/rpi/GpioRPi.h @@ -1,7 +1,7 @@ #ifndef BSP_RPI_GPIO_GPIORPI_H_ #define BSP_RPI_GPIO_GPIORPI_H_ -#include +#include #include "../../common/gpio/gpioDefinitions.h" diff --git a/src/fsfw_hal/linux/serial/CMakeLists.txt b/src/fsfw_hal/linux/serial/CMakeLists.txt new file mode 100644 index 00000000..07d20d29 --- /dev/null +++ b/src/fsfw_hal/linux/serial/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(${LIB_FSFW_NAME} PUBLIC SerialComIF.cpp SerialCookie.cpp + helper.cpp) diff --git a/hal/src/fsfw_hal/linux/uart/UartComIF.cpp b/src/fsfw_hal/linux/serial/SerialComIF.cpp similarity index 58% rename from hal/src/fsfw_hal/linux/uart/UartComIF.cpp rename to src/fsfw_hal/linux/serial/SerialComIF.cpp index 5aa72138..177d74e4 100644 --- a/hal/src/fsfw_hal/linux/uart/UartComIF.cpp +++ b/src/fsfw_hal/linux/serial/SerialComIF.cpp @@ -1,4 +1,4 @@ -#include "UartComIF.h" +#include "SerialComIF.h" #include #include @@ -11,19 +11,18 @@ #include "fsfw/serviceinterface.h" #include "fsfw_hal/linux/utility.h" -UartComIF::UartComIF(object_id_t objectId) : SystemObject(objectId) {} +SerialComIF::SerialComIF(object_id_t objectId) : SystemObject(objectId) {} -UartComIF::~UartComIF() {} +SerialComIF::~SerialComIF() {} -ReturnValue_t UartComIF::initializeInterface(CookieIF* cookie) { +ReturnValue_t SerialComIF::initializeInterface(CookieIF* cookie) { std::string deviceFile; - UartDeviceMapIter uartDeviceMapIter; if (cookie == nullptr) { return NULLPOINTER; } - UartCookie* uartCookie = dynamic_cast(cookie); + SerialCookie* uartCookie = dynamic_cast(cookie); if (uartCookie == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "UartComIF::initializeInterface: Invalid UART Cookie!" << std::endl; @@ -33,11 +32,11 @@ ReturnValue_t UartComIF::initializeInterface(CookieIF* cookie) { deviceFile = uartCookie->getDeviceFile(); - uartDeviceMapIter = uartDeviceMap.find(deviceFile); + auto uartDeviceMapIter = uartDeviceMap.find(deviceFile); if (uartDeviceMapIter == uartDeviceMap.end()) { int fileDescriptor = configureUartPort(uartCookie); if (fileDescriptor < 0) { - return RETURN_FAILED; + return returnvalue::FAILED; } size_t maxReplyLen = uartCookie->getMaxReplyLen(); UartElements uartElements = {fileDescriptor, std::vector(maxReplyLen), 0}; @@ -47,20 +46,20 @@ ReturnValue_t UartComIF::initializeInterface(CookieIF* cookie) { sif::warning << "UartComIF::initializeInterface: Failed to insert device " << deviceFile << "to UART device map" << std::endl; #endif - return RETURN_FAILED; + return returnvalue::FAILED; } } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "UartComIF::initializeInterface: UART device " << deviceFile << " already in use" << std::endl; #endif - return RETURN_FAILED; + return returnvalue::FAILED; } - return RETURN_OK; + return returnvalue::OK; } -int UartComIF::configureUartPort(UartCookie* uartCookie) { +int SerialComIF::configureUartPort(SerialCookie* uartCookie) { struct termios options = {}; std::string deviceFile = uartCookie->getDeviceFile(); @@ -89,11 +88,11 @@ int UartComIF::configureUartPort(UartCookie* uartCookie) { return fd; } - setParityOptions(&options, uartCookie); + uart::setParity(options, uartCookie->getParity()); setStopBitOptions(&options, uartCookie); setDatasizeOptions(&options, uartCookie); setFixedOptions(&options); - setUartMode(&options, *uartCookie); + uart::setMode(options, uartCookie->getUartMode()); if (uartCookie->getInputShouldBeFlushed()) { tcflush(fd, TCIFLUSH); } @@ -102,7 +101,7 @@ int UartComIF::configureUartPort(UartCookie* uartCookie) { options.c_cc[VTIME] = 0; options.c_cc[VMIN] = 0; - configureBaudrate(&options, uartCookie); + uart::setBaudrate(options, uartCookie->getBaudrate()); /* Save option settings */ if (tcsetattr(fd, TCSANOW, &options) != 0) { @@ -115,24 +114,7 @@ int UartComIF::configureUartPort(UartCookie* uartCookie) { return fd; } -void UartComIF::setParityOptions(struct termios* options, UartCookie* uartCookie) { - /* Clear parity bit */ - options->c_cflag &= ~PARENB; - switch (uartCookie->getParity()) { - case Parity::EVEN: - options->c_cflag |= PARENB; - options->c_cflag &= ~PARODD; - break; - case Parity::ODD: - options->c_cflag |= PARENB; - options->c_cflag |= PARODD; - break; - default: - break; - } -} - -void UartComIF::setStopBitOptions(struct termios* options, UartCookie* uartCookie) { +void SerialComIF::setStopBitOptions(struct termios* options, SerialCookie* uartCookie) { /* Clear stop field. Sets stop bit to one bit */ options->c_cflag &= ~CSTOPB; switch (uartCookie->getStopBits()) { @@ -144,7 +126,7 @@ void UartComIF::setStopBitOptions(struct termios* options, UartCookie* uartCooki } } -void UartComIF::setDatasizeOptions(struct termios* options, UartCookie* uartCookie) { +void SerialComIF::setDatasizeOptions(struct termios* options, SerialCookie* uartCookie) { /* Clear size bits */ options->c_cflag &= ~CSIZE; switch (uartCookie->getBitsPerWord()) { @@ -168,7 +150,7 @@ void UartComIF::setDatasizeOptions(struct termios* options, UartCookie* uartCook } } -void UartComIF::setFixedOptions(struct termios* options) { +void SerialComIF::setFixedOptions(struct termios* options) { /* Disable RTS/CTS hardware flow control */ options->c_cflag &= ~CRTSCTS; /* Turn on READ & ignore ctrl lines (CLOCAL = 1) */ @@ -191,153 +173,22 @@ void UartComIF::setFixedOptions(struct termios* options) { options->c_oflag &= ~ONLCR; } -void UartComIF::configureBaudrate(struct termios* options, UartCookie* uartCookie) { - switch (uartCookie->getBaudrate()) { - case UartBaudRate::RATE_50: - cfsetispeed(options, B50); - cfsetospeed(options, B50); - break; - case UartBaudRate::RATE_75: - cfsetispeed(options, B75); - cfsetospeed(options, B75); - break; - case UartBaudRate::RATE_110: - cfsetispeed(options, B110); - cfsetospeed(options, B110); - break; - case UartBaudRate::RATE_134: - cfsetispeed(options, B134); - cfsetospeed(options, B134); - break; - case UartBaudRate::RATE_150: - cfsetispeed(options, B150); - cfsetospeed(options, B150); - break; - case UartBaudRate::RATE_200: - cfsetispeed(options, B200); - cfsetospeed(options, B200); - break; - case UartBaudRate::RATE_300: - cfsetispeed(options, B300); - cfsetospeed(options, B300); - break; - case UartBaudRate::RATE_600: - cfsetispeed(options, B600); - cfsetospeed(options, B600); - break; - case UartBaudRate::RATE_1200: - cfsetispeed(options, B1200); - cfsetospeed(options, B1200); - break; - case UartBaudRate::RATE_1800: - cfsetispeed(options, B1800); - cfsetospeed(options, B1800); - break; - case UartBaudRate::RATE_2400: - cfsetispeed(options, B2400); - cfsetospeed(options, B2400); - break; - case UartBaudRate::RATE_4800: - cfsetispeed(options, B4800); - cfsetospeed(options, B4800); - break; - case UartBaudRate::RATE_9600: - cfsetispeed(options, B9600); - cfsetospeed(options, B9600); - break; - case UartBaudRate::RATE_19200: - cfsetispeed(options, B19200); - cfsetospeed(options, B19200); - break; - case UartBaudRate::RATE_38400: - cfsetispeed(options, B38400); - cfsetospeed(options, B38400); - break; - case UartBaudRate::RATE_57600: - cfsetispeed(options, B57600); - cfsetospeed(options, B57600); - break; - case UartBaudRate::RATE_115200: - cfsetispeed(options, B115200); - cfsetospeed(options, B115200); - break; - case UartBaudRate::RATE_230400: - cfsetispeed(options, B230400); - cfsetospeed(options, B230400); - break; - case UartBaudRate::RATE_460800: - cfsetispeed(options, B460800); - cfsetospeed(options, B460800); - break; - case UartBaudRate::RATE_500000: - cfsetispeed(options, B500000); - cfsetospeed(options, B500000); - break; - case UartBaudRate::RATE_576000: - cfsetispeed(options, B576000); - cfsetospeed(options, B576000); - break; - case UartBaudRate::RATE_921600: - cfsetispeed(options, B921600); - cfsetospeed(options, B921600); - break; - case UartBaudRate::RATE_1000000: - cfsetispeed(options, B1000000); - cfsetospeed(options, B1000000); - break; - case UartBaudRate::RATE_1152000: - cfsetispeed(options, B1152000); - cfsetospeed(options, B1152000); - break; - case UartBaudRate::RATE_1500000: - cfsetispeed(options, B1500000); - cfsetospeed(options, B1500000); - break; - case UartBaudRate::RATE_2000000: - cfsetispeed(options, B2000000); - cfsetospeed(options, B2000000); - break; - case UartBaudRate::RATE_2500000: - cfsetispeed(options, B2500000); - cfsetospeed(options, B2500000); - break; - case UartBaudRate::RATE_3000000: - cfsetispeed(options, B3000000); - cfsetospeed(options, B3000000); - break; - case UartBaudRate::RATE_3500000: - cfsetispeed(options, B3500000); - cfsetospeed(options, B3500000); - break; - case UartBaudRate::RATE_4000000: - cfsetispeed(options, B4000000); - cfsetospeed(options, B4000000); - break; - default: -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl; -#endif - break; - } -} - -ReturnValue_t UartComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) { +ReturnValue_t SerialComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) { int fd = 0; std::string deviceFile; - UartDeviceMapIter uartDeviceMapIter; if (sendLen == 0) { - return RETURN_OK; + return returnvalue::OK; } if (sendData == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "UartComIF::sendMessage: Send data is nullptr" << std::endl; #endif - return RETURN_FAILED; + return returnvalue::FAILED; } - UartCookie* uartCookie = dynamic_cast(cookie); + SerialCookie* uartCookie = dynamic_cast(cookie); if (uartCookie == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "UartComIF::sendMessasge: Invalid UART Cookie!" << std::endl; @@ -346,13 +197,13 @@ ReturnValue_t UartComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, } deviceFile = uartCookie->getDeviceFile(); - uartDeviceMapIter = uartDeviceMap.find(deviceFile); + auto uartDeviceMapIter = uartDeviceMap.find(deviceFile); if (uartDeviceMapIter == uartDeviceMap.end()) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::debug << "UartComIF::sendMessage: Device file " << deviceFile << "not in UART map" << std::endl; #endif - return RETURN_FAILED; + return returnvalue::FAILED; } fd = uartDeviceMapIter->second.fileDescriptor; @@ -362,19 +213,18 @@ ReturnValue_t UartComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, sif::error << "UartComIF::sendMessage: Failed to send data with error code " << errno << ": Error description: " << strerror(errno) << std::endl; #endif - return RETURN_FAILED; + return returnvalue::FAILED; } - return RETURN_OK; + return returnvalue::OK; } -ReturnValue_t UartComIF::getSendSuccess(CookieIF* cookie) { return RETURN_OK; } +ReturnValue_t SerialComIF::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; } -ReturnValue_t UartComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLen) { +ReturnValue_t SerialComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLen) { std::string deviceFile; - UartDeviceMapIter uartDeviceMapIter; - UartCookie* uartCookie = dynamic_cast(cookie); + SerialCookie* uartCookie = dynamic_cast(cookie); if (uartCookie == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::debug << "UartComIF::requestReceiveMessage: Invalid Uart Cookie!" << std::endl; @@ -384,10 +234,10 @@ ReturnValue_t UartComIF::requestReceiveMessage(CookieIF* cookie, size_t requestL UartModes uartMode = uartCookie->getUartMode(); deviceFile = uartCookie->getDeviceFile(); - uartDeviceMapIter = uartDeviceMap.find(deviceFile); + auto uartDeviceMapIter = uartDeviceMap.find(deviceFile); if (uartMode == UartModes::NON_CANONICAL and requestLen == 0) { - return RETURN_OK; + return returnvalue::OK; } if (uartDeviceMapIter == uartDeviceMap.end()) { @@ -395,7 +245,7 @@ ReturnValue_t UartComIF::requestReceiveMessage(CookieIF* cookie, size_t requestL sif::debug << "UartComIF::requestReceiveMessage: Device file " << deviceFile << " not in uart map" << std::endl; #endif - return RETURN_FAILED; + return returnvalue::FAILED; } if (uartMode == UartModes::CANONICAL) { @@ -403,13 +253,13 @@ ReturnValue_t UartComIF::requestReceiveMessage(CookieIF* cookie, size_t requestL } else if (uartMode == UartModes::NON_CANONICAL) { return handleNoncanonicalRead(*uartCookie, uartDeviceMapIter, requestLen); } else { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } -ReturnValue_t UartComIF::handleCanonicalRead(UartCookie& uartCookie, UartDeviceMapIter& iter, - size_t requestLen) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; +ReturnValue_t SerialComIF::handleCanonicalRead(SerialCookie& uartCookie, + UartDeviceMap::iterator& iter, size_t requestLen) { + ReturnValue_t result = returnvalue::OK; uint8_t maxReadCycles = uartCookie.getReadCycles(); uint8_t currentReadCycles = 0; int bytesRead = 0; @@ -452,7 +302,7 @@ ReturnValue_t UartComIF::handleCanonicalRead(UartCookie& uartCookie, UartDeviceM strerror(errno)); #endif #endif - return RETURN_FAILED; + return returnvalue::FAILED; } } else if (bytesRead > 0) { @@ -465,8 +315,9 @@ ReturnValue_t UartComIF::handleCanonicalRead(UartCookie& uartCookie, UartDeviceM return result; } -ReturnValue_t UartComIF::handleNoncanonicalRead(UartCookie& uartCookie, UartDeviceMapIter& iter, - size_t requestLen) { +ReturnValue_t SerialComIF::handleNoncanonicalRead(SerialCookie& uartCookie, + UartDeviceMap::iterator& iter, + size_t requestLen) { int fd = iter->second.fileDescriptor; auto bufferPtr = iter->second.replyBuffer.data(); // Size check to prevent buffer overflow @@ -485,25 +336,24 @@ ReturnValue_t UartComIF::handleNoncanonicalRead(UartCookie& uartCookie, UartDevi } int bytesRead = read(fd, bufferPtr, requestLen); if (bytesRead < 0) { - return RETURN_FAILED; + return returnvalue::FAILED; } else if (bytesRead != static_cast(requestLen)) { if (uartCookie.isReplySizeFixed()) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "UartComIF::requestReceiveMessage: Only read " << bytesRead << " of " << requestLen << " bytes" << std::endl; #endif - return RETURN_FAILED; + return returnvalue::FAILED; } } iter->second.replyLen = bytesRead; - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } -ReturnValue_t UartComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) { +ReturnValue_t SerialComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) { std::string deviceFile; - UartDeviceMapIter uartDeviceMapIter; - UartCookie* uartCookie = dynamic_cast(cookie); + SerialCookie* uartCookie = dynamic_cast(cookie); if (uartCookie == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::debug << "UartComIF::readReceivedMessage: Invalid uart cookie!" << std::endl; @@ -512,13 +362,13 @@ ReturnValue_t UartComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, } deviceFile = uartCookie->getDeviceFile(); - uartDeviceMapIter = uartDeviceMap.find(deviceFile); + auto uartDeviceMapIter = uartDeviceMap.find(deviceFile); if (uartDeviceMapIter == uartDeviceMap.end()) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::debug << "UartComIF::readReceivedMessage: Device file " << deviceFile << " not in uart map" << std::endl; #endif - return RETURN_FAILED; + return returnvalue::FAILED; } *buffer = uartDeviceMapIter->second.replyBuffer.data(); @@ -527,13 +377,12 @@ ReturnValue_t UartComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, /* Length is reset to 0 to prevent reading the same data twice */ uartDeviceMapIter->second.replyLen = 0; - return RETURN_OK; + return returnvalue::OK; } -ReturnValue_t UartComIF::flushUartRxBuffer(CookieIF* cookie) { +ReturnValue_t SerialComIF::flushUartRxBuffer(CookieIF* cookie) { std::string deviceFile; - UartDeviceMapIter uartDeviceMapIter; - UartCookie* uartCookie = dynamic_cast(cookie); + SerialCookie* uartCookie = dynamic_cast(cookie); if (uartCookie == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "UartComIF::flushUartRxBuffer: Invalid uart cookie!" << std::endl; @@ -541,19 +390,18 @@ ReturnValue_t UartComIF::flushUartRxBuffer(CookieIF* cookie) { return NULLPOINTER; } deviceFile = uartCookie->getDeviceFile(); - uartDeviceMapIter = uartDeviceMap.find(deviceFile); + auto uartDeviceMapIter = uartDeviceMap.find(deviceFile); if (uartDeviceMapIter != uartDeviceMap.end()) { int fd = uartDeviceMapIter->second.fileDescriptor; tcflush(fd, TCIFLUSH); - return RETURN_OK; + return returnvalue::OK; } - return RETURN_FAILED; + return returnvalue::FAILED; } -ReturnValue_t UartComIF::flushUartTxBuffer(CookieIF* cookie) { +ReturnValue_t SerialComIF::flushUartTxBuffer(CookieIF* cookie) { std::string deviceFile; - UartDeviceMapIter uartDeviceMapIter; - UartCookie* uartCookie = dynamic_cast(cookie); + SerialCookie* uartCookie = dynamic_cast(cookie); if (uartCookie == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "UartComIF::flushUartTxBuffer: Invalid uart cookie!" << std::endl; @@ -561,19 +409,18 @@ ReturnValue_t UartComIF::flushUartTxBuffer(CookieIF* cookie) { return NULLPOINTER; } deviceFile = uartCookie->getDeviceFile(); - uartDeviceMapIter = uartDeviceMap.find(deviceFile); + auto uartDeviceMapIter = uartDeviceMap.find(deviceFile); if (uartDeviceMapIter != uartDeviceMap.end()) { int fd = uartDeviceMapIter->second.fileDescriptor; tcflush(fd, TCOFLUSH); - return RETURN_OK; + return returnvalue::OK; } - return RETURN_FAILED; + return returnvalue::FAILED; } -ReturnValue_t UartComIF::flushUartTxAndRxBuf(CookieIF* cookie) { +ReturnValue_t SerialComIF::flushUartTxAndRxBuf(CookieIF* cookie) { std::string deviceFile; - UartDeviceMapIter uartDeviceMapIter; - UartCookie* uartCookie = dynamic_cast(cookie); + SerialCookie* uartCookie = dynamic_cast(cookie); if (uartCookie == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "UartComIF::flushUartTxAndRxBuf: Invalid uart cookie!" << std::endl; @@ -581,21 +428,11 @@ ReturnValue_t UartComIF::flushUartTxAndRxBuf(CookieIF* cookie) { return NULLPOINTER; } deviceFile = uartCookie->getDeviceFile(); - uartDeviceMapIter = uartDeviceMap.find(deviceFile); + auto uartDeviceMapIter = uartDeviceMap.find(deviceFile); if (uartDeviceMapIter != uartDeviceMap.end()) { int fd = uartDeviceMapIter->second.fileDescriptor; tcflush(fd, TCIOFLUSH); - return RETURN_OK; - } - return RETURN_FAILED; -} - -void UartComIF::setUartMode(struct termios* options, UartCookie& uartCookie) { - UartModes uartMode = uartCookie.getUartMode(); - if (uartMode == UartModes::NON_CANONICAL) { - /* Disable canonical mode */ - options->c_lflag &= ~ICANON; - } else if (uartMode == UartModes::CANONICAL) { - options->c_lflag |= ICANON; + return returnvalue::OK; } + return returnvalue::FAILED; } diff --git a/hal/src/fsfw_hal/linux/uart/UartComIF.h b/src/fsfw_hal/linux/serial/SerialComIF.h similarity index 62% rename from hal/src/fsfw_hal/linux/uart/UartComIF.h rename to src/fsfw_hal/linux/serial/SerialComIF.h index 224f1e77..907da7e0 100644 --- a/hal/src/fsfw_hal/linux/uart/UartComIF.h +++ b/src/fsfw_hal/linux/serial/SerialComIF.h @@ -3,12 +3,12 @@ #include #include +#include +#include #include #include -#include "UartCookie.h" - /** * @brief This is the communication interface to access serial ports on linux based operating * systems. @@ -18,20 +18,17 @@ * * @author J. Meier */ -class UartComIF : public DeviceCommunicationIF, public SystemObject { +class SerialComIF : public DeviceCommunicationIF, public SystemObject { public: static constexpr uint8_t uartRetvalId = CLASS_ID::HAL_UART; - static constexpr ReturnValue_t UART_READ_FAILURE = - HasReturnvaluesIF::makeReturnCode(uartRetvalId, 1); - static constexpr ReturnValue_t UART_READ_SIZE_MISSMATCH = - HasReturnvaluesIF::makeReturnCode(uartRetvalId, 2); - static constexpr ReturnValue_t UART_RX_BUFFER_TOO_SMALL = - HasReturnvaluesIF::makeReturnCode(uartRetvalId, 3); + static constexpr ReturnValue_t UART_READ_FAILURE = returnvalue::makeCode(uartRetvalId, 1); + static constexpr ReturnValue_t UART_READ_SIZE_MISSMATCH = returnvalue::makeCode(uartRetvalId, 2); + static constexpr ReturnValue_t UART_RX_BUFFER_TOO_SMALL = returnvalue::makeCode(uartRetvalId, 3); - UartComIF(object_id_t objectId); + SerialComIF(object_id_t objectId); - virtual ~UartComIF(); + virtual ~SerialComIF(); ReturnValue_t initializeInterface(CookieIF* cookie) override; ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override; @@ -65,7 +62,6 @@ class UartComIF : public DeviceCommunicationIF, public SystemObject { }; using UartDeviceMap = std::unordered_map; - using UartDeviceMapIter = UartDeviceMap::iterator; /** * The uart devie map stores informations of initialized uart ports. @@ -79,20 +75,9 @@ class UartComIF : public DeviceCommunicationIF, public SystemObject { * uart device file, baudrate, parity, stopbits etc. * @return The file descriptor of the configured uart. */ - int configureUartPort(UartCookie* uartCookie); + int configureUartPort(SerialCookie* uartCookie); - /** - * @brief This function adds the parity settings to the termios options struct. - * - * @param options Pointer to termios options struct which will be modified to enable or disable - * parity checking. - * @param uartCookie Pointer to uart cookie containing the information about the desired - * parity settings. - * - */ - void setParityOptions(struct termios* options, UartCookie* uartCookie); - - void setStopBitOptions(struct termios* options, UartCookie* uartCookie); + void setStopBitOptions(struct termios* options, SerialCookie* uartCookie); /** * @brief This function sets options which are not configurable by the uartCookie. @@ -102,19 +87,11 @@ class UartComIF : public DeviceCommunicationIF, public SystemObject { /** * @brief With this function the datasize settings are added to the termios options struct. */ - void setDatasizeOptions(struct termios* options, UartCookie* uartCookie); + void setDatasizeOptions(struct termios* options, SerialCookie* uartCookie); - /** - * @brief This functions adds the baudrate specified in the uartCookie to the termios options - * struct. - */ - void configureBaudrate(struct termios* options, UartCookie* uartCookie); - - void setUartMode(struct termios* options, UartCookie& uartCookie); - - ReturnValue_t handleCanonicalRead(UartCookie& uartCookie, UartDeviceMapIter& iter, + ReturnValue_t handleCanonicalRead(SerialCookie& uartCookie, UartDeviceMap::iterator& iter, size_t requestLen); - ReturnValue_t handleNoncanonicalRead(UartCookie& uartCookie, UartDeviceMapIter& iter, + ReturnValue_t handleNoncanonicalRead(SerialCookie& uartCookie, UartDeviceMap::iterator& iter, size_t requestLen); }; diff --git a/src/fsfw_hal/linux/serial/SerialCookie.cpp b/src/fsfw_hal/linux/serial/SerialCookie.cpp new file mode 100644 index 00000000..1b7e9b51 --- /dev/null +++ b/src/fsfw_hal/linux/serial/SerialCookie.cpp @@ -0,0 +1,51 @@ +#include "SerialCookie.h" + +#include + +SerialCookie::SerialCookie(object_id_t handlerId, std::string deviceFile, UartBaudRate baudrate, + size_t maxReplyLen, UartModes uartMode) + : handlerId(handlerId), + deviceFile(deviceFile), + uartMode(uartMode), + baudrate(baudrate), + maxReplyLen(maxReplyLen) {} + +SerialCookie::~SerialCookie() {} + +UartBaudRate SerialCookie::getBaudrate() const { return baudrate; } + +size_t SerialCookie::getMaxReplyLen() const { return maxReplyLen; } + +std::string SerialCookie::getDeviceFile() const { return deviceFile; } + +void SerialCookie::setParityOdd() { parity = Parity::ODD; } + +void SerialCookie::setParityEven() { parity = Parity::EVEN; } + +Parity SerialCookie::getParity() const { return parity; } + +void SerialCookie::setBitsPerWord(BitsPerWord bitsPerWord_) { bitsPerWord = bitsPerWord_; } + +BitsPerWord SerialCookie::getBitsPerWord() const { return bitsPerWord; } + +StopBits SerialCookie::getStopBits() const { return stopBits; } + +void SerialCookie::setTwoStopBits() { stopBits = StopBits::TWO_STOP_BITS; } + +void SerialCookie::setOneStopBit() { stopBits = StopBits::ONE_STOP_BIT; } + +UartModes SerialCookie::getUartMode() const { return uartMode; } + +void SerialCookie::setReadCycles(uint8_t readCycles) { this->readCycles = readCycles; } + +void SerialCookie::setToFlushInput(bool enable) { this->flushInput = enable; } + +uint8_t SerialCookie::getReadCycles() const { return readCycles; } + +bool SerialCookie::getInputShouldBeFlushed() { return this->flushInput; } + +object_id_t SerialCookie::getHandlerId() const { return this->handlerId; } + +void SerialCookie::setNoFixedSizeReply() { replySizeFixed = false; } + +bool SerialCookie::isReplySizeFixed() { return replySizeFixed; } diff --git a/hal/src/fsfw_hal/linux/uart/UartCookie.h b/src/fsfw_hal/linux/serial/SerialCookie.h similarity index 78% rename from hal/src/fsfw_hal/linux/uart/UartCookie.h rename to src/fsfw_hal/linux/serial/SerialCookie.h index 6840b352..7a9c0eca 100644 --- a/hal/src/fsfw_hal/linux/uart/UartCookie.h +++ b/src/fsfw_hal/linux/serial/SerialCookie.h @@ -3,50 +3,10 @@ #include #include +#include #include -enum class Parity { NONE, EVEN, ODD }; - -enum class StopBits { ONE_STOP_BIT, TWO_STOP_BITS }; - -enum class UartModes { CANONICAL, NON_CANONICAL }; - -enum class BitsPerWord { BITS_5, BITS_6, BITS_7, BITS_8 }; - -enum class UartBaudRate { - RATE_50, - RATE_75, - RATE_110, - RATE_134, - RATE_150, - RATE_200, - RATE_300, - RATE_600, - RATE_1200, - RATE_1800, - RATE_2400, - RATE_4800, - RATE_9600, - RATE_19200, - RATE_38400, - RATE_57600, - RATE_115200, - RATE_230400, - RATE_460800, - RATE_500000, - RATE_576000, - RATE_921600, - RATE_1000000, - RATE_1152000, - RATE_1500000, - RATE_2000000, - RATE_2500000, - RATE_3000000, - RATE_3500000, - RATE_4000000 -}; - /** * @brief Cookie for the UartComIF. There are many options available to configure the UART driver. * The constructor only requests for common options like the baudrate. Other options can @@ -54,7 +14,7 @@ enum class UartBaudRate { * * @author J. Meier */ -class UartCookie : public CookieIF { +class SerialCookie : public CookieIF { public: /** * @brief Constructor for the uart cookie. @@ -69,10 +29,10 @@ class UartCookie : public CookieIF { * 8 databits (number of bits transfered with one uart frame) * One stop bit */ - UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode, - UartBaudRate baudrate, size_t maxReplyLen); + SerialCookie(object_id_t handlerId, std::string deviceFile, UartBaudRate baudrate, + size_t maxReplyLen, UartModes uartMode = UartModes::NON_CANONICAL); - virtual ~UartCookie(); + virtual ~SerialCookie(); UartBaudRate getBaudrate() const; size_t getMaxReplyLen() const; diff --git a/src/fsfw_hal/linux/serial/helper.cpp b/src/fsfw_hal/linux/serial/helper.cpp new file mode 100644 index 00000000..ba975f2f --- /dev/null +++ b/src/fsfw_hal/linux/serial/helper.cpp @@ -0,0 +1,163 @@ +#include +#include + +#include "fsfw/serviceinterface.h" + +void uart::setMode(struct termios& options, UartModes mode) { + if (mode == UartModes::NON_CANONICAL) { + /* Disable canonical mode */ + options.c_lflag &= ~ICANON; + } else if (mode == UartModes::CANONICAL) { + options.c_lflag |= ICANON; + } +} + +void uart::setBaudrate(struct termios& options, UartBaudRate baud) { + switch (baud) { + case UartBaudRate::RATE_50: + cfsetspeed(&options, B50); + break; + case UartBaudRate::RATE_75: + cfsetspeed(&options, B75); + break; + case UartBaudRate::RATE_110: + cfsetspeed(&options, B110); + break; + case UartBaudRate::RATE_134: + cfsetspeed(&options, B134); + break; + case UartBaudRate::RATE_150: + cfsetspeed(&options, B150); + break; + case UartBaudRate::RATE_200: + cfsetspeed(&options, B200); + break; + case UartBaudRate::RATE_300: + cfsetspeed(&options, B300); + break; + case UartBaudRate::RATE_600: + cfsetspeed(&options, B600); + break; + case UartBaudRate::RATE_1200: + cfsetspeed(&options, B1200); + break; + case UartBaudRate::RATE_1800: + cfsetspeed(&options, B1800); + break; + case UartBaudRate::RATE_2400: + cfsetspeed(&options, B2400); + break; + case UartBaudRate::RATE_4800: + cfsetspeed(&options, B4800); + break; + case UartBaudRate::RATE_9600: + cfsetspeed(&options, B9600); + break; + case UartBaudRate::RATE_19200: + cfsetspeed(&options, B19200); + break; + case UartBaudRate::RATE_38400: + cfsetspeed(&options, B38400); + break; + case UartBaudRate::RATE_57600: + cfsetspeed(&options, B57600); + break; + case UartBaudRate::RATE_115200: + cfsetspeed(&options, B115200); + break; + case UartBaudRate::RATE_230400: + cfsetspeed(&options, B230400); + break; +#ifndef __APPLE__ + case UartBaudRate::RATE_460800: + cfsetspeed(&options, B460800); + break; + case UartBaudRate::RATE_500000: + cfsetspeed(&options, B500000); + break; + case UartBaudRate::RATE_576000: + cfsetspeed(&options, B576000); + break; + case UartBaudRate::RATE_921600: + cfsetspeed(&options, B921600); + break; + case UartBaudRate::RATE_1000000: + cfsetspeed(&options, B1000000); + break; + case UartBaudRate::RATE_1152000: + cfsetspeed(&options, B1152000); + break; + case UartBaudRate::RATE_1500000: + cfsetspeed(&options, B1500000); + break; + case UartBaudRate::RATE_2000000: + cfsetspeed(&options, B2000000); + break; + case UartBaudRate::RATE_2500000: + cfsetspeed(&options, B2500000); + break; + case UartBaudRate::RATE_3000000: + cfsetspeed(&options, B3000000); + break; + case UartBaudRate::RATE_3500000: + cfsetspeed(&options, B3500000); + break; + case UartBaudRate::RATE_4000000: + cfsetspeed(&options, B4000000); + break; +#endif // ! __APPLE__ + default: +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl; +#endif + break; + } +} + +void uart::setBitsPerWord(struct termios& options, BitsPerWord bits) { + options.c_cflag &= ~CSIZE; // Clear all the size bits + if (bits == BitsPerWord::BITS_5) { + options.c_cflag |= CS5; + } else if (bits == BitsPerWord::BITS_6) { + options.c_cflag |= CS6; + } else if (bits == BitsPerWord::BITS_7) { + options.c_cflag |= CS7; + } else if (bits == BitsPerWord::BITS_8) { + options.c_cflag |= CS8; + } +} + +void uart::enableRead(struct termios& options) { options.c_cflag |= CREAD; } + +void uart::ignoreCtrlLines(struct termios& options) { options.c_cflag |= CLOCAL; } + +void uart::setParity(struct termios& options, Parity parity) { + /* Clear parity bit */ + options.c_cflag &= ~PARENB; + switch (parity) { + case Parity::EVEN: + options.c_cflag |= PARENB; + options.c_cflag &= ~PARODD; + break; + case Parity::ODD: + options.c_cflag |= PARENB; + options.c_cflag |= PARODD; + break; + default: + break; + } +} + +int uart::readCountersAndErrors(int serialPort, serial_icounter_struct& icounter) { + return ioctl(serialPort, TIOCGICOUNT, &icounter); +} + +void uart::setStopbits(struct termios& options, StopBits bits) { + if (bits == StopBits::TWO_STOP_BITS) { + // Use two stop bits + options.c_cflag |= CSTOPB; + } else { + // Clear stop field, only one stop bit used in communication + options.c_cflag &= ~CSTOPB; + } +} diff --git a/src/fsfw_hal/linux/serial/helper.h b/src/fsfw_hal/linux/serial/helper.h new file mode 100644 index 00000000..7f067d00 --- /dev/null +++ b/src/fsfw_hal/linux/serial/helper.h @@ -0,0 +1,71 @@ +#ifndef FSFW_HAL_LINUX_UART_HELPER_H_ +#define FSFW_HAL_LINUX_UART_HELPER_H_ + +#include +#include + +enum class Parity { NONE, EVEN, ODD }; + +enum class StopBits { ONE_STOP_BIT, TWO_STOP_BITS }; + +enum class UartModes { CANONICAL, NON_CANONICAL }; + +enum class BitsPerWord { BITS_5, BITS_6, BITS_7, BITS_8 }; + +enum class UartBaudRate { + RATE_50, + RATE_75, + RATE_110, + RATE_134, + RATE_150, + RATE_200, + RATE_300, + RATE_600, + RATE_1200, + RATE_1800, + RATE_2400, + RATE_4800, + RATE_9600, + RATE_19200, + RATE_38400, + RATE_57600, + RATE_115200, + RATE_230400, + RATE_460800, + RATE_500000, + RATE_576000, + RATE_921600, + RATE_1000000, + RATE_1152000, + RATE_1500000, + RATE_2000000, + RATE_2500000, + RATE_3000000, + RATE_3500000, + RATE_4000000 +}; + +namespace uart { + +void setMode(struct termios& options, UartModes mode); +/** + * @brief This functions adds the baudrate specified in the uartCookie to the termios options + * struct. + */ +void setBaudrate(struct termios& options, UartBaudRate baud); + +void setStopbits(struct termios& options, StopBits bits); + +void setBitsPerWord(struct termios& options, BitsPerWord bits); + +void enableRead(struct termios& options); + +void setParity(struct termios& options, Parity parity); + +void ignoreCtrlLines(struct termios& options); + +int readCountersAndErrors(int serialPort, serial_icounter_struct& icounter); + +} // namespace uart + +#endif /* FSFW_HAL_LINUX_UART_HELPER_H_ */ diff --git a/src/fsfw_hal/linux/spi/CMakeLists.txt b/src/fsfw_hal/linux/spi/CMakeLists.txt new file mode 100644 index 00000000..f242bb3b --- /dev/null +++ b/src/fsfw_hal/linux/spi/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PUBLIC SpiComIF.cpp SpiCookie.cpp) diff --git a/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp b/src/fsfw_hal/linux/spi/SpiComIF.cpp similarity index 92% rename from hal/src/fsfw_hal/linux/spi/SpiComIF.cpp rename to src/fsfw_hal/linux/spi/SpiComIF.cpp index dcf92b5d..cc52b689 100644 --- a/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp +++ b/src/fsfw_hal/linux/spi/SpiComIF.cpp @@ -56,7 +56,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) { static_cast(spiAddress)); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } /* Now we emplaced the read buffer in the map, we still need to assign that location to the SPI driver transfer struct */ @@ -69,7 +69,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) { sif::printError("SpiComIF::initializeInterface: SPI address already exists!\n"); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } /* Pull CS high in any case to be sure that device is inactive */ @@ -87,7 +87,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) { int fileDescriptor = 0; UnixFileGuard fileHelper(spiCookie->getSpiDevice(), &fileDescriptor, O_RDWR, "SpiComIF::initializeInterface"); - if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) { + if (fileHelper.getOpenResult() != returnvalue::OK) { return fileHelper.getOpenResult(); } @@ -129,12 +129,12 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) { "Could not write bits per word!"); } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t SpiComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) { SpiCookie* spiCookie = dynamic_cast(cookie); - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; if (spiCookie == nullptr) { return NULLPOINTER; @@ -178,13 +178,13 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const spiCookie->assignReadBuffer(iter->second.replyBuffer.data()); } - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; int retval = 0; /* Prepare transfer */ int fileDescriptor = 0; std::string device = spiCookie->getSpiDevice(); UnixFileGuard fileHelper(device, &fileDescriptor, O_RDWR, "SpiComIF::sendMessage"); - if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) { + if (fileHelper.getOpenResult() != returnvalue::OK) { return OPENING_FILE_FAILED; } spi::SpiModes spiMode = spi::SpiModes::MODE_0; @@ -200,7 +200,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const /* Pull SPI CS low. For now, no support for active high given */ if (gpioId != gpio::NO_GPIO) { result = spiMutex->lockMutex(timeoutType, timeoutMs); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "SpiComIF::sendMessage: Failed to lock mutex" << std::endl; @@ -210,8 +210,8 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const #endif return result; } - ReturnValue_t result = gpioComIF->pullLow(gpioId); - if (result != HasReturnvaluesIF::RETURN_OK) { + result = gpioComIF->pullLow(gpioId); + if (result != returnvalue::OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "SpiComIF::sendMessage: Pulling low CS pin failed" << std::endl; @@ -251,7 +251,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const if (gpioId != gpio::NO_GPIO) { gpioComIF->pullHigh(gpioId); result = spiMutex->unlockMutex(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "SpiComIF::sendMessage: Failed to unlock mutex" << std::endl; #endif @@ -261,7 +261,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const return result; } -ReturnValue_t SpiComIF::getSendSuccess(CookieIF* cookie) { return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t SpiComIF::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; } ReturnValue_t SpiComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLen) { SpiCookie* spiCookie = dynamic_cast(cookie); @@ -270,32 +270,32 @@ ReturnValue_t SpiComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe } if (spiCookie->isFullDuplex()) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } return performHalfDuplexReception(spiCookie); } ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; std::string device = spiCookie->getSpiDevice(); int fileDescriptor = 0; UnixFileGuard fileHelper(device, &fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage"); - if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) { + if (fileHelper.getOpenResult() != returnvalue::OK) { return OPENING_FILE_FAILED; } uint8_t* rxBuf = nullptr; size_t readSize = spiCookie->getCurrentTransferSize(); result = getReadBuffer(spiCookie->getSpiAddress(), &rxBuf); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } gpioId_t gpioId = spiCookie->getChipSelectPin(); if (gpioId != gpio::NO_GPIO) { result = spiMutex->lockMutex(timeoutType, timeoutMs); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "SpiComIF::getSendSuccess: Failed to lock mutex" << std::endl; #endif @@ -318,7 +318,7 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) { if (gpioId != gpio::NO_GPIO) { gpioComIF->pullHigh(gpioId); result = spiMutex->unlockMutex(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "SpiComIF::getSendSuccess: Failed to unlock mutex" << std::endl; #endif @@ -332,18 +332,18 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) { ReturnValue_t SpiComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) { SpiCookie* spiCookie = dynamic_cast(cookie); if (spiCookie == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } uint8_t* rxBuf = nullptr; ReturnValue_t result = getReadBuffer(spiCookie->getSpiAddress(), &rxBuf); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } *buffer = rxBuf; *size = spiCookie->getCurrentTransferSize(); spiCookie->setTransferSize(0); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } MutexIF* SpiComIF::getMutex(MutexIF::TimeoutType* timeoutType, uint32_t* timeoutMs) { @@ -377,16 +377,16 @@ void SpiComIF::performSpiWiretapping(SpiCookie* spiCookie) { ReturnValue_t SpiComIF::getReadBuffer(address_t spiAddress, uint8_t** buffer) { if (buffer == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } auto iter = spiDeviceMap.find(spiAddress); if (iter == spiDeviceMap.end()) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } *buffer = iter->second.replyBuffer.data(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } GpioIF* SpiComIF::getGpioInterface() { return gpioComIF; } diff --git a/hal/src/fsfw_hal/linux/spi/SpiComIF.h b/src/fsfw_hal/linux/spi/SpiComIF.h similarity index 92% rename from hal/src/fsfw_hal/linux/spi/SpiComIF.h rename to src/fsfw_hal/linux/spi/SpiComIF.h index 357afa2f..11defdce 100644 --- a/hal/src/fsfw_hal/linux/spi/SpiComIF.h +++ b/src/fsfw_hal/linux/spi/SpiComIF.h @@ -23,14 +23,13 @@ class SpiCookie; class SpiComIF : public DeviceCommunicationIF, public SystemObject { public: static constexpr uint8_t spiRetvalId = CLASS_ID::HAL_SPI; - static constexpr ReturnValue_t OPENING_FILE_FAILED = - HasReturnvaluesIF::makeReturnCode(spiRetvalId, 0); + static constexpr ReturnValue_t OPENING_FILE_FAILED = returnvalue::makeCode(spiRetvalId, 0); /* Full duplex (ioctl) transfer failure */ static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED = - HasReturnvaluesIF::makeReturnCode(spiRetvalId, 1); + returnvalue::makeCode(spiRetvalId, 1); /* Half duplex (read/write) transfer failure */ static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED = - HasReturnvaluesIF::makeReturnCode(spiRetvalId, 2); + returnvalue::makeCode(spiRetvalId, 2); SpiComIF(object_id_t objectId, GpioIF* gpioComIF); diff --git a/hal/src/fsfw_hal/linux/spi/SpiCookie.cpp b/src/fsfw_hal/linux/spi/SpiCookie.cpp similarity index 99% rename from hal/src/fsfw_hal/linux/spi/SpiCookie.cpp rename to src/fsfw_hal/linux/spi/SpiCookie.cpp index e6271c5e..c94fcdf1 100644 --- a/hal/src/fsfw_hal/linux/spi/SpiCookie.cpp +++ b/src/fsfw_hal/linux/spi/SpiCookie.cpp @@ -1,4 +1,4 @@ -#include "fsfw_hal/linux/spi/SpiCookie.h" +#include "SpiCookie.h" SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev, const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed) diff --git a/hal/src/fsfw_hal/linux/spi/SpiCookie.h b/src/fsfw_hal/linux/spi/SpiCookie.h similarity index 100% rename from hal/src/fsfw_hal/linux/spi/SpiCookie.h rename to src/fsfw_hal/linux/spi/SpiCookie.h diff --git a/hal/src/fsfw_hal/linux/spi/spiDefinitions.h b/src/fsfw_hal/linux/spi/spiDefinitions.h similarity index 92% rename from hal/src/fsfw_hal/linux/spi/spiDefinitions.h rename to src/fsfw_hal/linux/spi/spiDefinitions.h index b4bae3c2..113f6551 100644 --- a/hal/src/fsfw_hal/linux/spi/spiDefinitions.h +++ b/src/fsfw_hal/linux/spi/spiDefinitions.h @@ -7,7 +7,7 @@ #include "../../common/gpio/gpioDefinitions.h" #include "../../common/spi/spiCommon.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" class SpiCookie; class SpiComIF; diff --git a/src/fsfw_hal/linux/uio/CMakeLists.txt b/src/fsfw_hal/linux/uio/CMakeLists.txt new file mode 100644 index 00000000..e3498246 --- /dev/null +++ b/src/fsfw_hal/linux/uio/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PUBLIC UioMapper.cpp) diff --git a/hal/src/fsfw_hal/linux/uio/UioMapper.cpp b/src/fsfw_hal/linux/uio/UioMapper.cpp similarity index 71% rename from hal/src/fsfw_hal/linux/uio/UioMapper.cpp rename to src/fsfw_hal/linux/uio/UioMapper.cpp index 43ca2727..33e4fd97 100644 --- a/hal/src/fsfw_hal/linux/uio/UioMapper.cpp +++ b/src/fsfw_hal/linux/uio/UioMapper.cpp @@ -1,6 +1,7 @@ #include "UioMapper.h" #include +#include #include #include @@ -13,22 +14,38 @@ const char UioMapper::UIO_PATH_PREFIX[] = "/sys/class/uio/"; const char UioMapper::MAP_SUBSTR[] = "/maps/map"; const char UioMapper::SIZE_FILE_PATH[] = "/size"; -UioMapper::UioMapper(std::string uioFile, int mapNum) : uioFile(uioFile), mapNum(mapNum) {} +UioMapper::UioMapper(std::string uioFile, int mapNum) : mapNum(mapNum) { + struct stat buf; + lstat(uioFile.c_str(), &buf); + if (S_ISLNK(buf.st_mode)) { + char* res = realpath(uioFile.c_str(), nullptr); + if (res) { + this->uioFile = res; + free(res); + } else { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "Could not resolve real path of UIO file " << uioFile << std::endl; +#endif + } + } else { + this->uioFile = std::move(uioFile); + } +} UioMapper::~UioMapper() {} ReturnValue_t UioMapper::getMappedAdress(uint32_t** address, Permissions permissions) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; int fd = open(uioFile.c_str(), O_RDWR); if (fd < 1) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PtmeAxiConfig::initialize: Invalid UIO device file" << std::endl; + sif::error << "UioMapper::getMappedAdress: Invalid UIO device file " << uioFile << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } size_t size = 0; result = getMapSize(&size); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } *address = static_cast( @@ -39,9 +56,9 @@ ReturnValue_t UioMapper::getMappedAdress(uint32_t** address, Permissions permiss 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; + return returnvalue::FAILED; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t UioMapper::getMapSize(size_t* size) { @@ -54,7 +71,7 @@ ReturnValue_t UioMapper::getMapSize(size_t* size) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "UioMapper::getMapSize: Failed to open file " << namestream.str() << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } char hexstring[SIZE_HEX_STRING] = ""; int items = fscanf(fp, "%s", hexstring); @@ -66,7 +83,7 @@ ReturnValue_t UioMapper::getMapSize(size_t* size) { << namestream.str() << std::endl; #endif fclose(fp); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } uint32_t sizeTmp = 0; items = sscanf(hexstring, "%x", &sizeTmp); @@ -79,8 +96,8 @@ ReturnValue_t UioMapper::getMapSize(size_t* size) { << "size of map" << mapNum << " to integer" << std::endl; #endif fclose(fp); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } fclose(fp); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/hal/src/fsfw_hal/linux/uio/UioMapper.h b/src/fsfw_hal/linux/uio/UioMapper.h similarity index 96% rename from hal/src/fsfw_hal/linux/uio/UioMapper.h rename to src/fsfw_hal/linux/uio/UioMapper.h index 20c90b4d..89c2c66a 100644 --- a/hal/src/fsfw_hal/linux/uio/UioMapper.h +++ b/src/fsfw_hal/linux/uio/UioMapper.h @@ -5,7 +5,7 @@ #include -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" /** * @brief Class to help opening uio device files and mapping the physical addresses into the user diff --git a/hal/src/fsfw_hal/linux/utility.cpp b/src/fsfw_hal/linux/utility.cpp similarity index 100% rename from hal/src/fsfw_hal/linux/utility.cpp rename to src/fsfw_hal/linux/utility.cpp diff --git a/hal/src/fsfw_hal/linux/utility.h b/src/fsfw_hal/linux/utility.h similarity index 100% rename from hal/src/fsfw_hal/linux/utility.h rename to src/fsfw_hal/linux/utility.h diff --git a/hal/src/fsfw_hal/stm32h7/CMakeLists.txt b/src/fsfw_hal/stm32h7/CMakeLists.txt similarity index 58% rename from hal/src/fsfw_hal/stm32h7/CMakeLists.txt rename to src/fsfw_hal/stm32h7/CMakeLists.txt index bae3b1ac..e8843ed3 100644 --- a/hal/src/fsfw_hal/stm32h7/CMakeLists.txt +++ b/src/fsfw_hal/stm32h7/CMakeLists.txt @@ -2,6 +2,4 @@ add_subdirectory(spi) add_subdirectory(gpio) add_subdirectory(devicetest) -target_sources(${LIB_FSFW_NAME} PRIVATE - dma.cpp -) +target_sources(${LIB_FSFW_NAME} PRIVATE dma.cpp) diff --git a/hal/src/fsfw_hal/stm32h7/definitions.h b/src/fsfw_hal/stm32h7/definitions.h similarity index 100% rename from hal/src/fsfw_hal/stm32h7/definitions.h rename to src/fsfw_hal/stm32h7/definitions.h diff --git a/src/fsfw_hal/stm32h7/devicetest/CMakeLists.txt b/src/fsfw_hal/stm32h7/devicetest/CMakeLists.txt new file mode 100644 index 00000000..8e789ddb --- /dev/null +++ b/src/fsfw_hal/stm32h7/devicetest/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE GyroL3GD20H.cpp) diff --git a/hal/src/fsfw_hal/stm32h7/devicetest/GyroL3GD20H.cpp b/src/fsfw_hal/stm32h7/devicetest/GyroL3GD20H.cpp similarity index 91% rename from hal/src/fsfw_hal/stm32h7/devicetest/GyroL3GD20H.cpp rename to src/fsfw_hal/stm32h7/devicetest/GyroL3GD20H.cpp index cbf8def5..624696c8 100644 --- a/hal/src/fsfw_hal/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/src/fsfw_hal/stm32h7/devicetest/GyroL3GD20H.cpp @@ -84,7 +84,7 @@ ReturnValue_t GyroL3GD20H::initialize() { spiHandle->Init.Mode = SPI_MODE_MASTER; if (HAL_SPI_Init(spiHandle) != HAL_OK) { sif::printWarning("Error initializing SPI\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } delete mspCfg; @@ -106,11 +106,11 @@ ReturnValue_t GyroL3GD20H::initialize() { return handlePollingTransferInit(); } default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t GyroL3GD20H::performOperation() { @@ -125,10 +125,10 @@ ReturnValue_t GyroL3GD20H::performOperation() { return handleInterruptSensorRead(); } default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t GyroL3GD20H::handleDmaTransferInit() { @@ -162,10 +162,10 @@ ReturnValue_t GyroL3GD20H::handleDmaTransferInit() { case (TransferStates::FAILURE): { sif::printWarning("Transfer failure\n"); transferState = TransferStates::FAILURE; - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -194,10 +194,10 @@ ReturnValue_t GyroL3GD20H::handleDmaTransferInit() { case (TransferStates::FAILURE): { sif::printWarning("GyroL3GD20H::initialize: Configuration transfer failure\n"); transferState = TransferStates::FAILURE; - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -228,13 +228,13 @@ ReturnValue_t GyroL3GD20H::handleDmaTransferInit() { case (TransferStates::FAILURE): { sif::printWarning("GyroL3GD20H::initialize: Configuration transfer failure\n"); transferState = TransferStates::FAILURE; - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t GyroL3GD20H::handleDmaSensorRead() { @@ -259,13 +259,13 @@ ReturnValue_t GyroL3GD20H::handleDmaSensorRead() { case (TransferStates::FAILURE): { sif::printWarning("GyroL3GD20H::handleDmaSensorRead: Sensor read failure\n"); transferState = TransferStates::FAILURE; - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } HAL_StatusTypeDef GyroL3GD20H::performDmaTransfer(size_t sendSize) { @@ -298,14 +298,14 @@ ReturnValue_t GyroL3GD20H::handlePollingTransferInit() { } case (HAL_TIMEOUT): { sif::printDebug("GyroL3GD20H::initialize: Polling transfer timeout\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } case (HAL_ERROR): { sif::printDebug("GyroL3GD20H::initialize: Polling transfer failure\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -323,14 +323,14 @@ ReturnValue_t GyroL3GD20H::handlePollingTransferInit() { } case (HAL_TIMEOUT): { sif::printDebug("GyroL3GD20H::initialize: Polling transfer timeout\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } case (HAL_ERROR): { sif::printDebug("GyroL3GD20H::initialize: Polling transfer failure\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -353,17 +353,17 @@ ReturnValue_t GyroL3GD20H::handlePollingTransferInit() { } case (HAL_TIMEOUT): { sif::printDebug("GyroL3GD20H::initialize: Polling transfer timeout\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } case (HAL_ERROR): { sif::printDebug("GyroL3GD20H::initialize: Polling transfer failure\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t GyroL3GD20H::handlePollingSensorRead() { @@ -380,17 +380,17 @@ ReturnValue_t GyroL3GD20H::handlePollingSensorRead() { } case (HAL_TIMEOUT): { sif::printDebug("GyroL3GD20H::initialize: Polling transfer timeout\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } case (HAL_ERROR): { sif::printDebug("GyroL3GD20H::initialize: Polling transfer failure\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t GyroL3GD20H::handleInterruptTransferInit() { @@ -416,7 +416,7 @@ ReturnValue_t GyroL3GD20H::handleInterruptTransferInit() { case (HAL_ERROR): case (HAL_TIMEOUT): { sif::printDebug("GyroL3GD20H::initialize: Initialization failure using interrupts\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -438,7 +438,7 @@ ReturnValue_t GyroL3GD20H::handleInterruptTransferInit() { case (HAL_ERROR): case (HAL_TIMEOUT): { sif::printDebug("GyroL3GD20H::initialize: Initialization failure using interrupts\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -465,10 +465,10 @@ ReturnValue_t GyroL3GD20H::handleInterruptTransferInit() { case (HAL_ERROR): case (HAL_TIMEOUT): { sif::printDebug("GyroL3GD20H::initialize: Initialization failure using interrupts\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t GyroL3GD20H::handleInterruptSensorRead() { @@ -489,10 +489,10 @@ ReturnValue_t GyroL3GD20H::handleInterruptSensorRead() { case (HAL_ERROR): case (HAL_TIMEOUT): { sif::printDebug("GyroL3GD20H::initialize: Sensor read failure using interrupts\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void GyroL3GD20H::prepareConfigRegs(uint8_t *configRegs) { diff --git a/hal/src/fsfw_hal/stm32h7/devicetest/GyroL3GD20H.h b/src/fsfw_hal/stm32h7/devicetest/GyroL3GD20H.h similarity index 92% rename from hal/src/fsfw_hal/stm32h7/devicetest/GyroL3GD20H.h rename to src/fsfw_hal/stm32h7/devicetest/GyroL3GD20H.h index a6c3376a..f967c8d1 100644 --- a/hal/src/fsfw_hal/stm32h7/devicetest/GyroL3GD20H.h +++ b/src/fsfw_hal/stm32h7/devicetest/GyroL3GD20H.h @@ -6,10 +6,14 @@ #include "../spi/mspInit.h" #include "../spi/spiDefinitions.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_spi.h" +#ifndef STM_USE_PERIPHERAL_TX_BUFFER_MPU_PROTECTION +#define STM_USE_PERIPHERAL_TX_BUFFER_MPU_PROTECTION 1 +#endif + enum class TransferStates { IDLE, WAIT, SUCCESS, FAILURE }; class GyroL3GD20H { diff --git a/hal/src/fsfw_hal/stm32h7/dma.cpp b/src/fsfw_hal/stm32h7/dma.cpp similarity index 100% rename from hal/src/fsfw_hal/stm32h7/dma.cpp rename to src/fsfw_hal/stm32h7/dma.cpp diff --git a/hal/src/fsfw_hal/stm32h7/dma.h b/src/fsfw_hal/stm32h7/dma.h similarity index 100% rename from hal/src/fsfw_hal/stm32h7/dma.h rename to src/fsfw_hal/stm32h7/dma.h diff --git a/src/fsfw_hal/stm32h7/gpio/CMakeLists.txt b/src/fsfw_hal/stm32h7/gpio/CMakeLists.txt new file mode 100644 index 00000000..54d76b2d --- /dev/null +++ b/src/fsfw_hal/stm32h7/gpio/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE gpio.cpp) diff --git a/hal/src/fsfw_hal/stm32h7/gpio/gpio.cpp b/src/fsfw_hal/stm32h7/gpio/gpio.cpp similarity index 100% rename from hal/src/fsfw_hal/stm32h7/gpio/gpio.cpp rename to src/fsfw_hal/stm32h7/gpio/gpio.cpp diff --git a/hal/src/fsfw_hal/stm32h7/gpio/gpio.h b/src/fsfw_hal/stm32h7/gpio/gpio.h similarity index 100% rename from hal/src/fsfw_hal/stm32h7/gpio/gpio.h rename to src/fsfw_hal/stm32h7/gpio/gpio.h diff --git a/src/fsfw_hal/stm32h7/i2c/CMakeLists.txt b/src/fsfw_hal/stm32h7/i2c/CMakeLists.txt new file mode 100644 index 00000000..a0d48465 --- /dev/null +++ b/src/fsfw_hal/stm32h7/i2c/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE) diff --git a/hal/src/fsfw_hal/stm32h7/interrupts.h b/src/fsfw_hal/stm32h7/interrupts.h similarity index 100% rename from hal/src/fsfw_hal/stm32h7/interrupts.h rename to src/fsfw_hal/stm32h7/interrupts.h diff --git a/src/fsfw_hal/stm32h7/spi/CMakeLists.txt b/src/fsfw_hal/stm32h7/spi/CMakeLists.txt new file mode 100644 index 00000000..9a98f502 --- /dev/null +++ b/src/fsfw_hal/stm32h7/spi/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources( + ${LIB_FSFW_NAME} + PRIVATE spiCore.cpp + spiDefinitions.cpp + spiInterrupts.cpp + mspInit.cpp + SpiCookie.cpp + SpiComIF.cpp + stm32h743zi.cpp) diff --git a/hal/src/fsfw_hal/stm32h7/spi/SpiComIF.cpp b/src/fsfw_hal/stm32h7/spi/SpiComIF.cpp similarity index 93% rename from hal/src/fsfw_hal/stm32h7/spi/SpiComIF.cpp rename to src/fsfw_hal/stm32h7/spi/SpiComIF.cpp index 49e4670d..724917bd 100644 --- a/hal/src/fsfw_hal/stm32h7/spi/SpiComIF.cpp +++ b/src/fsfw_hal/stm32h7/spi/SpiComIF.cpp @@ -35,7 +35,7 @@ void SpiComIF::addDmaHandles(DMA_HandleTypeDef *txHandle, DMA_HandleTypeDef *rxH spi::setDmaHandles(txHandle, rxHandle); } -ReturnValue_t SpiComIF::initialize() { return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t SpiComIF::initialize() { return returnvalue::OK; } ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { SpiCookie *spiCookie = dynamic_cast(cookie); @@ -55,7 +55,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { spi::getDmaHandles(&txHandle, &rxHandle); if (txHandle == nullptr or rxHandle == nullptr) { sif::printError("SpiComIF::initialize: DMA handles not set!\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } // This semaphore ensures thread-safety for a given bus @@ -79,7 +79,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { static_cast(spiAddress)); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } auto gpioPin = spiCookie->getChipSelectGpioPin(); @@ -98,7 +98,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { #endif } else { printCfgError("SPI Bus Index"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } auto mspCfg = spiCookie->getMspCfg(); @@ -107,21 +107,21 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { auto typedCfg = dynamic_cast(mspCfg); if (typedCfg == nullptr) { printCfgError("Polling MSP"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } spi::setSpiPollingMspFunctions(typedCfg); } else if (transferMode == spi::TransferModes::INTERRUPT) { auto typedCfg = dynamic_cast(mspCfg); if (typedCfg == nullptr) { printCfgError("IRQ MSP"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } spi::setSpiIrqMspFunctions(typedCfg); } else if (transferMode == spi::TransferModes::DMA) { auto typedCfg = dynamic_cast(mspCfg); if (typedCfg == nullptr) { printCfgError("DMA MSP"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } // Check DMA handles DMA_HandleTypeDef *txHandle = nullptr; @@ -129,7 +129,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { spi::getDmaHandles(&txHandle, &rxHandle); if (txHandle == nullptr or rxHandle == nullptr) { printCfgError("DMA Handle"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } spi::setSpiDmaMspFunctions(typedCfg); } @@ -145,12 +145,12 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { if (HAL_SPI_Init(&spiHandle) != HAL_OK) { sif::printWarning("SpiComIF::initialize: Error initializing SPI\n"); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } // The MSP configuration struct is not required anymore spiCookie->deleteMspCfg(); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen) { @@ -163,7 +163,7 @@ ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, s auto iter = spiDeviceMap.find(spiCookie->getDeviceAddress()); if (iter == spiDeviceMap.end()) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } iter->second.currentTransferLen = sendLen; @@ -176,7 +176,7 @@ ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, s case (spi::TransferStates::FAILURE): case (spi::TransferStates::SUCCESS): default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } @@ -194,13 +194,13 @@ ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, s sendData, sendLen); } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } -ReturnValue_t SpiComIF::getSendSuccess(CookieIF *cookie) { return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t SpiComIF::getSendSuccess(CookieIF *cookie) { return returnvalue::OK; } ReturnValue_t SpiComIF::requestReceiveMessage(CookieIF *cookie, size_t requestLen) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t SpiComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) { @@ -212,7 +212,7 @@ ReturnValue_t SpiComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, case (spi::TransferStates::SUCCESS): { auto iter = spiDeviceMap.find(spiCookie->getDeviceAddress()); if (iter == spiDeviceMap.end()) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } *buffer = iter->second.replyBuffer.data(); *size = iter->second.currentTransferLen; @@ -228,18 +228,18 @@ ReturnValue_t SpiComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, #endif #endif spiCookie->setTransferState(spi::TransferStates::IDLE); - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } case (spi::TransferStates::WAIT): case (spi::TransferStates::IDLE): { break; } default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void SpiComIF::setDefaultPollingTimeout(dur_millis_t timeout) { @@ -252,7 +252,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t *recvPtr, SPI_HandleT auto gpioPort = spiCookie.getChipSelectGpioPort(); auto gpioPin = spiCookie.getChipSelectGpioPin(); auto returnval = spiSemaphore->acquire(timeoutType, timeoutMs); - if (returnval != HasReturnvaluesIF::RETURN_OK) { + if (returnval != returnvalue::OK) { return returnval; } spiCookie.setTransferState(spi::TransferStates::WAIT); @@ -299,7 +299,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t *recvPtr, SPI_HandleT return spi::HAL_ERROR_RETVAL; } } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t SpiComIF::handleInterruptSendOperation(uint8_t *recvPtr, SPI_HandleTypeDef &spiHandle, @@ -318,7 +318,7 @@ ReturnValue_t SpiComIF::handleIrqSendOperation(uint8_t *recvPtr, SPI_HandleTypeD SpiCookie &spiCookie, const uint8_t *sendData, size_t sendLen) { ReturnValue_t result = genericIrqSendSetup(recvPtr, spiHandle, spiCookie, sendData, sendLen); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } // yet another HAL driver which is not const-correct.. @@ -366,7 +366,7 @@ ReturnValue_t SpiComIF::halErrorHandler(HAL_StatusTypeDef status, spi::TransferM return spi::HAL_TIMEOUT_RETVAL; } default: { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } } @@ -379,7 +379,7 @@ ReturnValue_t SpiComIF::genericIrqSendSetup(uint8_t *recvPtr, SPI_HandleTypeDef // Take the semaphore which will be released by a callback when the transfer is complete ReturnValue_t result = spiSemaphore->acquire(SemaphoreIF::TimeoutType::WAITING, timeoutMs); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { // Configuration error sif::printWarning( "SpiComIF::handleInterruptSendOperation: Semaphore " @@ -399,7 +399,7 @@ ReturnValue_t SpiComIF::genericIrqSendSetup(uint8_t *recvPtr, SPI_HandleTypeDef HAL_GPIO_WritePin(spiCookie.getChipSelectGpioPort(), spiCookie.getChipSelectGpioPin(), GPIO_PIN_RESET); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void SpiComIF::spiTransferTxCompleteCallback(SPI_HandleTypeDef *hspi, void *args) { @@ -445,7 +445,7 @@ void SpiComIF::genericIrqHandler(void *irqArgsVoid, spi::TransferStates targetSt #elif defined FSFW_OSAL_RTEMS ReturnValue_t result = comIF->spiSemaphore->release(); #endif - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { // Configuration error printf("SpiComIF::genericIrqHandler: Failure releasing Semaphore!\n"); } diff --git a/hal/src/fsfw_hal/stm32h7/spi/SpiComIF.h b/src/fsfw_hal/stm32h7/spi/SpiComIF.h similarity index 100% rename from hal/src/fsfw_hal/stm32h7/spi/SpiComIF.h rename to src/fsfw_hal/stm32h7/spi/SpiComIF.h diff --git a/hal/src/fsfw_hal/stm32h7/spi/SpiCookie.cpp b/src/fsfw_hal/stm32h7/spi/SpiCookie.cpp similarity index 100% rename from hal/src/fsfw_hal/stm32h7/spi/SpiCookie.cpp rename to src/fsfw_hal/stm32h7/spi/SpiCookie.cpp diff --git a/hal/src/fsfw_hal/stm32h7/spi/SpiCookie.h b/src/fsfw_hal/stm32h7/spi/SpiCookie.h similarity index 100% rename from hal/src/fsfw_hal/stm32h7/spi/SpiCookie.h rename to src/fsfw_hal/stm32h7/spi/SpiCookie.h diff --git a/hal/src/fsfw_hal/stm32h7/spi/mspInit.cpp b/src/fsfw_hal/stm32h7/spi/mspInit.cpp similarity index 100% rename from hal/src/fsfw_hal/stm32h7/spi/mspInit.cpp rename to src/fsfw_hal/stm32h7/spi/mspInit.cpp diff --git a/hal/src/fsfw_hal/stm32h7/spi/mspInit.h b/src/fsfw_hal/stm32h7/spi/mspInit.h similarity index 100% rename from hal/src/fsfw_hal/stm32h7/spi/mspInit.h rename to src/fsfw_hal/stm32h7/spi/mspInit.h diff --git a/hal/src/fsfw_hal/stm32h7/spi/spiCore.cpp b/src/fsfw_hal/stm32h7/spi/spiCore.cpp similarity index 100% rename from hal/src/fsfw_hal/stm32h7/spi/spiCore.cpp rename to src/fsfw_hal/stm32h7/spi/spiCore.cpp diff --git a/hal/src/fsfw_hal/stm32h7/spi/spiCore.h b/src/fsfw_hal/stm32h7/spi/spiCore.h similarity index 100% rename from hal/src/fsfw_hal/stm32h7/spi/spiCore.h rename to src/fsfw_hal/stm32h7/spi/spiCore.h diff --git a/hal/src/fsfw_hal/stm32h7/spi/spiDefinitions.cpp b/src/fsfw_hal/stm32h7/spi/spiDefinitions.cpp similarity index 100% rename from hal/src/fsfw_hal/stm32h7/spi/spiDefinitions.cpp rename to src/fsfw_hal/stm32h7/spi/spiDefinitions.cpp diff --git a/hal/src/fsfw_hal/stm32h7/spi/spiDefinitions.h b/src/fsfw_hal/stm32h7/spi/spiDefinitions.h similarity index 71% rename from hal/src/fsfw_hal/stm32h7/spi/spiDefinitions.h rename to src/fsfw_hal/stm32h7/spi/spiDefinitions.h index 12c3bf4e..cf05d986 100644 --- a/hal/src/fsfw_hal/stm32h7/spi/spiDefinitions.h +++ b/src/fsfw_hal/stm32h7/spi/spiDefinitions.h @@ -3,17 +3,16 @@ #include "../../common/spi/spiCommon.h" #include "fsfw/returnvalues/FwClassIds.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_spi.h" namespace spi { static constexpr uint8_t HAL_SPI_ID = CLASS_ID::HAL_SPI; -static constexpr ReturnValue_t HAL_TIMEOUT_RETVAL = - HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 0); -static constexpr ReturnValue_t HAL_BUSY_RETVAL = HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 1); -static constexpr ReturnValue_t HAL_ERROR_RETVAL = HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 2); +static constexpr ReturnValue_t HAL_TIMEOUT_RETVAL = returnvalue::makeCode(HAL_SPI_ID, 0); +static constexpr ReturnValue_t HAL_BUSY_RETVAL = returnvalue::makeCode(HAL_SPI_ID, 1); +static constexpr ReturnValue_t HAL_ERROR_RETVAL = returnvalue::makeCode(HAL_SPI_ID, 2); enum class TransferStates { IDLE, WAIT, SUCCESS, FAILURE }; diff --git a/hal/src/fsfw_hal/stm32h7/spi/spiInterrupts.cpp b/src/fsfw_hal/stm32h7/spi/spiInterrupts.cpp similarity index 100% rename from hal/src/fsfw_hal/stm32h7/spi/spiInterrupts.cpp rename to src/fsfw_hal/stm32h7/spi/spiInterrupts.cpp diff --git a/hal/src/fsfw_hal/stm32h7/spi/spiInterrupts.h b/src/fsfw_hal/stm32h7/spi/spiInterrupts.h similarity index 100% rename from hal/src/fsfw_hal/stm32h7/spi/spiInterrupts.h rename to src/fsfw_hal/stm32h7/spi/spiInterrupts.h diff --git a/hal/src/fsfw_hal/stm32h7/spi/stm32h743zi.cpp b/src/fsfw_hal/stm32h7/spi/stm32h743zi.cpp similarity index 100% rename from hal/src/fsfw_hal/stm32h7/spi/stm32h743zi.cpp rename to src/fsfw_hal/stm32h7/spi/stm32h743zi.cpp diff --git a/hal/src/fsfw_hal/stm32h7/spi/stm32h743zi.h b/src/fsfw_hal/stm32h7/spi/stm32h743zi.h similarity index 100% rename from hal/src/fsfw_hal/stm32h7/spi/stm32h743zi.h rename to src/fsfw_hal/stm32h7/spi/stm32h743zi.h diff --git a/src/fsfw_hal/stm32h7/uart/CMakeLists.txt b/src/fsfw_hal/stm32h7/uart/CMakeLists.txt new file mode 100644 index 00000000..a0d48465 --- /dev/null +++ b/src/fsfw_hal/stm32h7/uart/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE) diff --git a/src/fsfw_tests/CMakeLists.txt b/src/fsfw_tests/CMakeLists.txt new file mode 100644 index 00000000..d161699a --- /dev/null +++ b/src/fsfw_tests/CMakeLists.txt @@ -0,0 +1,7 @@ +if(FSFW_ADD_INTERNAL_TESTS) + add_subdirectory(internal) +endif() + +if(NOT FSFW_BUILD_TESTS) + add_subdirectory(integration) +endif() diff --git a/tests/src/fsfw_tests/integration/CMakeLists.txt b/src/fsfw_tests/integration/CMakeLists.txt similarity index 100% rename from tests/src/fsfw_tests/integration/CMakeLists.txt rename to src/fsfw_tests/integration/CMakeLists.txt diff --git a/src/fsfw_tests/integration/assemblies/CMakeLists.txt b/src/fsfw_tests/integration/assemblies/CMakeLists.txt new file mode 100644 index 00000000..63a6447a --- /dev/null +++ b/src/fsfw_tests/integration/assemblies/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE TestAssembly.cpp) diff --git a/tests/src/fsfw_tests/integration/assemblies/TestAssembly.cpp b/src/fsfw_tests/integration/assemblies/TestAssembly.cpp similarity index 94% rename from tests/src/fsfw_tests/integration/assemblies/TestAssembly.cpp rename to src/fsfw_tests/integration/assemblies/TestAssembly.cpp index a0313f96..668120c6 100644 --- a/tests/src/fsfw_tests/integration/assemblies/TestAssembly.cpp +++ b/src/fsfw_tests/integration/assemblies/TestAssembly.cpp @@ -30,7 +30,7 @@ ReturnValue_t TestAssembly::commandChildren(Mode_t mode, Submode_t submode) { #else sif::printInfo("TestAssembly: Received command to go to mode %d submode %d\n", mode, submode); #endif - ReturnValue_t result = RETURN_OK; + ReturnValue_t result = returnvalue::OK; if (mode == MODE_OFF) { commandTable[0].setMode(MODE_OFF); commandTable[0].setSubmode(SUBMODE_NONE); @@ -113,14 +113,14 @@ ReturnValue_t TestAssembly::isModeCombinationValid(Mode_t mode, Submode_t submod switch (mode) { case MODE_OFF: if (submode == SUBMODE_NONE) { - return RETURN_OK; + return returnvalue::OK; } else { return INVALID_SUBMODE; } case DeviceHandlerIF::MODE_NORMAL: case MODE_ON: if (submode < 3) { - return RETURN_OK; + return returnvalue::OK; } else { return INVALID_SUBMODE; } @@ -130,24 +130,24 @@ ReturnValue_t TestAssembly::isModeCombinationValid(Mode_t mode, Submode_t submod ReturnValue_t TestAssembly::initialize() { ReturnValue_t result = AssemblyBase::initialize(); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } handler0 = ObjectManager::instance()->get(deviceHandler0Id); handler1 = ObjectManager::instance()->get(deviceHandler1Id); if ((handler0 == nullptr) or (handler1 == nullptr)) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } handler0->setParentQueue(this->getCommandQueue()); handler1->setParentQueue(this->getCommandQueue()); result = registerChild(deviceHandler0Id); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = registerChild(deviceHandler1Id); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } return result; @@ -160,11 +160,11 @@ ReturnValue_t TestAssembly::checkChildrenStateOn(Mode_t wantedMode, Submode_t wa return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE; } } - return RETURN_OK; + return returnvalue::OK; } else if (submode == submodes::SINGLE) { for (const auto& info : childrenMap) { if (info.second.mode == wantedMode and info.second.mode != wantedSubmode) { - return RETURN_OK; + return returnvalue::OK; } } } diff --git a/tests/src/fsfw_tests/integration/assemblies/TestAssembly.h b/src/fsfw_tests/integration/assemblies/TestAssembly.h similarity index 97% rename from tests/src/fsfw_tests/integration/assemblies/TestAssembly.h rename to src/fsfw_tests/integration/assemblies/TestAssembly.h index 6042f54e..91ffbf60 100644 --- a/tests/src/fsfw_tests/integration/assemblies/TestAssembly.h +++ b/src/fsfw_tests/integration/assemblies/TestAssembly.h @@ -22,7 +22,7 @@ class TestAssembly : public AssemblyBase { * @param mode * @param submode * @return - * - @c RETURN_OK if ok + * - @c returnvalue::OK if ok * - @c NEED_SECOND_STEP if children need to be commanded again */ ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) override; diff --git a/src/fsfw_tests/integration/controller/CMakeLists.txt b/src/fsfw_tests/integration/controller/CMakeLists.txt new file mode 100644 index 00000000..5eeb5c68 --- /dev/null +++ b/src/fsfw_tests/integration/controller/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE TestController.cpp) diff --git a/tests/src/fsfw_tests/integration/controller/TestController.cpp b/src/fsfw_tests/integration/controller/TestController.cpp similarity index 91% rename from tests/src/fsfw_tests/integration/controller/TestController.cpp rename to src/fsfw_tests/integration/controller/TestController.cpp index 03f24311..2ee4d5fe 100644 --- a/tests/src/fsfw_tests/integration/controller/TestController.cpp +++ b/src/fsfw_tests/integration/controller/TestController.cpp @@ -10,7 +10,7 @@ TestController::TestController(object_id_t objectId, object_id_t parentId, size_ TestController::~TestController() {} ReturnValue_t TestController::handleCommandMessage(CommandMessage *message) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void TestController::performControlOperation() {} @@ -24,7 +24,7 @@ LocalPoolDataSetBase *TestController::getDataSetHandle(sid_t sid) { return nullp ReturnValue_t TestController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t TestController::initializeAfterTaskCreation() { @@ -33,5 +33,5 @@ ReturnValue_t TestController::initializeAfterTaskCreation() { ReturnValue_t TestController::checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode) { - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } diff --git a/tests/src/fsfw_tests/integration/controller/TestController.h b/src/fsfw_tests/integration/controller/TestController.h similarity index 100% rename from tests/src/fsfw_tests/integration/controller/TestController.h rename to src/fsfw_tests/integration/controller/TestController.h diff --git a/tests/src/fsfw_tests/integration/controller/ctrldefinitions/testCtrlDefinitions.h b/src/fsfw_tests/integration/controller/ctrldefinitions/testCtrlDefinitions.h similarity index 100% rename from tests/src/fsfw_tests/integration/controller/ctrldefinitions/testCtrlDefinitions.h rename to src/fsfw_tests/integration/controller/ctrldefinitions/testCtrlDefinitions.h diff --git a/src/fsfw_tests/integration/devices/CMakeLists.txt b/src/fsfw_tests/integration/devices/CMakeLists.txt new file mode 100644 index 00000000..d5799197 --- /dev/null +++ b/src/fsfw_tests/integration/devices/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE TestCookie.cpp TestDeviceHandler.cpp + TestEchoComIF.cpp) diff --git a/tests/src/fsfw_tests/integration/devices/TestCookie.cpp b/src/fsfw_tests/integration/devices/TestCookie.cpp similarity index 100% rename from tests/src/fsfw_tests/integration/devices/TestCookie.cpp rename to src/fsfw_tests/integration/devices/TestCookie.cpp diff --git a/tests/src/fsfw_tests/integration/devices/TestCookie.h b/src/fsfw_tests/integration/devices/TestCookie.h similarity index 100% rename from tests/src/fsfw_tests/integration/devices/TestCookie.h rename to src/fsfw_tests/integration/devices/TestCookie.h diff --git a/tests/src/fsfw_tests/integration/devices/TestDeviceHandler.cpp b/src/fsfw_tests/integration/devices/TestDeviceHandler.cpp similarity index 95% rename from tests/src/fsfw_tests/integration/devices/TestDeviceHandler.cpp rename to src/fsfw_tests/integration/devices/TestDeviceHandler.cpp index cd15d6e0..fdf02a70 100644 --- a/tests/src/fsfw_tests/integration/devices/TestDeviceHandler.cpp +++ b/src/fsfw_tests/integration/devices/TestDeviceHandler.cpp @@ -13,14 +13,14 @@ TestDevice::TestDevice(object_id_t objectId, object_id_t comIF, CookieIF* cookie dataset(this), fullInfoPrintout(fullInfoPrintout) {} -TestDevice::~TestDevice() {} +TestDevice::~TestDevice() = default; void TestDevice::performOperationHook() { if (periodicPrintout) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TestDevice" << deviceIdx << "::performOperationHook: Alive!" << std::endl; #else - sif::printInfo("TestDevice%d::performOperationHook: Alive!", deviceIdx); + sif::printInfo("TestDevice%d::performOperationHook: Alive!\n", deviceIdx); #endif } @@ -139,7 +139,7 @@ ReturnValue_t TestDevice::buildCommandFromCommand(DeviceCommandId_t deviceComman const uint8_t* commandData, size_t commandDataLen) { using namespace testdevice; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; switch (deviceCommand) { case (TEST_NORMAL_MODE_CMD): { commandSent = true; @@ -222,7 +222,7 @@ ReturnValue_t TestDevice::buildNormalModeCommand(DeviceCommandId_t deviceCommand } /* The command is passed on in the command buffer as it is */ passOnCommand(deviceCommand, commandData, commandDataLen); - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t TestDevice::buildTestCommand0(DeviceCommandId_t deviceCommand, @@ -248,7 +248,7 @@ ReturnValue_t TestDevice::buildTestCommand0(DeviceCommandId_t deviceCommand, /* The command is passed on in the command buffer as it is */ passOnCommand(deviceCommand, commandData, commandDataLen); - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t TestDevice::buildTestCommand1(DeviceCommandId_t deviceCommand, @@ -277,7 +277,7 @@ ReturnValue_t TestDevice::buildTestCommand1(DeviceCommandId_t deviceCommand, size_t size = commandDataLen; ReturnValue_t result = SerializeAdapter::deSerialize(¶meter1, &commandData, &size, SerializeIF::Endianness::BIG); - if (result == HasReturnvaluesIF::RETURN_FAILED) { + if (result == returnvalue::FAILED) { return result; } @@ -299,7 +299,7 @@ ReturnValue_t TestDevice::buildTestCommand1(DeviceCommandId_t deviceCommand, memcpy(commandBuffer + 6, ¶meter2, sizeof(parameter2)); rawPacket = commandBuffer; rawPacketLen = sizeof(deviceCommand) + sizeof(parameter1) + sizeof(parameter2); - return RETURN_OK; + return returnvalue::OK; } void TestDevice::passOnCommand(DeviceCommandId_t command, const uint8_t* commandData, @@ -342,7 +342,7 @@ ReturnValue_t TestDevice::scanForReply(const uint8_t* start, size_t len, DeviceC size_t size = len; ReturnValue_t result = SerializeAdapter::deSerialize(foundId, &start, &size, SerializeIF::Endianness::BIG); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { return result; } @@ -366,7 +366,7 @@ ReturnValue_t TestDevice::scanForReply(const uint8_t* start, size_t len, DeviceC *foundLen = len; *foundId = pendingCmd; - return RETURN_OK; + return returnvalue::OK; } case (TEST_COMMAND_0): { @@ -389,7 +389,7 @@ ReturnValue_t TestDevice::scanForReply(const uint8_t* start, size_t len, DeviceC *foundLen = TEST_COMMAND_0_SIZE; *foundId = pendingCmd; - return RETURN_OK; + return returnvalue::OK; } case (TEST_COMMAND_1): { @@ -409,7 +409,7 @@ ReturnValue_t TestDevice::scanForReply(const uint8_t* start, size_t len, DeviceC *foundLen = len; *foundId = pendingCmd; - return RETURN_OK; + return returnvalue::OK; } default: @@ -418,7 +418,7 @@ ReturnValue_t TestDevice::scanForReply(const uint8_t* start, size_t len, DeviceC } ReturnValue_t TestDevice::interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; switch (id) { /* Periodic replies */ case testdevice::TEST_NORMAL_MODE_CMD: { @@ -460,7 +460,7 @@ ReturnValue_t TestDevice::interpretingNormalModeReply() { dataset.testFloat3Vec.value[2] = 0.0; dataset.setValidity(false, true); } - return RETURN_OK; + return returnvalue::OK; } PoolReadGuard readHelper(&dataset); @@ -570,7 +570,7 @@ ReturnValue_t TestDevice::interpretingNormalModeReply() { } } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t TestDevice::interpretingTestReply0(DeviceCommandId_t id, const uint8_t* packet) { @@ -589,7 +589,7 @@ ReturnValue_t TestDevice::interpretingTestReply0(DeviceCommandId_t id, const uin actionHelper.step(1, commander, id); actionHelper.finish(true, commander, id); - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t TestDevice::interpretingTestReply1(DeviceCommandId_t id, const uint8_t* packet) { @@ -608,7 +608,7 @@ ReturnValue_t TestDevice::interpretingTestReply1(DeviceCommandId_t id, const uin ReturnValue_t result = actionHelper.reportData(commander, id, packet, testdevice::TEST_COMMAND_1_SIZE, false); - if (result != RETURN_OK) { + if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "TestDevice" << deviceIdx << "::interpretingReply1: Sending data " @@ -620,7 +620,7 @@ ReturnValue_t TestDevice::interpretingTestReply1(DeviceCommandId_t id, const uin return result; } - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { /* Finish reply */ actionHelper.finish(true, commander, id); } else { @@ -628,7 +628,7 @@ ReturnValue_t TestDevice::interpretingTestReply1(DeviceCommandId_t id, const uin actionHelper.finish(false, commander, id, result); } - return RETURN_OK; + return returnvalue::OK; } uint32_t TestDevice::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 5000; } @@ -645,8 +645,8 @@ ReturnValue_t TestDevice::initializeLocalDataPool(localpool::DataPool& localData sid_t sid(this->getObjectId(), td::TEST_SET_ID); /* Subscribe for periodic HK packets but do not enable reporting for now. Non-diangostic with a period of one second */ - poolManager.subscribeForPeriodicPacket(sid, false, 1.0, false); - return HasReturnvaluesIF::RETURN_OK; + poolManager.subscribeForRegularPeriodicPacket({sid, false, 1.0}); + return returnvalue::OK; } ReturnValue_t TestDevice::getParameter(uint8_t domainId, uint8_t uniqueId, @@ -658,7 +658,7 @@ ReturnValue_t TestDevice::getParameter(uint8_t domainId, uint8_t uniqueId, if (fullInfoPrintout) { uint32_t newValue = 0; ReturnValue_t result = newValues->getElement(&newValue, 0, 0); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TestDevice" << deviceIdx << "::getParameter: Setting parameter 0 to " @@ -677,7 +677,7 @@ ReturnValue_t TestDevice::getParameter(uint8_t domainId, uint8_t uniqueId, if (fullInfoPrintout) { int32_t newValue = 0; ReturnValue_t result = newValues->getElement(&newValue, 0, 0); - if (result == HasReturnvaluesIF::RETURN_OK) { + if (result == returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TestDevice" << deviceIdx << "::getParameter: Setting parameter 1 to " @@ -695,10 +695,10 @@ ReturnValue_t TestDevice::getParameter(uint8_t domainId, uint8_t uniqueId, case ParameterUniqueIds::TEST_FLOAT_VEC3_2: { if (fullInfoPrintout) { float newVector[3]; - if (newValues->getElement(newVector, 0, 0) != RETURN_OK or - newValues->getElement(newVector + 1, 0, 1) != RETURN_OK or - newValues->getElement(newVector + 2, 0, 2) != RETURN_OK) { - return HasReturnvaluesIF::RETURN_FAILED; + if (newValues->getElement(newVector, 0, 0) != returnvalue::OK or + newValues->getElement(newVector + 1, 0, 1) != returnvalue::OK or + newValues->getElement(newVector + 2, 0, 2) != returnvalue::OK) { + return returnvalue::FAILED; } #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TestDevice" << deviceIdx @@ -720,7 +720,7 @@ ReturnValue_t TestDevice::getParameter(uint8_t domainId, uint8_t uniqueId, if (fullInfoPrintout) { uint8_t enabled = 0; ReturnValue_t result = newValues->getElement(&enabled, 0, 0); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } char const* printout = nullptr; @@ -743,7 +743,7 @@ ReturnValue_t TestDevice::getParameter(uint8_t domainId, uint8_t uniqueId, case (ParameterUniqueIds::CHANGING_DATASETS): { uint8_t enabled = 0; ReturnValue_t result = newValues->getElement(&enabled, 0, 0); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { return result; } if (not enabled) { @@ -776,7 +776,7 @@ ReturnValue_t TestDevice::getParameter(uint8_t domainId, uint8_t uniqueId, default: return INVALID_IDENTIFIER_ID; } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } LocalPoolObjectBase* TestDevice::getPoolObjectHandle(lp_id_t localPoolId) { diff --git a/tests/src/fsfw_tests/integration/devices/TestDeviceHandler.h b/src/fsfw_tests/integration/devices/TestDeviceHandler.h similarity index 100% rename from tests/src/fsfw_tests/integration/devices/TestDeviceHandler.h rename to src/fsfw_tests/integration/devices/TestDeviceHandler.h diff --git a/tests/src/fsfw_tests/integration/devices/TestEchoComIF.cpp b/src/fsfw_tests/integration/devices/TestEchoComIF.cpp similarity index 92% rename from tests/src/fsfw_tests/integration/devices/TestEchoComIF.cpp rename to src/fsfw_tests/integration/devices/TestEchoComIF.cpp index 727381a2..c0aa64a4 100644 --- a/tests/src/fsfw_tests/integration/devices/TestEchoComIF.cpp +++ b/src/fsfw_tests/integration/devices/TestEchoComIF.cpp @@ -25,9 +25,9 @@ ReturnValue_t TestEchoComIF::initializeInterface(CookieIF *cookie) { auto resultPair = replyMap.emplace(dummyCookie->getAddress(), ReplyBuffer(dummyCookie->getReplyMaxLen())); if (not resultPair.second) { - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t TestEchoComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, @@ -50,17 +50,17 @@ ReturnValue_t TestEchoComIF::sendMessage(CookieIF *cookie, const uint8_t *sendDa "reply buffer length!\n", sendLen); #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } replyBuffer.resize(sendLen); memcpy(replyBuffer.data(), sendData, sendLen); - return RETURN_OK; + return returnvalue::OK; } -ReturnValue_t TestEchoComIF::getSendSuccess(CookieIF *cookie) { return RETURN_OK; } +ReturnValue_t TestEchoComIF::getSendSuccess(CookieIF *cookie) { return returnvalue::OK; } ReturnValue_t TestEchoComIF::requestReceiveMessage(CookieIF *cookie, size_t requestLen) { - return RETURN_OK; + return returnvalue::OK; } ReturnValue_t TestEchoComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) { @@ -78,5 +78,5 @@ ReturnValue_t TestEchoComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buf // add anything that needs to be read periodically by dummy handler dummyReplyCounter = 0; } - return RETURN_OK; + return returnvalue::OK; } diff --git a/tests/src/fsfw_tests/integration/devices/TestEchoComIF.h b/src/fsfw_tests/integration/devices/TestEchoComIF.h similarity index 100% rename from tests/src/fsfw_tests/integration/devices/TestEchoComIF.h rename to src/fsfw_tests/integration/devices/TestEchoComIF.h diff --git a/tests/src/fsfw_tests/integration/devices/devicedefinitions/testDeviceDefinitions.h b/src/fsfw_tests/integration/devices/devicedefinitions/testDeviceDefinitions.h similarity index 100% rename from tests/src/fsfw_tests/integration/devices/devicedefinitions/testDeviceDefinitions.h rename to src/fsfw_tests/integration/devices/devicedefinitions/testDeviceDefinitions.h diff --git a/src/fsfw_tests/integration/task/CMakeLists.txt b/src/fsfw_tests/integration/task/CMakeLists.txt new file mode 100644 index 00000000..62d5e8ef --- /dev/null +++ b/src/fsfw_tests/integration/task/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE TestTask.cpp) diff --git a/tests/src/fsfw_tests/integration/task/TestTask.cpp b/src/fsfw_tests/integration/task/TestTask.cpp similarity index 87% rename from tests/src/fsfw_tests/integration/task/TestTask.cpp rename to src/fsfw_tests/integration/task/TestTask.cpp index 765f780e..a09644d2 100644 --- a/tests/src/fsfw_tests/integration/task/TestTask.cpp +++ b/src/fsfw_tests/integration/task/TestTask.cpp @@ -12,10 +12,10 @@ TestTask::TestTask(object_id_t objectId) : SystemObject(objectId), testMode(test IPCStore = ObjectManager::instance()->get(objects::IPC_STORE); } -TestTask::~TestTask() {} +TestTask::~TestTask() = default; ReturnValue_t TestTask::performOperation(uint8_t operationCode) { - ReturnValue_t result = RETURN_OK; + ReturnValue_t result = returnvalue::OK; testLock->lockMutex(MutexIF::TimeoutType::WAITING, 20); if (oneShotAction) { // Add code here which should only be run once @@ -40,23 +40,23 @@ ReturnValue_t TestTask::performOperation(uint8_t operationCode) { ReturnValue_t TestTask::performOneShotAction() { /* Everything here will only be performed once. */ - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t TestTask::performPeriodicAction() { /* This is performed each task cycle */ - ReturnValue_t result = RETURN_OK; + ReturnValue_t result = returnvalue::OK; return result; } ReturnValue_t TestTask::performActionA() { /* This is performed each alternating task cycle */ - ReturnValue_t result = RETURN_OK; + ReturnValue_t result = returnvalue::OK; return result; } ReturnValue_t TestTask::performActionB() { /* This is performed each alternating task cycle */ - ReturnValue_t result = RETURN_OK; + ReturnValue_t result = returnvalue::OK; return result; } diff --git a/tests/src/fsfw_tests/integration/task/TestTask.h b/src/fsfw_tests/integration/task/TestTask.h similarity index 79% rename from tests/src/fsfw_tests/integration/task/TestTask.h rename to src/fsfw_tests/integration/task/TestTask.h index cd630ee3..40eb4afd 100644 --- a/tests/src/fsfw_tests/integration/task/TestTask.h +++ b/src/fsfw_tests/integration/task/TestTask.h @@ -11,11 +11,11 @@ * @details * Should not be used for board specific tests. Instead, a derived board test class should be used. */ -class TestTask : public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF { +class TestTask : public SystemObject, public ExecutableObjectIF { public: - TestTask(object_id_t objectId); - virtual ~TestTask(); - virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; + explicit TestTask(object_id_t objectId); + ~TestTask() override; + ReturnValue_t performOperation(uint8_t operationCode) override; protected: virtual ReturnValue_t performOneShotAction(); diff --git a/src/fsfw_tests/internal/CMakeLists.txt b/src/fsfw_tests/internal/CMakeLists.txt new file mode 100644 index 00000000..c1af5467 --- /dev/null +++ b/src/fsfw_tests/internal/CMakeLists.txt @@ -0,0 +1,6 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE InternalUnitTester.cpp + UnittDefinitions.cpp) + +add_subdirectory(osal) +add_subdirectory(serialize) +add_subdirectory(globalfunctions) diff --git a/tests/src/fsfw_tests/internal/InternalUnitTester.cpp b/src/fsfw_tests/internal/InternalUnitTester.cpp similarity index 97% rename from tests/src/fsfw_tests/internal/InternalUnitTester.cpp rename to src/fsfw_tests/internal/InternalUnitTester.cpp index 4e45d25b..a135359c 100644 --- a/tests/src/fsfw_tests/internal/InternalUnitTester.cpp +++ b/src/fsfw_tests/internal/InternalUnitTester.cpp @@ -37,5 +37,5 @@ ReturnValue_t InternalUnitTester::performTests( #else sif::printInfo("Internal unit tests finished.\n"); #endif - return RETURN_OK; + return returnvalue::OK; } diff --git a/tests/src/fsfw_tests/internal/InternalUnitTester.h b/src/fsfw_tests/internal/InternalUnitTester.h similarity index 89% rename from tests/src/fsfw_tests/internal/InternalUnitTester.h rename to src/fsfw_tests/internal/InternalUnitTester.h index d6d7ca36..89bac368 100644 --- a/tests/src/fsfw_tests/internal/InternalUnitTester.h +++ b/src/fsfw_tests/internal/InternalUnitTester.h @@ -2,7 +2,7 @@ #define FRAMEWORK_TEST_UNITTESTCLASS_H_ #include "UnittDefinitions.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" /** * @brief Can be used for internal testing, for example for hardware specific @@ -13,7 +13,7 @@ * which simply calls all other tests from other files manually. * Maybe there is a better way.. */ -class InternalUnitTester : public HasReturnvaluesIF { +class InternalUnitTester { public: struct TestConfig { bool testArrayPrinter = false; diff --git a/tests/src/fsfw_tests/internal/UnittDefinitions.cpp b/src/fsfw_tests/internal/UnittDefinitions.cpp similarity index 89% rename from tests/src/fsfw_tests/internal/UnittDefinitions.cpp rename to src/fsfw_tests/internal/UnittDefinitions.cpp index 3322b1ad..ea562591 100644 --- a/tests/src/fsfw_tests/internal/UnittDefinitions.cpp +++ b/src/fsfw_tests/internal/UnittDefinitions.cpp @@ -6,5 +6,5 @@ ReturnValue_t unitt::put_error(std::string errorId) { #else sif::printError("Unit Tester error: Failed at test ID %s\n", errorId.c_str()); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } diff --git a/tests/src/fsfw_tests/internal/UnittDefinitions.h b/src/fsfw_tests/internal/UnittDefinitions.h similarity index 94% rename from tests/src/fsfw_tests/internal/UnittDefinitions.h rename to src/fsfw_tests/internal/UnittDefinitions.h index 11e83d22..4517d94e 100644 --- a/tests/src/fsfw_tests/internal/UnittDefinitions.h +++ b/src/fsfw_tests/internal/UnittDefinitions.h @@ -5,7 +5,7 @@ #include #include -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/serviceinterface/ServiceInterface.h" namespace tv { diff --git a/src/fsfw_tests/internal/globalfunctions/CMakeLists.txt b/src/fsfw_tests/internal/globalfunctions/CMakeLists.txt new file mode 100644 index 00000000..6e7e58ad --- /dev/null +++ b/src/fsfw_tests/internal/globalfunctions/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE TestArrayPrinter.cpp) diff --git a/tests/src/fsfw_tests/internal/globalfunctions/TestArrayPrinter.cpp b/src/fsfw_tests/internal/globalfunctions/TestArrayPrinter.cpp similarity index 100% rename from tests/src/fsfw_tests/internal/globalfunctions/TestArrayPrinter.cpp rename to src/fsfw_tests/internal/globalfunctions/TestArrayPrinter.cpp diff --git a/tests/src/fsfw_tests/internal/globalfunctions/TestArrayPrinter.h b/src/fsfw_tests/internal/globalfunctions/TestArrayPrinter.h similarity index 100% rename from tests/src/fsfw_tests/internal/globalfunctions/TestArrayPrinter.h rename to src/fsfw_tests/internal/globalfunctions/TestArrayPrinter.h diff --git a/src/fsfw_tests/internal/osal/CMakeLists.txt b/src/fsfw_tests/internal/osal/CMakeLists.txt new file mode 100644 index 00000000..db1031a0 --- /dev/null +++ b/src/fsfw_tests/internal/osal/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE testMq.cpp testMutex.cpp + testSemaphore.cpp) diff --git a/tests/src/fsfw_tests/internal/osal/testMq.cpp b/src/fsfw_tests/internal/osal/testMq.cpp similarity index 84% rename from tests/src/fsfw_tests/internal/osal/testMq.cpp rename to src/fsfw_tests/internal/osal/testMq.cpp index 0f78dbb9..88082b0a 100644 --- a/tests/src/fsfw_tests/internal/osal/testMq.cpp +++ b/src/fsfw_tests/internal/osal/testMq.cpp @@ -7,8 +7,6 @@ #include "fsfw_tests/internal/UnittDefinitions.h" -using retval = HasReturnvaluesIF; - void testmq::testMq() { std::string id = "[testMq]"; MessageQueueIF* testSenderMq = QueueFactory::instance()->createMessageQueue(1); @@ -22,22 +20,22 @@ void testmq::testMq() { testSenderMq->setDefaultDestination(testReceiverMqId); auto result = testSenderMq->sendMessage(testReceiverMqId, &testMessage); - if (result != retval::RETURN_OK) { + if (result != returnvalue::OK) { unitt::put_error(id); } MessageQueueMessage recvMessage; result = testReceiverMq->receiveMessage(&recvMessage); - if (result != retval::RETURN_OK or recvMessage.getData()[0] != 42) { + if (result != returnvalue::OK or recvMessage.getData()[0] != 42) { unitt::put_error(id); } result = testSenderMq->sendMessage(testReceiverMqId, &testMessage); - if (result != retval::RETURN_OK) { + if (result != returnvalue::OK) { unitt::put_error(id); } MessageQueueId_t senderId = 0; result = testReceiverMq->receiveMessage(&recvMessage, &senderId); - if (result != retval::RETURN_OK or recvMessage.getData()[0] != 42) { + if (result != returnvalue::OK or recvMessage.getData()[0] != 42) { unitt::put_error(id); } if (senderId != testSenderMqId) { diff --git a/tests/src/fsfw_tests/internal/osal/testMq.h b/src/fsfw_tests/internal/osal/testMq.h similarity index 100% rename from tests/src/fsfw_tests/internal/osal/testMq.h rename to src/fsfw_tests/internal/osal/testMq.h diff --git a/tests/src/fsfw_tests/internal/osal/testMutex.cpp b/src/fsfw_tests/internal/osal/testMutex.cpp similarity index 93% rename from tests/src/fsfw_tests/internal/osal/testMutex.cpp rename to src/fsfw_tests/internal/osal/testMutex.cpp index 6206c31d..98c471cb 100644 --- a/tests/src/fsfw_tests/internal/osal/testMutex.cpp +++ b/src/fsfw_tests/internal/osal/testMutex.cpp @@ -16,7 +16,7 @@ void testmutex::testMutex() { std::string id = "[testMutex]"; MutexIF* mutex = MutexFactory::instance()->createMutex(); auto result = mutex->lockMutex(MutexIF::TimeoutType::POLLING); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { unitt::put_error(id); } // timed_mutex from the C++ library specifies undefined behaviour if @@ -35,7 +35,7 @@ void testmutex::testMutex() { } result = mutex->unlockMutex(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { unitt::put_error(id); } diff --git a/tests/src/fsfw_tests/internal/osal/testMutex.h b/src/fsfw_tests/internal/osal/testMutex.h similarity index 100% rename from tests/src/fsfw_tests/internal/osal/testMutex.h rename to src/fsfw_tests/internal/osal/testMutex.h diff --git a/tests/src/fsfw_tests/internal/osal/testSemaphore.cpp b/src/fsfw_tests/internal/osal/testSemaphore.cpp similarity index 94% rename from tests/src/fsfw_tests/internal/osal/testSemaphore.cpp rename to src/fsfw_tests/internal/osal/testSemaphore.cpp index a3e4c277..df88b4ed 100644 --- a/tests/src/fsfw_tests/internal/osal/testSemaphore.cpp +++ b/src/fsfw_tests/internal/osal/testSemaphore.cpp @@ -54,7 +54,7 @@ void testsemaph::testCountingSemaph() { // release 3 times in a row for (int i = 0; i < 3; i++) { auto result = countingSemaph->release(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { unitt::put_error(id); } } @@ -75,7 +75,7 @@ void testsemaph::testBinSemaphoreImplementation(SemaphoreIF* binSemaph, std::str unitt::put_error(id); } result = binSemaph->acquire(SemaphoreIF::BLOCKING); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { unitt::put_error(id); } @@ -104,7 +104,7 @@ void testsemaph::testBinSemaphoreImplementation(SemaphoreIF* binSemaph, std::str } result = binSemaph->release(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { unitt::put_error(id); } } @@ -122,7 +122,7 @@ void testsemaph::testCountingSemaphImplementation(SemaphoreIF* countingSemaph, s // acquire 3 times in a row for (int i = 0; i < 3; i++) { result = countingSemaph->acquire(SemaphoreIF::BLOCKING); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { unitt::put_error(id); } } @@ -144,7 +144,7 @@ void testsemaph::testCountingSemaphImplementation(SemaphoreIF* countingSemaph, s // release 3 times in a row for (int i = 0; i < 3; i++) { result = countingSemaph->release(); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (result != returnvalue::OK) { unitt::put_error(id); } } diff --git a/tests/src/fsfw_tests/internal/osal/testSemaphore.h b/src/fsfw_tests/internal/osal/testSemaphore.h similarity index 100% rename from tests/src/fsfw_tests/internal/osal/testSemaphore.h rename to src/fsfw_tests/internal/osal/testSemaphore.h diff --git a/src/fsfw_tests/internal/serialize/CMakeLists.txt b/src/fsfw_tests/internal/serialize/CMakeLists.txt new file mode 100644 index 00000000..ee264d9d --- /dev/null +++ b/src/fsfw_tests/internal/serialize/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE IntTestSerialization.cpp) diff --git a/tests/src/fsfw_tests/internal/serialize/IntTestSerialization.cpp b/src/fsfw_tests/internal/serialize/IntTestSerialization.cpp similarity index 97% rename from tests/src/fsfw_tests/internal/serialize/IntTestSerialization.cpp rename to src/fsfw_tests/internal/serialize/IntTestSerialization.cpp index 8e1f2bdd..58ab05c1 100644 --- a/tests/src/fsfw_tests/internal/serialize/IntTestSerialization.cpp +++ b/src/fsfw_tests/internal/serialize/IntTestSerialization.cpp @@ -8,24 +8,23 @@ #include "fsfw_tests/internal/UnittDefinitions.h" -using retval = HasReturnvaluesIF; std::array testserialize::test_array = {0}; ReturnValue_t testserialize::test_serialization() { // Here, we test all serialization tools. First test basic cases. ReturnValue_t result = test_endianness_tools(); - if (result != retval::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = test_autoserialization(); - if (result != retval::RETURN_OK) { + if (result != returnvalue::OK) { return result; } result = test_serial_buffer_adapter(); - if (result != retval::RETURN_OK) { + if (result != returnvalue::OK) { return result; } - return retval::RETURN_OK; + return returnvalue::OK; } ReturnValue_t testserialize::test_endianness_tools() { @@ -49,7 +48,7 @@ ReturnValue_t testserialize::test_endianness_tools() { if (test_array[0] != 0 and test_array[1] != 1) { return unitt::put_error(id); } - return retval::RETURN_OK; + return returnvalue::OK; } ReturnValue_t testserialize::test_autoserialization() { @@ -153,7 +152,7 @@ ReturnValue_t testserialize::test_autoserialization() { } // Check overflow - return retval::RETURN_OK; + return returnvalue::OK; } // TODO: Also test for constant buffers. @@ -206,5 +205,5 @@ ReturnValue_t testserialize::test_serial_buffer_adapter() { if (testUint16 != 16) { return unitt::put_error(id); } - return retval::RETURN_OK; + return returnvalue::OK; } diff --git a/tests/src/fsfw_tests/internal/serialize/IntTestSerialization.h b/src/fsfw_tests/internal/serialize/IntTestSerialization.h similarity index 90% rename from tests/src/fsfw_tests/internal/serialize/IntTestSerialization.h rename to src/fsfw_tests/internal/serialize/IntTestSerialization.h index 2f1786d4..939b6614 100644 --- a/tests/src/fsfw_tests/internal/serialize/IntTestSerialization.h +++ b/src/fsfw_tests/internal/serialize/IntTestSerialization.h @@ -3,7 +3,7 @@ #include -#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/returnvalues/returnvalue.h" namespace testserialize { ReturnValue_t test_serialization(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt deleted file mode 100644 index febd4f0a..00000000 --- a/tests/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(src) diff --git a/tests/src/CMakeLists.txt b/tests/src/CMakeLists.txt deleted file mode 100644 index 6673f1e4..00000000 --- a/tests/src/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -target_include_directories(${LIB_FSFW_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} -) - -target_include_directories(${LIB_FSFW_NAME} INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR} -) - -add_subdirectory(fsfw_tests) diff --git a/tests/src/fsfw_tests/CMakeLists.txt b/tests/src/fsfw_tests/CMakeLists.txt deleted file mode 100644 index f6e1b8ab..00000000 --- a/tests/src/fsfw_tests/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -if(FSFW_ADD_INTERNAL_TESTS) - add_subdirectory(internal) -endif() - -if(FSFW_BUILD_UNITTESTS) - add_subdirectory(unit) -else() - add_subdirectory(integration) -endif() diff --git a/tests/src/fsfw_tests/integration/assemblies/CMakeLists.txt b/tests/src/fsfw_tests/integration/assemblies/CMakeLists.txt deleted file mode 100644 index 22c06600..00000000 --- a/tests/src/fsfw_tests/integration/assemblies/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - TestAssembly.cpp -) \ No newline at end of file diff --git a/tests/src/fsfw_tests/integration/controller/CMakeLists.txt b/tests/src/fsfw_tests/integration/controller/CMakeLists.txt deleted file mode 100644 index f5655b71..00000000 --- a/tests/src/fsfw_tests/integration/controller/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - TestController.cpp -) \ No newline at end of file diff --git a/tests/src/fsfw_tests/integration/devices/CMakeLists.txt b/tests/src/fsfw_tests/integration/devices/CMakeLists.txt deleted file mode 100644 index cfd238d2..00000000 --- a/tests/src/fsfw_tests/integration/devices/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - TestCookie.cpp - TestDeviceHandler.cpp - TestEchoComIF.cpp -) diff --git a/tests/src/fsfw_tests/integration/task/CMakeLists.txt b/tests/src/fsfw_tests/integration/task/CMakeLists.txt deleted file mode 100644 index 4cd481bf..00000000 --- a/tests/src/fsfw_tests/integration/task/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - TestTask.cpp -) \ No newline at end of file diff --git a/tests/src/fsfw_tests/internal/CMakeLists.txt b/tests/src/fsfw_tests/internal/CMakeLists.txt deleted file mode 100644 index 2a144a9b..00000000 --- a/tests/src/fsfw_tests/internal/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - InternalUnitTester.cpp - UnittDefinitions.cpp -) - -add_subdirectory(osal) -add_subdirectory(serialize) -add_subdirectory(globalfunctions) \ No newline at end of file diff --git a/tests/src/fsfw_tests/internal/globalfunctions/CMakeLists.txt b/tests/src/fsfw_tests/internal/globalfunctions/CMakeLists.txt deleted file mode 100644 index cde97734..00000000 --- a/tests/src/fsfw_tests/internal/globalfunctions/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - TestArrayPrinter.cpp -) diff --git a/tests/src/fsfw_tests/internal/osal/CMakeLists.txt b/tests/src/fsfw_tests/internal/osal/CMakeLists.txt deleted file mode 100644 index 8d79d759..00000000 --- a/tests/src/fsfw_tests/internal/osal/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - testMq.cpp - testMutex.cpp - testSemaphore.cpp -) diff --git a/tests/src/fsfw_tests/internal/serialize/CMakeLists.txt b/tests/src/fsfw_tests/internal/serialize/CMakeLists.txt deleted file mode 100644 index 47e8b538..00000000 --- a/tests/src/fsfw_tests/internal/serialize/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - IntTestSerialization.cpp -) diff --git a/tests/src/fsfw_tests/unit/CMakeLists.txt b/tests/src/fsfw_tests/unit/CMakeLists.txt deleted file mode 100644 index a8d31d88..00000000 --- a/tests/src/fsfw_tests/unit/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE - CatchDefinitions.cpp - CatchFactory.cpp - printChar.cpp - version.cpp -) - -target_sources(${FSFW_TEST_TGT} PRIVATE - CatchRunner.cpp - CatchSetup.cpp -) - -add_subdirectory(testcfg) -add_subdirectory(action) -add_subdirectory(container) -add_subdirectory(osal) -add_subdirectory(serialize) -add_subdirectory(datapoollocal) -add_subdirectory(storagemanager) -add_subdirectory(globalfunctions) -add_subdirectory(timemanager) -add_subdirectory(tmtcpacket) -add_subdirectory(cfdp) -add_subdirectory(hal) -add_subdirectory(internalerror) diff --git a/tests/src/fsfw_tests/unit/action/CMakeLists.txt b/tests/src/fsfw_tests/unit/action/CMakeLists.txt deleted file mode 100644 index 659f251a..00000000 --- a/tests/src/fsfw_tests/unit/action/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE - TestActionHelper.cpp -) diff --git a/tests/src/fsfw_tests/unit/cfdp/CMakeLists.txt b/tests/src/fsfw_tests/unit/cfdp/CMakeLists.txt deleted file mode 100644 index 8e18cd3b..00000000 --- a/tests/src/fsfw_tests/unit/cfdp/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE - testCfdp.cpp - testTlvsLvs.cpp - testAckPdu.cpp - testEofPdu.cpp - testNakPdu.cpp - testFinishedPdu.cpp - testPromptPdu.cpp - testKeepAlivePdu.cpp - testMetadataPdu.cpp - testFileData.cpp -) diff --git a/tests/src/fsfw_tests/unit/cfdp/testAckPdu.cpp b/tests/src/fsfw_tests/unit/cfdp/testAckPdu.cpp deleted file mode 100644 index e5668799..00000000 --- a/tests/src/fsfw_tests/unit/cfdp/testAckPdu.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include - -#include "fsfw/cfdp/pdu/AckPduDeserializer.h" -#include "fsfw/cfdp/pdu/AckPduSerializer.h" -#include "fsfw/globalfunctions/arrayprinter.h" - -TEST_CASE("ACK PDU", "[AckPdu]") { - using namespace cfdp; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - std::array buf = {}; - uint8_t* bufptr = buf.data(); - size_t maxsz = buf.size(); - size_t sz = 0; - auto seqNum = TransactionSeqNum(WidthInBytes::TWO_BYTES, 15); - auto sourceId = EntityId(WidthInBytes::TWO_BYTES, 1); - auto destId = EntityId(WidthInBytes::TWO_BYTES, 2); - auto pduConf = PduConfig(TransmissionModes::ACKNOWLEDGED, seqNum, sourceId, destId); - AckInfo ackInfo(FileDirectives::EOF_DIRECTIVE, ConditionCode::NO_ERROR, - AckTransactionStatus::ACTIVE); - auto ackSerializer = AckPduSerializer(ackInfo, pduConf); - result = ackSerializer.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - - SECTION("Serialize") { - REQUIRE(buf.data()[sz - 3] == cfdp::FileDirectives::ACK); - REQUIRE((buf.data()[sz - 2] >> 4) == FileDirectives::EOF_DIRECTIVE); - REQUIRE((buf.data()[sz - 2] & 0x0f) == 0); - REQUIRE(buf.data()[sz - 1] == AckTransactionStatus::ACTIVE); - ackInfo.setAckedDirective(FileDirectives::FINISH); - ackInfo.setAckedConditionCode(ConditionCode::FILESTORE_REJECTION); - ackInfo.setTransactionStatus(AckTransactionStatus::TERMINATED); - auto ackSerializer2 = AckPduSerializer(ackInfo, pduConf); - bufptr = buf.data(); - sz = 0; - result = ackSerializer2.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(buf.data()[sz - 3] == cfdp::FileDirectives::ACK); - REQUIRE((buf.data()[sz - 2] >> 4) == FileDirectives::FINISH); - REQUIRE((buf.data()[sz - 2] & 0x0f) == 0b0001); - REQUIRE((buf.data()[sz - 1] >> 4) == ConditionCode::FILESTORE_REJECTION); - REQUIRE((buf.data()[sz - 1] & 0b11) == AckTransactionStatus::TERMINATED); - - bufptr = buf.data(); - sz = 0; - ackInfo.setAckedDirective(FileDirectives::KEEP_ALIVE); - auto ackSerializer3 = AckPduSerializer(ackInfo, pduConf); - result = ackSerializer3.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK); - // Invalid file directive - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); - - ackInfo.setAckedDirective(FileDirectives::FINISH); - // buffer too small - result = ackSerializer.serialize(&bufptr, &sz, 8, SerializeIF::Endianness::NETWORK); - REQUIRE(result == SerializeIF::BUFFER_TOO_SHORT); - } - - SECTION("Deserialize") { - AckInfo ackInfo; - auto reader = AckPduDeserializer(buf.data(), sz, ackInfo); - result = reader.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(ackInfo.getAckedDirective() == FileDirectives::EOF_DIRECTIVE); - REQUIRE(ackInfo.getAckedConditionCode() == ConditionCode::NO_ERROR); - REQUIRE(ackInfo.getDirectiveSubtypeCode() == 0); - REQUIRE(ackInfo.getTransactionStatus() == AckTransactionStatus::ACTIVE); - - AckInfo newInfo = AckInfo(FileDirectives::FINISH, ConditionCode::FILESTORE_REJECTION, - AckTransactionStatus::TERMINATED); - auto ackSerializer2 = AckPduSerializer(newInfo, pduConf); - bufptr = buf.data(); - sz = 0; - result = ackSerializer2.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - - auto reader2 = AckPduDeserializer(buf.data(), sz, ackInfo); - result = reader2.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(ackInfo.getAckedDirective() == FileDirectives::FINISH); - REQUIRE(ackInfo.getAckedConditionCode() == ConditionCode::FILESTORE_REJECTION); - REQUIRE(ackInfo.getDirectiveSubtypeCode() == 0b0001); - REQUIRE(ackInfo.getTransactionStatus() == AckTransactionStatus::TERMINATED); - - uint8_t prevVal = buf[sz - 2]; - buf[sz - 2] = FileDirectives::INVALID_DIRECTIVE << 4; - result = reader2.parseData(); - REQUIRE(result == cfdp::INVALID_ACK_DIRECTIVE_FIELDS); - buf[sz - 2] = FileDirectives::FINISH << 4 | 0b1111; - result = reader2.parseData(); - REQUIRE(result == cfdp::INVALID_ACK_DIRECTIVE_FIELDS); - buf[sz - 2] = prevVal; - buf[sz - 3] = cfdp::FileDirectives::INVALID_DIRECTIVE; - result = reader2.parseData(); - REQUIRE(result == cfdp::INVALID_DIRECTIVE_FIELDS); - buf[sz - 3] = cfdp::FileDirectives::ACK; - auto maxSizeTooSmall = AckPduDeserializer(buf.data(), sz - 2, ackInfo); - result = maxSizeTooSmall.parseData(); - REQUIRE(result == SerializeIF::STREAM_TOO_SHORT); - } -} diff --git a/tests/src/fsfw_tests/unit/cfdp/testCfdp.cpp b/tests/src/fsfw_tests/unit/cfdp/testCfdp.cpp deleted file mode 100644 index 19b1ec7f..00000000 --- a/tests/src/fsfw_tests/unit/cfdp/testCfdp.cpp +++ /dev/null @@ -1,368 +0,0 @@ -#include -#include -#include - -#include "fsfw/cfdp/FileSize.h" -#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h" -#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h" -#include "fsfw/cfdp/pdu/HeaderDeserializer.h" -#include "fsfw/cfdp/pdu/HeaderSerializer.h" -#include "fsfw/globalfunctions/arrayprinter.h" -#include "fsfw/serialize/SerializeAdapter.h" -#include "fsfw_tests/unit/CatchDefinitions.h" - -TEST_CASE("CFDP Base", "[CfdpBase]") { - using namespace cfdp; - std::array serBuf; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - cfdp::TransactionSeqNum seqNum = TransactionSeqNum(cfdp::WidthInBytes::ONE_BYTE, 2); - cfdp::EntityId sourceId = EntityId(cfdp::WidthInBytes::ONE_BYTE, 0); - cfdp::EntityId destId = EntityId(cfdp::WidthInBytes::ONE_BYTE, 1); - PduConfig pduConf = - PduConfig(cfdp::TransmissionModes::ACKNOWLEDGED, seqNum, sourceId, destId, false); - uint8_t* serTarget = serBuf.data(); - const uint8_t* deserTarget = serTarget; - size_t serSize = 0; - - SECTION("Header Serialization") { - auto headerSerializer = HeaderSerializer(pduConf, cfdp::PduType::FILE_DIRECTIVE, 0); - const uint8_t** dummyPtr = nullptr; - ReturnValue_t deserResult = - headerSerializer.deSerialize(dummyPtr, &serSize, SerializeIF::Endianness::NETWORK); - REQUIRE(deserResult == retval::CATCH_FAILED); - deserResult = headerSerializer.serialize(nullptr, &serSize, serBuf.size(), - SerializeIF::Endianness::NETWORK); - REQUIRE(deserResult == retval::CATCH_FAILED); - REQUIRE(seqNum.getSerializedSize() == 1); - - REQUIRE(headerSerializer.getPduDataFieldLen() == 0); - REQUIRE(headerSerializer.getSerializedSize() == 7); - REQUIRE(headerSerializer.getWholePduSize() == 7); - REQUIRE(headerSerializer.getCrcFlag() == false); - REQUIRE(headerSerializer.getDirection() == cfdp::Direction::TOWARDS_RECEIVER); - REQUIRE(headerSerializer.getLargeFileFlag() == false); - REQUIRE(headerSerializer.getLenEntityIds() == 1); - REQUIRE(headerSerializer.getLenSeqNum() == 1); - REQUIRE(headerSerializer.getPduType() == cfdp::PduType::FILE_DIRECTIVE); - REQUIRE(headerSerializer.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::NOT_PRESENT); - REQUIRE(headerSerializer.getSegmentationControl() == false); - REQUIRE(headerSerializer.getTransmissionMode() == cfdp::TransmissionModes::ACKNOWLEDGED); - - cfdp::TransactionSeqNum seqNumLocal; - headerSerializer.getTransactionSeqNum(seqNumLocal); - REQUIRE(seqNumLocal.getWidth() == cfdp::WidthInBytes::ONE_BYTE); - REQUIRE(seqNumLocal.getValue() == 2); - cfdp::EntityId sourceDestId; - headerSerializer.getSourceId(sourceDestId); - REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE); - REQUIRE(sourceDestId.getValue() == 0); - headerSerializer.getDestId(sourceDestId); - REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE); - REQUIRE(sourceDestId.getValue() == 1); - - result = headerSerializer.serialize(&serTarget, &serSize, serBuf.size(), - SerializeIF::Endianness::BIG); - REQUIRE(result == retval::CATCH_OK); - REQUIRE(serSize == 7); - // Only version bits are set - REQUIRE(serBuf[0] == 0b00100000); - // PDU data field length is 0 - REQUIRE(serBuf[1] == 0); - REQUIRE(serBuf[2] == 0); - // Entity and Transaction Sequence number are 1 byte large - REQUIRE(serBuf[3] == 0b00010001); - // Source ID - REQUIRE(serBuf[4] == 0); - // Transaction Seq Number - REQUIRE(serBuf[5] == 2); - // Dest ID - REQUIRE(serBuf[6] == 1); - - for (uint8_t idx = 0; idx < 7; idx++) { - ReturnValue_t result = - headerSerializer.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::BIG); - REQUIRE(result == static_cast(SerializeIF::BUFFER_TOO_SHORT)); - } - - // Set PDU data field len - headerSerializer.setPduDataFieldLen(0x0ff0); - REQUIRE(headerSerializer.getPduDataFieldLen() == 0x0ff0); - REQUIRE(headerSerializer.getSerializedSize() == 7); - REQUIRE(headerSerializer.getWholePduSize() == 7 + 0x0ff0); - serTarget = serBuf.data(); - serSize = 0; - result = headerSerializer.serialize(&serTarget, &serSize, serBuf.size(), - SerializeIF::Endianness::BIG); - REQUIRE(serBuf[1] == 0x0f); - REQUIRE(serBuf[2] == 0xf0); - - pduConf.crcFlag = true; - pduConf.largeFile = true; - pduConf.direction = cfdp::Direction::TOWARDS_SENDER; - pduConf.mode = cfdp::TransmissionModes::UNACKNOWLEDGED; - headerSerializer.setSegmentationControl( - cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION); - headerSerializer.setPduType(cfdp::PduType::FILE_DATA); - headerSerializer.setSegmentMetadataFlag(cfdp::SegmentMetadataFlag::PRESENT); - serTarget = serBuf.data(); - serSize = 0; - result = headerSerializer.serialize(&serTarget, &serSize, serBuf.size(), - SerializeIF::Endianness::BIG); - - // Everything except version bit flipped to one now - REQUIRE(serBuf[0] == 0x3f); - REQUIRE(serBuf[3] == 0x99); - pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff); - pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00); - pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff); - REQUIRE(pduConf.sourceId.getSerializedSize() == 4); - REQUIRE(headerSerializer.getSerializedSize() == 14); - serTarget = serBuf.data(); - serSize = 0; - result = headerSerializer.serialize(&serTarget, &serSize, serBuf.size(), - SerializeIF::Endianness::BIG); - - for (uint8_t idx = 0; idx < 14; idx++) { - ReturnValue_t result = - headerSerializer.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::BIG); - REQUIRE(result == static_cast(SerializeIF::BUFFER_TOO_SHORT)); - } - REQUIRE(headerSerializer.getCrcFlag() == true); - REQUIRE(headerSerializer.getDirection() == cfdp::Direction::TOWARDS_SENDER); - REQUIRE(headerSerializer.getLargeFileFlag() == true); - REQUIRE(headerSerializer.getLenEntityIds() == 4); - REQUIRE(headerSerializer.getLenSeqNum() == 2); - REQUIRE(headerSerializer.getPduType() == cfdp::PduType::FILE_DATA); - REQUIRE(headerSerializer.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT); - REQUIRE(headerSerializer.getTransmissionMode() == cfdp::TransmissionModes::UNACKNOWLEDGED); - REQUIRE(headerSerializer.getSegmentationControl() == true); - // Last three bits are 2 now (length of seq number) and bit 1 to bit 3 is 4 (len entity IDs) - REQUIRE(serBuf[3] == 0b11001010); - uint32_t entityId = 0; - size_t deSerSize = 0; - SerializeAdapter::deSerialize(&entityId, serBuf.data() + 4, &deSerSize, - SerializeIF::Endianness::NETWORK); - REQUIRE(deSerSize == 4); - REQUIRE(entityId == 0xff00ff00); - uint16_t seqNum = 0; - SerializeAdapter::deSerialize(&seqNum, serBuf.data() + 8, &deSerSize, - SerializeIF::Endianness::NETWORK); - REQUIRE(deSerSize == 2); - REQUIRE(seqNum == 0x0fff); - SerializeAdapter::deSerialize(&entityId, serBuf.data() + 10, &deSerSize, - SerializeIF::Endianness::NETWORK); - REQUIRE(deSerSize == 4); - REQUIRE(entityId == 0x00ff00ff); - - result = pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 0xfff); - REQUIRE(result == retval::CATCH_FAILED); - result = pduConf.sourceId.setValue(cfdp::WidthInBytes::TWO_BYTES, 0xfffff); - REQUIRE(result == retval::CATCH_FAILED); - result = pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xfffffffff); - REQUIRE(result == retval::CATCH_FAILED); - uint8_t oneByteSourceId = 32; - serTarget = &oneByteSourceId; - size_t deserLen = 1; - pduConf.sourceId.deSerialize(cfdp::WidthInBytes::ONE_BYTE, - const_cast(&serTarget), &deserLen, - SerializeIF::Endianness::MACHINE); - REQUIRE(pduConf.sourceId.getValue() == 32); - - uint16_t twoByteSourceId = 0xf0f0; - serTarget = reinterpret_cast(&twoByteSourceId); - deserLen = 2; - pduConf.sourceId.deSerialize(cfdp::WidthInBytes::TWO_BYTES, - const_cast(&serTarget), &deserLen, - SerializeIF::Endianness::MACHINE); - REQUIRE(pduConf.sourceId.getValue() == 0xf0f0); - - uint32_t fourByteSourceId = 0xf0f0f0f0; - serTarget = reinterpret_cast(&fourByteSourceId); - deserLen = 4; - pduConf.sourceId.deSerialize(cfdp::WidthInBytes::FOUR_BYTES, - const_cast(&serTarget), &deserLen, - SerializeIF::Endianness::MACHINE); - REQUIRE(pduConf.sourceId.getValue() == 0xf0f0f0f0); - - pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 1); - serTarget = serBuf.data(); - serSize = 1; - result = pduConf.sourceId.serialize(&serTarget, &serSize, 1, SerializeIF::Endianness::MACHINE); - REQUIRE(result == static_cast(SerializeIF::BUFFER_TOO_SHORT)); - } - - SECTION("Header Deserialization") { - // We unittested the serializer before, so we can use it now to generate valid raw CFDP - // data - auto headerSerializer = HeaderSerializer(pduConf, cfdp::PduType::FILE_DIRECTIVE, 0); - ReturnValue_t result = headerSerializer.serialize(&serTarget, &serSize, serBuf.size(), - SerializeIF::Endianness::BIG); - REQUIRE(result == retval::CATCH_OK); - REQUIRE(serBuf[1] == 0); - REQUIRE(serBuf[2] == 0); - // Entity and Transaction Sequence number are 1 byte large - REQUIRE(serBuf[3] == 0b00010001); - REQUIRE(serSize == 7); - // Deser call not strictly necessary - auto headerDeser = HeaderDeserializer(serBuf.data(), serBuf.size()); - - ReturnValue_t serResult = headerDeser.parseData(); - REQUIRE(serResult == retval::CATCH_OK); - REQUIRE(headerDeser.getPduDataFieldLen() == 0); - REQUIRE(headerDeser.getHeaderSize() == 7); - REQUIRE(headerDeser.getWholePduSize() == 7); - REQUIRE(headerDeser.getCrcFlag() == false); - REQUIRE(headerDeser.getDirection() == cfdp::Direction::TOWARDS_RECEIVER); - REQUIRE(headerDeser.getLargeFileFlag() == false); - REQUIRE(headerDeser.getLenEntityIds() == 1); - REQUIRE(headerDeser.getLenSeqNum() == 1); - REQUIRE(headerDeser.getPduType() == cfdp::PduType::FILE_DIRECTIVE); - REQUIRE(headerDeser.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::NOT_PRESENT); - REQUIRE(headerDeser.getSegmentationControl() == false); - REQUIRE(headerDeser.getTransmissionMode() == cfdp::TransmissionModes::ACKNOWLEDGED); - - pduConf.crcFlag = true; - pduConf.largeFile = true; - pduConf.direction = cfdp::Direction::TOWARDS_SENDER; - pduConf.mode = cfdp::TransmissionModes::UNACKNOWLEDGED; - headerSerializer.setSegmentationControl( - cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION); - headerSerializer.setPduType(cfdp::PduType::FILE_DATA); - headerSerializer.setSegmentMetadataFlag(cfdp::SegmentMetadataFlag::PRESENT); - result = pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff); - REQUIRE(result == retval::CATCH_OK); - result = pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00); - REQUIRE(result == retval::CATCH_OK); - result = pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff); - REQUIRE(result == retval::CATCH_OK); - serTarget = serBuf.data(); - serSize = 0; - result = headerSerializer.serialize(&serTarget, &serSize, serBuf.size(), - SerializeIF::Endianness::BIG); - headerDeser = HeaderDeserializer(serBuf.data(), serBuf.size()); - - result = headerDeser.parseData(); - REQUIRE(result == retval::CATCH_OK); - // Everything except version bit flipped to one now - REQUIRE(serBuf[0] == 0x3f); - REQUIRE(serBuf[3] == 0b11001010); - REQUIRE(headerDeser.getWholePduSize() == 14); - - REQUIRE(headerDeser.getCrcFlag() == true); - REQUIRE(headerDeser.getDirection() == cfdp::Direction::TOWARDS_SENDER); - REQUIRE(headerDeser.getLargeFileFlag() == true); - REQUIRE(headerDeser.getLenEntityIds() == 4); - REQUIRE(headerDeser.getLenSeqNum() == 2); - REQUIRE(headerDeser.getPduType() == cfdp::PduType::FILE_DATA); - REQUIRE(headerDeser.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT); - REQUIRE(headerDeser.getSegmentationControl() == true); - REQUIRE(headerDeser.getTransmissionMode() == cfdp::TransmissionModes::UNACKNOWLEDGED); - - cfdp::TransactionSeqNum seqNumLocal; - headerDeser.getTransactionSeqNum(seqNumLocal); - REQUIRE(seqNumLocal.getWidth() == cfdp::WidthInBytes::TWO_BYTES); - REQUIRE(seqNumLocal.getValue() == 0x0fff); - cfdp::EntityId sourceDestId; - headerDeser.getSourceId(sourceDestId); - REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::FOUR_BYTES); - REQUIRE(sourceDestId.getValue() == 0xff00ff00); - headerDeser.getDestId(sourceDestId); - REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::FOUR_BYTES); - REQUIRE(sourceDestId.getValue() == 0x00ff00ff); - - size_t deSerSize = headerDeser.getWholePduSize(); - serTarget = serBuf.data(); - const uint8_t** serTargetConst = const_cast(&serTarget); - result = headerDeser.parseData(); - REQUIRE(result == retval::CATCH_OK); - - headerDeser.setData(nullptr, -1); - REQUIRE(headerDeser.getHeaderSize() == 0); - headerDeser.setData(serBuf.data(), serBuf.size()); - - serTarget = serBuf.data(); - serSize = 0; - pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 22); - pduConf.destId.setValue(cfdp::WidthInBytes::ONE_BYTE, 48); - result = headerSerializer.serialize(&serTarget, &serSize, serBuf.size(), - SerializeIF::Endianness::BIG); - REQUIRE(result == retval::CATCH_OK); - REQUIRE(headerDeser.getWholePduSize() == 8); - headerDeser.setData(serBuf.data(), serBuf.size()); - - headerDeser.getSourceId(sourceDestId); - REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE); - REQUIRE(sourceDestId.getValue() == 22); - } - - SECTION("File Directive") { - auto fdSer = FileDirectiveSerializer(pduConf, FileDirectives::ACK, 4); - REQUIRE(fdSer.getSerializedSize() == 8); - serTarget = serBuf.data(); - serSize = 0; - result = fdSer.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - // Only version bits are set - REQUIRE(serBuf[0] == 0b00100000); - // PDU data field length is 5 (4 + Directive code octet) - REQUIRE(serBuf[1] == 0); - REQUIRE(serBuf[2] == 5); - // Entity and Transaction Sequence number are 1 byte large - REQUIRE(serBuf[3] == 0b00010001); - // Source ID - REQUIRE(serBuf[4] == 0); - // Transaction Seq Number - REQUIRE(serBuf[5] == 2); - // Dest ID - REQUIRE(serBuf[6] == 1); - REQUIRE(serBuf[7] == FileDirectives::ACK); - - serTarget = serBuf.data(); - size_t deserSize = 20; - serSize = 0; - REQUIRE(fdSer.deSerialize(&deserTarget, &deserSize, SerializeIF::Endianness::NETWORK) == - HasReturnvaluesIF::RETURN_FAILED); - REQUIRE(fdSer.serialize(nullptr, nullptr, 85, SerializeIF::Endianness::NETWORK) == - HasReturnvaluesIF::RETURN_FAILED); - for (uint8_t idx = 0; idx < 8; idx++) { - serTarget = serBuf.data(); - serSize = 0; - REQUIRE(fdSer.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::NETWORK) == - SerializeIF::BUFFER_TOO_SHORT); - } - - deserTarget = serBuf.data(); - deserSize = 0; - auto fdDeser = FileDirectiveDeserializer(deserTarget, serBuf.size()); - REQUIRE(fdDeser.getEndianness() == SerializeIF::Endianness::NETWORK); - fdDeser.setEndianness(SerializeIF::Endianness::MACHINE); - REQUIRE(fdDeser.getEndianness() == SerializeIF::Endianness::MACHINE); - fdDeser.setEndianness(SerializeIF::Endianness::NETWORK); - REQUIRE(fdDeser.parseData() == HasReturnvaluesIF::RETURN_OK); - REQUIRE(fdDeser.getFileDirective() == FileDirectives::ACK); - REQUIRE(fdDeser.getPduDataFieldLen() == 5); - REQUIRE(fdDeser.getHeaderSize() == 8); - REQUIRE(fdDeser.getPduType() == cfdp::PduType::FILE_DIRECTIVE); - - serBuf[7] = 0xff; - // Invalid file directive - REQUIRE(fdDeser.parseData() == cfdp::INVALID_DIRECTIVE_FIELDS); - } - - SECTION("FileSize") { - std::array fssBuf = {}; - uint8_t* buffer = fssBuf.data(); - size_t size = 0; - cfdp::FileSize fss; - REQUIRE(fss.getSize() == 0); - fss.setFileSize(0x20, false); - ReturnValue_t result = - fss.serialize(&buffer, &size, fssBuf.size(), SerializeIF::Endianness::MACHINE); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - uint32_t fileSize = 0; - result = SerializeAdapter::deSerialize(&fileSize, fssBuf.data(), nullptr, - SerializeIF::Endianness::MACHINE); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(fileSize == 0x20); - } -} diff --git a/tests/src/fsfw_tests/unit/cfdp/testTlvsLvs.cpp b/tests/src/fsfw_tests/unit/cfdp/testTlvsLvs.cpp deleted file mode 100644 index c251fd15..00000000 --- a/tests/src/fsfw_tests/unit/cfdp/testTlvsLvs.cpp +++ /dev/null @@ -1,330 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "fsfw/cfdp/pdu/PduConfig.h" -#include "fsfw/cfdp/tlv/Lv.h" -#include "fsfw/cfdp/tlv/Tlv.h" -#include "fsfw/globalfunctions/arrayprinter.h" - -TEST_CASE("CFDP TLV LV", "[CfdpTlvLv]") { - using namespace cfdp; - int result = HasReturnvaluesIF::RETURN_OK; - std::array rawBuf; - uint8_t* serPtr = rawBuf.data(); - const uint8_t* deserPtr = rawBuf.data(); - size_t deserSize = 0; - cfdp::EntityId sourceId = EntityId(cfdp::WidthInBytes::TWO_BYTES, 0x0ff0); - - SECTION("TLV Serialization") { - std::array tlvRawBuf; - serPtr = tlvRawBuf.data(); - result = - sourceId.serialize(&serPtr, &deserSize, tlvRawBuf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(deserSize == 2); - auto tlv = Tlv(TlvTypes::ENTITY_ID, tlvRawBuf.data(), deserSize); - REQUIRE(tlv.getSerializedSize() == 4); - REQUIRE(tlv.getLengthField() == 2); - serPtr = rawBuf.data(); - deserSize = 0; - result = tlv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(deserSize == 4); - REQUIRE(rawBuf[0] == TlvTypes::ENTITY_ID); - REQUIRE(rawBuf[1] == 2); - uint16_t entityId = 0; - SerializeAdapter::deSerialize(&entityId, rawBuf.data() + 2, &deserSize, - SerializeIF::Endianness::NETWORK); - REQUIRE(entityId == 0x0ff0); - - // Set new value - sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 12); - serPtr = tlvRawBuf.data(); - deserSize = 0; - result = - sourceId.serialize(&serPtr, &deserSize, tlvRawBuf.size(), SerializeIF::Endianness::NETWORK); - tlv.setValue(tlvRawBuf.data(), cfdp::WidthInBytes::FOUR_BYTES); - serPtr = rawBuf.data(); - deserSize = 0; - result = tlv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(rawBuf[0] == TlvTypes::ENTITY_ID); - REQUIRE(rawBuf[1] == 4); - - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - - serPtr = rawBuf.data(); - deserSize = 0; - auto tlvInvalid = Tlv(cfdp::TlvTypes::INVALID_TLV, tlvRawBuf.data(), 0); - REQUIRE(tlvInvalid.serialize(&serPtr, &deserSize, rawBuf.size(), - SerializeIF::Endianness::NETWORK) != HasReturnvaluesIF::RETURN_OK); - tlvInvalid = Tlv(cfdp::TlvTypes::ENTITY_ID, nullptr, 3); - REQUIRE(tlvInvalid.serialize(&serPtr, &deserSize, rawBuf.size(), - SerializeIF::Endianness::NETWORK) != HasReturnvaluesIF::RETURN_OK); - REQUIRE(tlvInvalid.serialize(&serPtr, &deserSize, 0, SerializeIF::Endianness::NETWORK) != - HasReturnvaluesIF::RETURN_OK); - REQUIRE(tlvInvalid.getSerializedSize() == 0); - REQUIRE(tlvInvalid.serialize(nullptr, nullptr, 0, SerializeIF::Endianness::NETWORK) != - HasReturnvaluesIF::RETURN_OK); - - Tlv zeroLenField(TlvTypes::FAULT_HANDLER, nullptr, 0); - REQUIRE(zeroLenField.getSerializedSize() == 2); - serPtr = rawBuf.data(); - deserSize = 0; - REQUIRE(zeroLenField.serialize(&serPtr, &deserSize, rawBuf.size(), - SerializeIF::Endianness::NETWORK) == - HasReturnvaluesIF::RETURN_OK); - REQUIRE(rawBuf[0] == TlvTypes::FAULT_HANDLER); - REQUIRE(rawBuf[1] == 0); - } - - SECTION("TLV Deserialization") { - // Serialization was tested before, generate raw data now - std::array tlvRawBuf; - serPtr = tlvRawBuf.data(); - result = - sourceId.serialize(&serPtr, &deserSize, tlvRawBuf.size(), SerializeIF::Endianness::NETWORK); - auto tlvSerialization = Tlv(TlvTypes::ENTITY_ID, tlvRawBuf.data(), deserSize); - serPtr = rawBuf.data(); - deserSize = 0; - result = tlvSerialization.serialize(&serPtr, &deserSize, rawBuf.size(), - SerializeIF::Endianness::NETWORK); - Tlv tlv; - deserPtr = rawBuf.data(); - result = tlv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(tlv.getSerializedSize() == 4); - REQUIRE(tlv.getType() == TlvTypes::ENTITY_ID); - deserPtr = tlv.getValue(); - uint16_t entityId = 0; - deserSize = 0; - SerializeAdapter::deSerialize(&entityId, deserPtr, &deserSize, - SerializeIF::Endianness::NETWORK); - REQUIRE(entityId == 0x0ff0); - - REQUIRE(tlv.deSerialize(nullptr, nullptr, SerializeIF::Endianness::NETWORK) != - HasReturnvaluesIF::RETURN_OK); - deserPtr = rawBuf.data(); - deserSize = 0; - REQUIRE(tlv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK) == - SerializeIF::STREAM_TOO_SHORT); - // Set invalid TLV - rawBuf[0] = TlvTypes::INVALID_TLV; - deserSize = 4; - REQUIRE(tlv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK) != - HasReturnvaluesIF::RETURN_OK); - - Tlv zeroLenField(TlvTypes::FAULT_HANDLER, nullptr, 0); - serPtr = rawBuf.data(); - deserSize = 0; - REQUIRE(zeroLenField.serialize(&serPtr, &deserSize, rawBuf.size(), - SerializeIF::Endianness::NETWORK) == - HasReturnvaluesIF::RETURN_OK); - deserPtr = rawBuf.data(); - result = zeroLenField.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(zeroLenField.getSerializedSize() == 2); - REQUIRE(deserSize == 0); - } - - SECTION("LV Serialization") { - std::array lvRawBuf; - serPtr = lvRawBuf.data(); - result = - sourceId.serialize(&serPtr, &deserSize, lvRawBuf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(deserSize == 2); - auto lv = cfdp::Lv(lvRawBuf.data(), 2); - auto lvCopy = cfdp::Lv(lv); - REQUIRE(lv.getSerializedSize() == 3); - REQUIRE(lvCopy.getSerializedSize() == 3); - REQUIRE(lv.getValue(nullptr) == lvCopy.getValue(nullptr)); - serPtr = rawBuf.data(); - deserSize = 0; - result = lv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(deserSize == 3); - REQUIRE(rawBuf[0] == 2); - uint16_t sourceId = 0; - result = SerializeAdapter::deSerialize(&sourceId, rawBuf.data() + 1, &deserSize, - SerializeIF::Endianness::BIG); - REQUIRE(sourceId == 0x0ff0); - - auto lvEmpty = Lv(nullptr, 0); - REQUIRE(lvEmpty.getSerializedSize() == 1); - serPtr = rawBuf.data(); - deserSize = 0; - result = - lvEmpty.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(deserSize == 1); - } - - SECTION("LV Deserialization") { - std::array lvRawBuf; - serPtr = lvRawBuf.data(); - result = - sourceId.serialize(&serPtr, &deserSize, lvRawBuf.size(), SerializeIF::Endianness::NETWORK); - auto lv = cfdp::Lv(lvRawBuf.data(), 2); - serPtr = rawBuf.data(); - deserSize = 0; - result = lv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - - Lv uninitLv; - deserPtr = rawBuf.data(); - deserSize = 3; - result = uninitLv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::BIG); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(uninitLv.getSerializedSize() == 3); - const uint8_t* storedValue = uninitLv.getValue(nullptr); - uint16_t sourceId = 0; - result = SerializeAdapter::deSerialize(&sourceId, storedValue, &deserSize, - SerializeIF::Endianness::BIG); - REQUIRE(sourceId == 0x0ff0); - - auto lvEmpty = Lv(nullptr, 0); - REQUIRE(lvEmpty.getSerializedSize() == 1); - serPtr = rawBuf.data(); - deserSize = 0; - result = - lvEmpty.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(deserSize == 1); - deserPtr = rawBuf.data(); - result = uninitLv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::BIG); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(uninitLv.getSerializedSize() == 1); - - REQUIRE(uninitLv.deSerialize(nullptr, nullptr, SerializeIF::Endianness::BIG) == - HasReturnvaluesIF::RETURN_FAILED); - serPtr = rawBuf.data(); - deserSize = 0; - REQUIRE(uninitLv.serialize(&serPtr, &deserSize, 0, SerializeIF::Endianness::BIG) == - SerializeIF::BUFFER_TOO_SHORT); - REQUIRE(uninitLv.serialize(nullptr, nullptr, 12, SerializeIF::Endianness::BIG)); - deserSize = 0; - REQUIRE(uninitLv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::BIG) == - SerializeIF::STREAM_TOO_SHORT); - } - - SECTION("Filestore Response TLV") { - std::string name = "hello.txt"; - cfdp::Lv firstName(reinterpret_cast(name.data()), name.size()); - std::string name2 = "hello2.txt"; - cfdp::Lv secondName(reinterpret_cast(name2.data()), name2.size()); - std::string msg = "12345"; - cfdp::Lv fsMsg(reinterpret_cast(msg.data()), msg.size()); - FilestoreResponseTlv response(cfdp::FilestoreActionCode::APPEND_FILE, cfdp::FSR_SUCCESS, - firstName, &fsMsg); - response.setSecondFileName(&secondName); - REQUIRE(response.getLengthField() == 10 + 11 + 6 + 1); - REQUIRE(response.getSerializedSize() == response.getLengthField() + 2); - - cfdp::Tlv rawResponse; - std::array serBuf = {}; - result = response.convertToTlv(rawResponse, serBuf.data(), serBuf.size(), - SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(rawResponse.getType() == cfdp::TlvTypes::FILESTORE_RESPONSE); - cfdp::Lv emptyMsg; - cfdp::Lv emptySecondName; - FilestoreResponseTlv emptyTlv(firstName, &emptyMsg); - emptyTlv.setSecondFileName(&emptySecondName); - result = emptyTlv.deSerialize(rawResponse, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(emptyTlv.getActionCode() == cfdp::FilestoreActionCode::APPEND_FILE); - REQUIRE(emptyTlv.getStatusCode() == cfdp::FSR_SUCCESS); - size_t firstNameLen = 0; - const char* firstNamePtr = - reinterpret_cast(emptyTlv.getFirstFileName().getValue(&firstNameLen)); - auto helloString = std::string(firstNamePtr, firstNameLen); - REQUIRE(helloString == "hello.txt"); - } - - SECTION("Filestore Request TLV") { - std::string name = "hello.txt"; - cfdp::Lv firstName(reinterpret_cast(name.data()), name.size()); - std::string name2 = "hello2.txt"; - cfdp::Lv secondName(reinterpret_cast(name2.data()), name2.size()); - FilestoreRequestTlv request(cfdp::FilestoreActionCode::APPEND_FILE, firstName); - - // second name not set yet - REQUIRE(request.getLengthField() == 10 + 1); - REQUIRE(request.getSerializedSize() == request.getLengthField() + 2); - - std::array serBuf = {}; - uint8_t* ptr = serBuf.data(); - size_t sz = 0; - result = request.serialize(&ptr, &sz, serBuf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == cfdp::FILESTORE_REQUIRES_SECOND_FILE); - - ptr = serBuf.data(); - sz = 0; - request.setSecondFileName(&secondName); - size_t expectedSz = request.getLengthField(); - REQUIRE(expectedSz == 10 + 11 + 1); - REQUIRE(request.getSerializedSize() == expectedSz + 2); - result = request.serialize(&ptr, &sz, serBuf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(sz == expectedSz + 2); - - FilestoreRequestTlv emptyRequest(firstName); - emptyRequest.setSecondFileName(&secondName); - const uint8_t* constptr = serBuf.data(); - result = emptyRequest.deSerialize(&constptr, &sz, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - - cfdp::Tlv rawRequest; - ptr = serBuf.data(); - sz = 0; - result = request.convertToTlv(rawRequest, serBuf.data(), serBuf.size(), - SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(rawRequest.getType() == cfdp::TlvTypes::FILESTORE_REQUEST); - - emptyRequest.setActionCode(cfdp::FilestoreActionCode::DELETE_FILE); - result = emptyRequest.deSerialize(rawRequest, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(emptyRequest.getType() == cfdp::TlvTypes::FILESTORE_REQUEST); - REQUIRE(emptyRequest.getActionCode() == cfdp::FilestoreActionCode::APPEND_FILE); - } - - SECTION("Other") { - MessageToUserTlv emptyTlv; - uint8_t flowLabel = 1; - FlowLabelTlv flowLabelTlv(&flowLabel, 1); - - FaultHandlerOverrideTlv faultOverrideTlv(cfdp::ConditionCode::FILESTORE_REJECTION, - cfdp::FaultHandlerCode::NOTICE_OF_CANCELLATION); - size_t sz = 0; - ReturnValue_t result = - faultOverrideTlv.serialize(&serPtr, &sz, rawBuf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(faultOverrideTlv.getSerializedSize() == 3); - REQUIRE(sz == 3); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - - FaultHandlerOverrideTlv emptyOverrideTlv; - result = emptyOverrideTlv.deSerialize(&deserPtr, &sz, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - - EntityId entId(cfdp::WidthInBytes::TWO_BYTES, 0x42); - EntityId emptyId; - EntityIdTlv idTlv(emptyId); - serPtr = rawBuf.data(); - result = idTlv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK); - cfdp::Tlv rawTlv(cfdp::TlvTypes::ENTITY_ID, rawBuf.data() + 2, 2); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - deserPtr = rawBuf.data(); - result = idTlv.deSerialize(rawTlv, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - } -} diff --git a/tests/src/fsfw_tests/unit/container/CMakeLists.txt b/tests/src/fsfw_tests/unit/container/CMakeLists.txt deleted file mode 100644 index 5dae974c..00000000 --- a/tests/src/fsfw_tests/unit/container/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE - RingBufferTest.cpp - TestArrayList.cpp - TestDynamicFifo.cpp - TestFifo.cpp - TestFixedArrayList.cpp - TestFixedMap.cpp - TestFixedOrderedMultimap.cpp - TestPlacementFactory.cpp -) diff --git a/tests/src/fsfw_tests/unit/datapoollocal/CMakeLists.txt b/tests/src/fsfw_tests/unit/datapoollocal/CMakeLists.txt deleted file mode 100644 index bf465282..00000000 --- a/tests/src/fsfw_tests/unit/datapoollocal/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE - LocalPoolVariableTest.cpp - LocalPoolVectorTest.cpp - DataSetTest.cpp - LocalPoolManagerTest.cpp - LocalPoolOwnerBase.cpp -) diff --git a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp b/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp deleted file mode 100644 index f2a5c18a..00000000 --- a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp +++ /dev/null @@ -1,413 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "LocalPoolOwnerBase.h" -#include "fsfw_tests/unit/CatchDefinitions.h" - -TEST_CASE("LocalPoolManagerTest", "[LocManTest]") { - LocalPoolOwnerBase* poolOwner = - ObjectManager::instance()->get(objects::TEST_LOCAL_POOL_OWNER_BASE); - REQUIRE(poolOwner != nullptr); - REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); - REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() == retval::CATCH_OK); - - MessageQueueMockBase* poolOwnerMock = poolOwner->getMockQueueHandle(); - REQUIRE(poolOwnerMock != nullptr); - - // MessageQueueIF* hkCommander = QueueFactory::instance()->createMessageQueue(); - CommandMessage messageSent; - uint8_t messagesSent = 0; - - SECTION("BasicTest") { - { - /* For code coverage, should not crash */ - LocalDataPoolManager manager(nullptr, nullptr); - } - auto owner = poolOwner->poolManager.getOwner(); - REQUIRE(owner != nullptr); - CHECK(owner->getObjectId() == objects::TEST_LOCAL_POOL_OWNER_BASE); - - /* Subscribe for message generation on update. */ - REQUIRE(poolOwner->subscribeWrapperSetUpdate() == retval::CATCH_OK); - /* Subscribe for an update message. */ - poolOwner->dataset.setChanged(true); - /* Now the update message should be generated. */ - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent() == true); - - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == - static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); - - /* Should have been reset. */ - CHECK(poolOwner->dataset.hasChanged() == false); - /* Set changed again, result should be the same. */ - poolOwner->dataset.setChanged(true); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == - static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); - - /* Now subscribe for set update HK as well. */ - REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK); - poolOwner->dataset.setChanged(true); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 2); - /* first message sent should be the update notification, considering - the internal list is a vector checked in insertion order. */ - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == - static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); - - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == static_cast(HousekeepingMessage::HK_REPORT)); - /* Clear message to avoid memory leak, our mock won't do it for us (yet) */ - CommandMessageCleaner::clearCommandMessage(&messageSent); - } - - SECTION("SetSnapshotUpdateTest") { - /* Set the variables in the set to certain values. These are checked later. */ - { - PoolReadGuard readHelper(&poolOwner->dataset); - REQUIRE(readHelper.getReadResult() == retval::CATCH_OK); - poolOwner->dataset.localPoolVarUint8.value = 5; - poolOwner->dataset.localPoolVarFloat.value = -12.242; - poolOwner->dataset.localPoolUint16Vec.value[0] = 2; - poolOwner->dataset.localPoolUint16Vec.value[1] = 32; - poolOwner->dataset.localPoolUint16Vec.value[2] = 42932; - } - - /* Subscribe for snapshot generation on update. */ - REQUIRE(poolOwner->subscribeWrapperSetUpdateSnapshot() == retval::CATCH_OK); - poolOwner->dataset.setChanged(true); - - /* Store current time, we are going to check the (approximate) time equality later */ - timeval now; - Clock::getClock_timeval(&now); - - /* Trigger generation of snapshot */ - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - /* Check that snapshot was generated */ - CHECK(messageSent.getCommand() == static_cast(HousekeepingMessage::UPDATE_SNAPSHOT_SET)); - /* Now we deserialize the snapshot into a new dataset instance */ - CCSDSTime::CDS_short cdsShort; - LocalPoolTestDataSet newSet; - HousekeepingSnapshot snapshot(&cdsShort, &newSet); - store_address_t storeId; - HousekeepingMessage::getUpdateSnapshotSetCommand(&messageSent, &storeId); - ConstAccessorPair accessorPair = tglob::getIpcStoreHandle()->getData(storeId); - REQUIRE(accessorPair.first == retval::CATCH_OK); - const uint8_t* readOnlyPtr = accessorPair.second.data(); - size_t sizeToDeserialize = accessorPair.second.size(); - CHECK(newSet.localPoolVarFloat.value == 0); - CHECK(newSet.localPoolVarUint8 == 0); - CHECK(newSet.localPoolUint16Vec.value[0] == 0); - CHECK(newSet.localPoolUint16Vec.value[1] == 0); - CHECK(newSet.localPoolUint16Vec.value[2] == 0); - /* Fill the dataset and timestamp */ - REQUIRE(snapshot.deSerialize(&readOnlyPtr, &sizeToDeserialize, - SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); - /* Now we check that the snapshot is actually correct */ - CHECK(newSet.localPoolVarFloat.value == Catch::Approx(-12.242)); - CHECK(newSet.localPoolVarUint8 == 5); - CHECK(newSet.localPoolUint16Vec.value[0] == 2); - CHECK(newSet.localPoolUint16Vec.value[1] == 32); - CHECK(newSet.localPoolUint16Vec.value[2] == 42932); - - /* Now we check that both times are equal */ - timeval timeFromHK; - auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort); - CHECK(result == HasReturnvaluesIF::RETURN_OK); - timeval difference = timeFromHK - now; - CHECK(timevalOperations::toDouble(difference) < 1.0); - } - - SECTION("VariableSnapshotTest") { - /* Acquire subscription interface */ - ProvidesDataPoolSubscriptionIF* subscriptionIF = poolOwner->getSubscriptionInterface(); - REQUIRE(subscriptionIF != nullptr); - - /* Subscribe for variable snapshot */ - REQUIRE(poolOwner->subscribeWrapperVariableSnapshot(lpool::uint8VarId) == retval::CATCH_OK); - auto poolVar = - dynamic_cast*>(poolOwner->getPoolObjectHandle(lpool::uint8VarId)); - REQUIRE(poolVar != nullptr); - - { - PoolReadGuard rg(poolVar); - CHECK(rg.getReadResult() == retval::CATCH_OK); - poolVar->value = 25; - } - - poolVar->setChanged(true); - /* Store current time, we are going to check the (approximate) time equality later */ - CCSDSTime::CDS_short timeCdsNow; - timeval now; - Clock::getClock_timeval(&now); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - - /* Check update snapshot was sent. */ - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - - /* Should have been reset. */ - CHECK(poolVar->hasChanged() == false); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == - static_cast(HousekeepingMessage::UPDATE_SNAPSHOT_VARIABLE)); - /* Now we deserialize the snapshot into a new dataset instance */ - CCSDSTime::CDS_short cdsShort; - lp_var_t varCopy = lp_var_t(lpool::uint8VarGpid); - HousekeepingSnapshot snapshot(&cdsShort, &varCopy); - store_address_t storeId; - HousekeepingMessage::getUpdateSnapshotVariableCommand(&messageSent, &storeId); - ConstAccessorPair accessorPair = tglob::getIpcStoreHandle()->getData(storeId); - REQUIRE(accessorPair.first == retval::CATCH_OK); - const uint8_t* readOnlyPtr = accessorPair.second.data(); - size_t sizeToDeserialize = accessorPair.second.size(); - CHECK(varCopy.value == 0); - /* Fill the dataset and timestamp */ - REQUIRE(snapshot.deSerialize(&readOnlyPtr, &sizeToDeserialize, - SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); - CHECK(varCopy.value == 25); - - /* Now we check that both times are equal */ - timeval timeFromHK; - auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort); - CHECK(result == HasReturnvaluesIF::RETURN_OK); - timeval difference = timeFromHK - now; - CHECK(timevalOperations::toDouble(difference) < 1.0); - } - - SECTION("VariableNotificationTest") { - /* Acquire subscription interface */ - ProvidesDataPoolSubscriptionIF* subscriptionIF = poolOwner->getSubscriptionInterface(); - REQUIRE(subscriptionIF != nullptr); - - /* Subscribe for variable update */ - REQUIRE(poolOwner->subscribeWrapperVariableUpdate(lpool::uint8VarId) == retval::CATCH_OK); - lp_var_t* poolVar = - dynamic_cast*>(poolOwner->getPoolObjectHandle(lpool::uint8VarId)); - REQUIRE(poolVar != nullptr); - poolVar->setChanged(true); - REQUIRE(poolVar->hasChanged() == true); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - - /* Check update notification was sent. */ - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - /* Should have been reset. */ - CHECK(poolVar->hasChanged() == false); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == - static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE)); - /* Now subscribe for the dataset update (HK and update) again with subscription interface */ - REQUIRE(subscriptionIF->subscribeForSetUpdateMessage(lpool::testSetId, objects::NO_OBJECT, - objects::HK_RECEIVER_MOCK, - false) == retval::CATCH_OK); - REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK); - - poolOwner->dataset.setChanged(true); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - /* Now two messages should be sent. */ - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 2); - poolOwnerMock->clearMessages(true); - - poolOwner->dataset.setChanged(true); - poolVar->setChanged(true); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - /* Now three messages should be sent. */ - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 3); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == - static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE)); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == - static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == static_cast(HousekeepingMessage::HK_REPORT)); - CommandMessageCleaner::clearCommandMessage(&messageSent); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == static_cast(MessageQueueIF::EMPTY)); - } - - SECTION("PeriodicHKAndMessaging") { - /* Now we subcribe for a HK periodic generation. Even when it's difficult to simulate - the temporal behaviour correctly the HK manager should generate a HK packet - immediately and the periodic helper depends on HK op function calls anyway instead of - using the clock, so we could also just call performHkOperation multiple times */ - REQUIRE(poolOwner->subscribePeriodicHk(true) == retval::CATCH_OK); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - /* Now HK packet should be sent as message immediately. */ - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - LocalPoolDataSetBase* setHandle = poolOwner->getDataSetHandle(lpool::testSid); - REQUIRE(setHandle != nullptr); - CHECK(poolOwner->poolManager.generateHousekeepingPacket(lpool::testSid, setHandle, false) == - retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - CHECK(setHandle->getReportingEnabled() == true); - CommandMessage hkCmd; - HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - CHECK(setHandle->getReportingEnabled() == false); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, true, false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - CHECK(setHandle->getReportingEnabled() == true); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - CHECK(setHandle->getReportingEnabled() == false); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4, - false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - /* For non-diagnostics and a specified minimum frequency of 0.2 seconds, the - resulting collection interval should be 1.0 second */ - CHECK(poolOwner->dataset.getCollectionInterval() == 1.0); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - /* Now HK packet should be sent as message. */ - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setUpdateNotificationSetCommand(&hkCmd, lpool::testSid); - sid_t sidToCheck; - store_address_t storeId; - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - CHECK(poolOwner->changedDataSetCallbackWasCalled(sidToCheck, storeId) == true); - CHECK(sidToCheck == lpool::testSid); - - /* Now we test the handling is the dataset is set to diagnostic */ - poolOwner->dataset.setDiagnostic(true); - - HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == - static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); - /* We still expect a failure message being sent */ - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4, - false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == - static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == - static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, true); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4, - true); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, true, true); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, true); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == - static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, true); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setUpdateNotificationVariableCommand(&hkCmd, lpool::uint8VarGpid); - gp_id_t gpidToCheck; - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - CHECK(poolOwner->changedVariableCallbackWasCalled(gpidToCheck, storeId) == true); - CHECK(gpidToCheck == lpool::uint8VarGpid); - - HousekeepingMessage::setUpdateSnapshotSetCommand(&hkCmd, lpool::testSid, - storeId::INVALID_STORE_ADDRESS); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - CHECK(poolOwner->changedDataSetCallbackWasCalled(sidToCheck, storeId) == true); - CHECK(sidToCheck == lpool::testSid); - - HousekeepingMessage::setUpdateSnapshotVariableCommand(&hkCmd, lpool::uint8VarGpid, - storeId::INVALID_STORE_ADDRESS); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - CHECK(poolOwner->changedVariableCallbackWasCalled(gpidToCheck, storeId) == true); - CHECK(gpidToCheck == lpool::uint8VarGpid); - - poolOwner->poolManager.printPoolEntry(lpool::uint8VarId); - } - - /* we need to reset the subscription list because the pool owner - is a global object. */ - CHECK(poolOwner->reset() == retval::CATCH_OK); - poolOwnerMock->clearMessages(true); -} diff --git a/tests/src/fsfw_tests/unit/globalfunctions/CMakeLists.txt b/tests/src/fsfw_tests/unit/globalfunctions/CMakeLists.txt deleted file mode 100644 index 348b99fc..00000000 --- a/tests/src/fsfw_tests/unit/globalfunctions/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE - testDleEncoder.cpp - testOpDivider.cpp - testBitutil.cpp - testCRC.cpp - testTimevalOperations.cpp -) diff --git a/tests/src/fsfw_tests/unit/globalfunctions/testTimevalOperations.cpp b/tests/src/fsfw_tests/unit/globalfunctions/testTimevalOperations.cpp deleted file mode 100644 index 347d2204..00000000 --- a/tests/src/fsfw_tests/unit/globalfunctions/testTimevalOperations.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#include - -#include -#include - -#include "fsfw_tests/unit/CatchDefinitions.h" - -TEST_CASE("TimevalTest", "[timevalOperations]") { - SECTION("Comparison") { - timeval t1; - t1.tv_sec = 1648227422; - t1.tv_usec = 123456; - timeval t2; - t2.tv_sec = 1648227422; - t2.tv_usec = 123456; - REQUIRE(t1 == t2); - REQUIRE(t2 == t1); - REQUIRE_FALSE(t1 != t2); - REQUIRE_FALSE(t2 != t1); - REQUIRE(t1 <= t2); - REQUIRE(t2 <= t1); - REQUIRE(t1 >= t2); - REQUIRE(t2 >= t1); - REQUIRE_FALSE(t1 < t2); - REQUIRE_FALSE(t2 < t1); - REQUIRE_FALSE(t1 > t2); - REQUIRE_FALSE(t2 > t1); - - timeval t3; - t3.tv_sec = 1648227422; - t3.tv_usec = 123457; - REQUIRE_FALSE(t1 == t3); - REQUIRE(t1 != t3); - REQUIRE(t1 <= t3); - REQUIRE_FALSE(t3 <= t1); - REQUIRE_FALSE(t1 >= t3); - REQUIRE(t3 >= t1); - REQUIRE(t1 < t3); - REQUIRE_FALSE(t3 < t1); - REQUIRE_FALSE(t1 > t3); - REQUIRE(t3 > t1); - - timeval t4; - t4.tv_sec = 1648227423; - t4.tv_usec = 123456; - REQUIRE_FALSE(t1 == t4); - REQUIRE(t1 != t4); - REQUIRE(t1 <= t4); - REQUIRE_FALSE(t4 <= t1); - REQUIRE_FALSE(t1 >= t4); - REQUIRE(t4 >= t1); - REQUIRE(t1 < t4); - REQUIRE_FALSE(t4 < t1); - REQUIRE_FALSE(t1 > t4); - REQUIRE(t4 > t1); - } - SECTION("Operators") { - timeval t1; - t1.tv_sec = 1648227422; - t1.tv_usec = 123456; - timeval t2; - t2.tv_sec = 1648227422; - t2.tv_usec = 123456; - timeval t3 = t1 - t2; - REQUIRE(t3.tv_sec == 0); - REQUIRE(t3.tv_usec == 0); - timeval t4 = t1 - t3; - REQUIRE(t4.tv_sec == 1648227422); - REQUIRE(t4.tv_usec == 123456); - timeval t5 = t3 - t1; - REQUIRE(t5.tv_sec == -1648227422); - REQUIRE(t5.tv_usec == -123456); - - timeval t6; - t6.tv_sec = 1648227400; - t6.tv_usec = 999999; - - timeval t7 = t6 + t1; - REQUIRE(t7.tv_sec == (1648227422ull + 1648227400ull + 1ull)); - REQUIRE(t7.tv_usec == 123455); - - timeval t8 = t1 - t6; - REQUIRE(t8.tv_sec == 1648227422 - 1648227400 - 1); - REQUIRE(t8.tv_usec == 123457); - - double scalar = 2; - timeval t9 = t1 * scalar; - REQUIRE(t9.tv_sec == 3296454844); - REQUIRE(t9.tv_usec == 246912); - timeval t10 = scalar * t1; - REQUIRE(t10.tv_sec == 3296454844); - REQUIRE(t10.tv_usec == 246912); - timeval t11 = t6 * scalar; - REQUIRE(t11.tv_sec == (3296454800 + 1)); - REQUIRE(t11.tv_usec == 999998); - - timeval t12 = t1 / scalar; - REQUIRE(t12.tv_sec == 824113711); - REQUIRE(t12.tv_usec == 61728); - - timeval t13 = t6 / scalar; - REQUIRE(t13.tv_sec == 824113700); - // Rounding issue - REQUIRE(t13.tv_usec == 499999); - - double scalar2 = t9 / t1; - REQUIRE(scalar2 == Catch::Approx(2.0)); - double scalar3 = t1 / t6; - REQUIRE(scalar3 == Catch::Approx(1.000000013)); - double scalar4 = t3 / t1; - REQUIRE(scalar4 == Catch::Approx(0)); - double scalar5 = t12 / t1; - REQUIRE(scalar5 == Catch::Approx(0.5)); - } - - SECTION("timevalOperations::toTimeval") { - double seconds = 1648227422.123456; - timeval t1 = timevalOperations::toTimeval(seconds); - REQUIRE(t1.tv_sec == 1648227422); - // Allow 1 usec rounding tolerance - REQUIRE(t1.tv_usec >= 123455); - REQUIRE(t1.tv_usec <= 123457); - } -} \ No newline at end of file diff --git a/tests/src/fsfw_tests/unit/hal/CMakeLists.txt b/tests/src/fsfw_tests/unit/hal/CMakeLists.txt deleted file mode 100644 index ee14a3aa..00000000 --- a/tests/src/fsfw_tests/unit/hal/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE - testCommandExecutor.cpp -) diff --git a/tests/src/fsfw_tests/unit/internalerror/CMakeLists.txt b/tests/src/fsfw_tests/unit/internalerror/CMakeLists.txt deleted file mode 100644 index d49ce006..00000000 --- a/tests/src/fsfw_tests/unit/internalerror/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE - TestInternalErrorReporter.cpp -) diff --git a/tests/src/fsfw_tests/unit/mocks/HkReceiverMock.h b/tests/src/fsfw_tests/unit/mocks/HkReceiverMock.h deleted file mode 100644 index 8d4b4983..00000000 --- a/tests/src/fsfw_tests/unit/mocks/HkReceiverMock.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef FSFW_UNITTEST_TESTS_MOCKS_HKRECEIVERMOCK_H_ -#define FSFW_UNITTEST_TESTS_MOCKS_HKRECEIVERMOCK_H_ - -#include -#include - -class HkReceiverMock : public SystemObject, public AcceptsHkPacketsIF { - public: - HkReceiverMock(object_id_t objectId) : SystemObject(objectId) {} - - MessageQueueId_t getHkQueue() const { return MessageQueueIF::NO_QUEUE; } -}; - -#endif /* FSFW_UNITTEST_TESTS_MOCKS_HKRECEIVERMOCK_H_ */ diff --git a/tests/src/fsfw_tests/unit/mocks/MessageQueueMockBase.h b/tests/src/fsfw_tests/unit/mocks/MessageQueueMockBase.h deleted file mode 100644 index c3d08a86..00000000 --- a/tests/src/fsfw_tests/unit/mocks/MessageQueueMockBase.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef FSFW_UNITTEST_TESTS_MOCKS_MESSAGEQUEUEMOCKBASE_H_ -#define FSFW_UNITTEST_TESTS_MOCKS_MESSAGEQUEUEMOCKBASE_H_ - -#include -#include - -#include "fsfw/ipc/MessageQueueBase.h" -#include "fsfw/ipc/CommandMessage.h" -#include "fsfw/ipc/MessageQueueIF.h" -#include "fsfw/ipc/MessageQueueMessage.h" -#include "fsfw_tests/unit/CatchDefinitions.h" - -class MessageQueueMockBase : public MessageQueueBase { - public: - MessageQueueMockBase() - : MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, nullptr) {} - - uint8_t messageSentCounter = 0; - bool messageSent = false; - - bool wasMessageSent(uint8_t* messageSentCounter = nullptr, bool resetCounter = true) { - bool tempMessageSent = messageSent; - messageSent = false; - if (messageSentCounter != nullptr) { - *messageSentCounter = this->messageSentCounter; - } - if (resetCounter) { - this->messageSentCounter = 0; - } - return tempMessageSent; - } - - /** - * Pop a message, clearing it in the process. - * @return - */ - ReturnValue_t popMessage() { - CommandMessage message; - message.clear(); - return receiveMessage(&message); - } - - virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override { - if (messagesSentQueue.empty()) { - return MessageQueueIF::EMPTY; - } - this->last = message->getSender(); - std::memcpy(message->getBuffer(), messagesSentQueue.front().getBuffer(), - message->getMessageSize()); - messagesSentQueue.pop(); - return HasReturnvaluesIF::RETURN_OK; - } - virtual ReturnValue_t flush(uint32_t* count) { return HasReturnvaluesIF::RETURN_OK; } - virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, - MessageQueueId_t sentFrom, - bool ignoreFault = false) override { - messageSent = true; - messageSentCounter++; - MessageQueueMessage& messageRef = *(dynamic_cast(message)); - messagesSentQueue.push(messageRef); - return HasReturnvaluesIF::RETURN_OK; - } - - virtual ReturnValue_t reply(MessageQueueMessageIF* message) override { - return sendMessageFrom(MessageQueueIF::NO_QUEUE, message, this->getId(), false); - } - - void clearMessages(bool clearCommandMessages = true) { - while (not messagesSentQueue.empty()) { - if (clearCommandMessages) { - CommandMessage message; - std::memcpy(message.getBuffer(), messagesSentQueue.front().getBuffer(), - message.getMessageSize()); - message.clear(); - } - messagesSentQueue.pop(); - } - } - - private: - std::queue messagesSentQueue; -}; - -#endif /* FSFW_UNITTEST_TESTS_MOCKS_MESSAGEQUEUEMOCKBASE_H_ */ diff --git a/tests/src/fsfw_tests/unit/mocks/PeriodicTaskIFMock.h b/tests/src/fsfw_tests/unit/mocks/PeriodicTaskIFMock.h deleted file mode 100644 index ebd9a2e7..00000000 --- a/tests/src/fsfw_tests/unit/mocks/PeriodicTaskIFMock.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef FSFW_UNITTEST_TESTS_MOCKS_PERIODICTASKMOCK_H_ -#define FSFW_UNITTEST_TESTS_MOCKS_PERIODICTASKMOCK_H_ - -#include -#include - -class PeriodicTaskMock : public PeriodicTaskIF { - public: - PeriodicTaskMock(uint32_t period = 5) : period(period) {} - /** - * @brief A virtual destructor as it is mandatory for interfaces. - */ - virtual ~PeriodicTaskMock() {} - /** - * @brief With the startTask method, a created task can be started - * for the first time. - */ - virtual ReturnValue_t startTask() override { return HasReturnvaluesIF::RETURN_OK; }; - - virtual ReturnValue_t addComponent(object_id_t object) override { - ExecutableObjectIF* executableObject = - ObjectManager::instance()->get(objects::INTERNAL_ERROR_REPORTER); - if (executableObject == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - executableObject->setTaskIF(this); - executableObject->initializeAfterTaskCreation(); - return HasReturnvaluesIF::RETURN_OK; - }; - - virtual ReturnValue_t sleepFor(uint32_t ms) override { return HasReturnvaluesIF::RETURN_OK; }; - - virtual uint32_t getPeriodMs() const override { return period; }; - uint32_t period; -}; - -#endif // FSFW_UNITTEST_TESTS_MOCKS_PERIODICTASKMOCK_H_ \ No newline at end of file diff --git a/tests/src/fsfw_tests/unit/osal/CMakeLists.txt b/tests/src/fsfw_tests/unit/osal/CMakeLists.txt deleted file mode 100644 index 030d363b..00000000 --- a/tests/src/fsfw_tests/unit/osal/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE - TestMessageQueue.cpp - TestSemaphore.cpp - TestClock.cpp -) diff --git a/tests/src/fsfw_tests/unit/osal/TestSemaphore.cpp b/tests/src/fsfw_tests/unit/osal/TestSemaphore.cpp deleted file mode 100644 index 6988af5b..00000000 --- a/tests/src/fsfw_tests/unit/osal/TestSemaphore.cpp +++ /dev/null @@ -1,46 +0,0 @@ - -#ifdef LINUX - -/* -#include -#include - -#include "catch.hpp" -#include "core/CatchDefinitions.h" - -TEST_CASE("Binary Semaphore Test" , "[BinSemaphore]") { - //perform set-up here - SemaphoreIF* binSemaph = SemaphoreFactory::instance()-> - createBinarySemaphore(); - REQUIRE(binSemaph != nullptr); - SECTION("Simple Test") { - // set-up is run for each section - REQUIRE(binSemaph->getSemaphoreCounter() == 1); - REQUIRE(binSemaph->release() == - static_cast(SemaphoreIF::SEMAPHORE_NOT_OWNED)); - REQUIRE(binSemaph->acquire(SemaphoreIF::POLLING) == - retval::CATCH_OK); - { - // not precise enough on linux.. should use clock instead.. - //Stopwatch stopwatch(false); - //REQUIRE(binSemaph->acquire(SemaphoreIF::TimeoutType::WAITING, 5) == - // SemaphoreIF::SEMAPHORE_TIMEOUT); - //dur_millis_t time = stopwatch.stop(); - //CHECK(time == 5); - } - REQUIRE(binSemaph->getSemaphoreCounter() == 0); - REQUIRE(binSemaph->release() == retval::CATCH_OK); - } - SemaphoreFactory::instance()->deleteSemaphore(binSemaph); - // perform tear-down here -} - - -TEST_CASE("Counting Semaphore Test" , "[CountingSemaph]") { - SECTION("Simple Test") { - - } -} -*/ - -#endif diff --git a/tests/src/fsfw_tests/unit/serialize/CMakeLists.txt b/tests/src/fsfw_tests/unit/serialize/CMakeLists.txt deleted file mode 100644 index 96c80f4a..00000000 --- a/tests/src/fsfw_tests/unit/serialize/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE - TestSerialBufferAdapter.cpp - TestSerialization.cpp - TestSerialLinkedPacket.cpp -) diff --git a/tests/src/fsfw_tests/unit/storagemanager/CMakeLists.txt b/tests/src/fsfw_tests/unit/storagemanager/CMakeLists.txt deleted file mode 100644 index 7b6280df..00000000 --- a/tests/src/fsfw_tests/unit/storagemanager/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE - TestNewAccessor.cpp - TestPool.cpp -) diff --git a/tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt b/tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt deleted file mode 100644 index f840e38b..00000000 --- a/tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE - ipc/MissionMessageTypes.cpp - pollingsequence/PollingSequenceFactory.cpp -) - -# Add include paths for the executable -target_include_directories(${FSFW_TEST_TGT} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} -) - -# If a special translation file for object IDs exists, compile it. -if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp") - target_sources(${FSFW_TEST_TGT} PRIVATE - objects/translateObjects.cpp - ) -endif() - -# If a special translation file for events exists, compile it. -if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp") - target_sources(${FSFW_TEST_TGT} PRIVATE - events/translateEvents.cpp - ) -endif() \ No newline at end of file diff --git a/tests/src/fsfw_tests/unit/timemanager/CMakeLists.txt b/tests/src/fsfw_tests/unit/timemanager/CMakeLists.txt deleted file mode 100644 index 4b1693a9..00000000 --- a/tests/src/fsfw_tests/unit/timemanager/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE - TestCountdown.cpp - TestCCSDSTime.cpp -) diff --git a/tests/src/fsfw_tests/unit/tmtcpacket/CMakeLists.txt b/tests/src/fsfw_tests/unit/tmtcpacket/CMakeLists.txt deleted file mode 100644 index 958bda40..00000000 --- a/tests/src/fsfw_tests/unit/tmtcpacket/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE - testCcsds.cpp -) diff --git a/tests/src/fsfw_tests/unit/tmtcpacket/PusTmTest.cpp b/tests/src/fsfw_tests/unit/tmtcpacket/PusTmTest.cpp deleted file mode 100644 index 8b137891..00000000 --- a/tests/src/fsfw_tests/unit/tmtcpacket/PusTmTest.cpp +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/src/fsfw_tests/unit/tmtcpacket/testCcsds.cpp b/tests/src/fsfw_tests/unit/tmtcpacket/testCcsds.cpp deleted file mode 100644 index d395449d..00000000 --- a/tests/src/fsfw_tests/unit/tmtcpacket/testCcsds.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include - -#include "fsfw/tmtcpacket/SpacePacket.h" - -TEST_CASE("CCSDS Test", "[ccsds]") { - REQUIRE(spacepacket::getTcSpacePacketIdFromApid(0x22) == 0x1822); - REQUIRE(spacepacket::getTmSpacePacketIdFromApid(0x22) == 0x0822); - - REQUIRE(spacepacket::getTcSpacePacketIdFromApid(0x7ff) == 0x1fff); - REQUIRE(spacepacket::getTmSpacePacketIdFromApid(0x7ff) == 0xfff); -} diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt new file mode 100644 index 00000000..ad26e392 --- /dev/null +++ b/unittests/CMakeLists.txt @@ -0,0 +1,28 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE CatchDefinitions.cpp CatchFactory.cpp + printChar.cpp testVersion.cpp) + +target_sources(${FSFW_TEST_TGT} PRIVATE CatchRunner.cpp CatchSetup.cpp) + +add_subdirectory(testcfg) +add_subdirectory(mocks) + +add_subdirectory(tcdistributor) +add_subdirectory(action) +add_subdirectory(power) +add_subdirectory(util) +add_subdirectory(container) +add_subdirectory(osal) +add_subdirectory(pus) +add_subdirectory(serialize) +add_subdirectory(datapoollocal) +add_subdirectory(storagemanager) +add_subdirectory(globalfunctions) +add_subdirectory(timemanager) +add_subdirectory(tmtcpacket) +add_subdirectory(cfdp) +add_subdirectory(hal) +add_subdirectory(internalerror) +add_subdirectory(devicehandler) +add_subdirectory(tmtcservices) + +target_include_directories(${FSFW_TEST_TGT} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tests/src/fsfw_tests/unit/CatchDefinitions.cpp b/unittests/CatchDefinitions.cpp similarity index 95% rename from tests/src/fsfw_tests/unit/CatchDefinitions.cpp rename to unittests/CatchDefinitions.cpp index 85e3aad0..3c76fd88 100644 --- a/tests/src/fsfw_tests/unit/CatchDefinitions.cpp +++ b/unittests/CatchDefinitions.cpp @@ -3,6 +3,8 @@ #include #include +#include "fsfw/FSFW.h" + StorageManagerIF* tglob::getIpcStoreHandle() { if (ObjectManager::instance() != nullptr) { return ObjectManager::instance()->get(objects::IPC_STORE); diff --git a/tests/src/fsfw_tests/unit/CatchDefinitions.h b/unittests/CatchDefinitions.h similarity index 59% rename from tests/src/fsfw_tests/unit/CatchDefinitions.h rename to unittests/CatchDefinitions.h index f0189602..a5949fed 100644 --- a/tests/src/fsfw_tests/unit/CatchDefinitions.h +++ b/unittests/CatchDefinitions.h @@ -2,13 +2,10 @@ #define FSFW_UNITTEST_CORE_CATCHDEFINITIONS_H_ #include -#include +#include #include -namespace retval { -static constexpr int CATCH_OK = static_cast(HasReturnvaluesIF::RETURN_OK); -static constexpr int CATCH_FAILED = static_cast(HasReturnvaluesIF::RETURN_FAILED); -} // namespace retval +#include "fsfw/FSFW.h" namespace tconst { static constexpr MessageQueueId_t testQueueId = 42; diff --git a/tests/src/fsfw_tests/unit/CatchFactory.cpp b/unittests/CatchFactory.cpp similarity index 69% rename from tests/src/fsfw_tests/unit/CatchFactory.cpp rename to unittests/CatchFactory.cpp index 01018dfa..98307496 100644 --- a/tests/src/fsfw_tests/unit/CatchFactory.cpp +++ b/unittests/CatchFactory.cpp @@ -7,11 +7,9 @@ #include #include #include -#include #include #include -#include "datapoollocal/LocalPoolOwnerBase.h" #include "mocks/HkReceiverMock.h" #include "tests/TestsConfig.h" @@ -32,18 +30,10 @@ */ void Factory::produceFrameworkObjects(void* args) { setStaticFrameworkObjectIds(); - new EventManager(objects::EVENT_MANAGER); + new EventManager(objects::EVENT_MANAGER, 80); new HealthTable(objects::HEALTH_TABLE); new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER); - new LocalPoolOwnerBase(objects::TEST_LOCAL_POOL_OWNER_BASE); - new HkReceiverMock(objects::HK_RECEIVER_MOCK); - - { - PoolManager::LocalPoolConfig poolCfg = {{100, 16}, {50, 32}, {25, 64}, {15, 128}, {5, 1024}}; - new PoolManager(objects::TC_STORE, poolCfg); - } - { PoolManager::LocalPoolConfig poolCfg = {{100, 16}, {50, 32}, {25, 64}, {15, 128}, {5, 1024}}; new PoolManager(objects::TM_STORE, poolCfg); @@ -55,23 +45,20 @@ void Factory::produceFrameworkObjects(void* args) { } } +// TODO: Our tests, and the code base in general should really not depend on some arbitrary function +// like this. Instead, this should be more like a general struct containing all important +// object IDs which are then explicitely passed in the object constructor void Factory::setStaticFrameworkObjectIds() { - PusServiceBase::packetSource = objects::NO_OBJECT; - PusServiceBase::packetDestination = objects::NO_OBJECT; + PusServiceBase::PACKET_DESTINATION = objects::NO_OBJECT; CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT; CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT; - VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION; - DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT; - DeviceHandlerBase::rawDataReceiverId = objects::PUS_SERVICE_2_DEVICE_ACCESS; - - LocalDataPoolManager::defaultHkDestination = objects::HK_RECEIVER_MOCK; + DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT; + LocalDataPoolManager::defaultHkDestination = objects::NO_OBJECT; DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT; - - TmPacketBase::timeStamperId = objects::NO_OBJECT; } #endif diff --git a/tests/src/fsfw_tests/unit/CatchFactory.h b/unittests/CatchFactory.h similarity index 100% rename from tests/src/fsfw_tests/unit/CatchFactory.h rename to unittests/CatchFactory.h diff --git a/tests/src/fsfw_tests/unit/CatchRunner.cpp b/unittests/CatchRunner.cpp similarity index 92% rename from tests/src/fsfw_tests/unit/CatchRunner.cpp rename to unittests/CatchRunner.cpp index 1377049c..9bdcb676 100644 --- a/tests/src/fsfw_tests/unit/CatchRunner.cpp +++ b/unittests/CatchRunner.cpp @@ -13,6 +13,7 @@ #include extern int customSetup(); +extern int customTeardown(); int main(int argc, char* argv[]) { customSetup(); @@ -21,5 +22,6 @@ int main(int argc, char* argv[]) { int result = Catch::Session().run(argc, argv); // global clean-up + customTeardown(); return result; } diff --git a/tests/src/fsfw_tests/unit/CatchRunner.h b/unittests/CatchRunner.h similarity index 100% rename from tests/src/fsfw_tests/unit/CatchRunner.h rename to unittests/CatchRunner.h diff --git a/tests/src/fsfw_tests/unit/CatchSetup.cpp b/unittests/CatchSetup.cpp similarity index 90% rename from tests/src/fsfw_tests/unit/CatchSetup.cpp rename to unittests/CatchSetup.cpp index 06f5190a..fc5bb3f5 100644 --- a/tests/src/fsfw_tests/unit/CatchSetup.cpp +++ b/unittests/CatchSetup.cpp @@ -1,5 +1,6 @@ #include "CatchDefinitions.h" #include "CatchFactory.h" +#include "fsfw/FSFW.h" #ifdef GCOV #include @@ -29,3 +30,8 @@ int customSetup() { objMan->initialize(); return 0; } + +int customTeardown() { + ObjectManager::clear(); + return 0; +} diff --git a/unittests/action/CMakeLists.txt b/unittests/action/CMakeLists.txt new file mode 100644 index 00000000..99941357 --- /dev/null +++ b/unittests/action/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE TestActionHelper.cpp) diff --git a/tests/src/fsfw_tests/unit/action/TestActionHelper.cpp b/unittests/action/TestActionHelper.cpp similarity index 81% rename from tests/src/fsfw_tests/unit/action/TestActionHelper.cpp rename to unittests/action/TestActionHelper.cpp index 923b7436..d99700d7 100644 --- a/tests/src/fsfw_tests/unit/action/TestActionHelper.cpp +++ b/unittests/action/TestActionHelper.cpp @@ -6,11 +6,12 @@ #include #include -#include "fsfw_tests/unit/mocks/MessageQueueMockBase.h" +#include "mocks/MessageQueueMock.h" -TEST_CASE("Action Helper", "[ActionHelper]") { +TEST_CASE("Action Helper", "[action]") { ActionHelperOwnerMockBase testDhMock; - MessageQueueMockBase testMqMock; + // TODO: Setting another number here breaks the test. Find out why + MessageQueueMock testMqMock(MessageQueueIF::NO_QUEUE); ActionHelper actionHelper = ActionHelper(&testDhMock, dynamic_cast(&testMqMock)); CommandMessage actionMessage; ActionId_t testActionId = 777; @@ -19,12 +20,12 @@ TEST_CASE("Action Helper", "[ActionHelper]") { StorageManagerIF* ipcStore = tglob::getIpcStoreHandle(); REQUIRE(ipcStore != nullptr); ipcStore->addData(¶mAddress, testParams.data(), 3); - REQUIRE(actionHelper.initialize() == retval::CATCH_OK); + REQUIRE(actionHelper.initialize() == returnvalue::OK); SECTION("Simple tests") { ActionMessage::setCommand(&actionMessage, testActionId, paramAddress); CHECK(not testDhMock.executeActionCalled); - REQUIRE(actionHelper.handleActionMessage(&actionMessage) == retval::CATCH_OK); + REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK); CHECK(testDhMock.executeActionCalled); // No message is sent if everything is alright. CHECK(not testMqMock.wasMessageSent()); @@ -57,8 +58,7 @@ TEST_CASE("Action Helper", "[ActionHelper]") { step += 1; CHECK(testMqMock.wasMessageSent()); CommandMessage testMessage; - REQUIRE(testMqMock.receiveMessage(&testMessage) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(testMqMock.getNextSentMessage(testMessage) == returnvalue::OK); REQUIRE(testMessage.getCommand() == static_cast(ActionMessage::STEP_FAILED)); REQUIRE(testMessage.getParameter() == static_cast(testActionId)); uint32_t parameter2 = ((uint32_t)step << 16) | (uint32_t)status; @@ -72,25 +72,23 @@ TEST_CASE("Action Helper", "[ActionHelper]") { actionHelper.finish(false, testMqMock.getId(), testActionId, status); CHECK(testMqMock.wasMessageSent()); CommandMessage testMessage; - REQUIRE(testMqMock.receiveMessage(&testMessage) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(testMqMock.getNextSentMessage(testMessage) == returnvalue::OK); REQUIRE(testMessage.getCommand() == static_cast(ActionMessage::COMPLETION_FAILED)); REQUIRE(ActionMessage::getActionId(&testMessage) == testActionId); REQUIRE(ActionMessage::getReturnCode(&testMessage) == static_cast(status)); } SECTION("Handle failed") { - store_address_t toLongParamAddress = StorageManagerIF::INVALID_ADDRESS; + store_address_t toLongParamAddress = store_address_t::invalid(); std::array toLongData = {5, 4, 3, 2, 1}; - REQUIRE(ipcStore->addData(&toLongParamAddress, toLongData.data(), 5) == retval::CATCH_OK); + REQUIRE(ipcStore->addData(&toLongParamAddress, toLongData.data(), 5) == returnvalue::OK); ActionMessage::setCommand(&actionMessage, testActionId, toLongParamAddress); CHECK(not testDhMock.executeActionCalled); - REQUIRE(actionHelper.handleActionMessage(&actionMessage) == retval::CATCH_OK); + REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK); REQUIRE(ipcStore->getData(toLongParamAddress).first == static_cast(StorageManagerIF::DATA_DOES_NOT_EXIST)); CommandMessage testMessage; - REQUIRE(testMqMock.receiveMessage(&testMessage) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(testMqMock.getNextSentMessage(testMessage) == returnvalue::OK); REQUIRE(testMessage.getCommand() == static_cast(ActionMessage::STEP_FAILED)); REQUIRE(ActionMessage::getReturnCode(&testMessage) == 0xAFFE); REQUIRE(ActionMessage::getStep(&testMessage) == 0); @@ -98,12 +96,11 @@ TEST_CASE("Action Helper", "[ActionHelper]") { } SECTION("Missing IPC Data") { - ActionMessage::setCommand(&actionMessage, testActionId, StorageManagerIF::INVALID_ADDRESS); + ActionMessage::setCommand(&actionMessage, testActionId, store_address_t::invalid()); CHECK(not testDhMock.executeActionCalled); - REQUIRE(actionHelper.handleActionMessage(&actionMessage) == retval::CATCH_OK); + REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK); CommandMessage testMessage; - REQUIRE(testMqMock.receiveMessage(&testMessage) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(testMqMock.getNextSentMessage(testMessage) == returnvalue::OK); REQUIRE(testMessage.getCommand() == static_cast(ActionMessage::STEP_FAILED)); REQUIRE(ActionMessage::getReturnCode(&testMessage) == static_cast(StorageManagerIF::ILLEGAL_STORAGE_ID)); diff --git a/tests/src/fsfw_tests/unit/action/TestActionHelper.h b/unittests/action/TestActionHelper.h similarity index 93% rename from tests/src/fsfw_tests/unit/action/TestActionHelper.h rename to unittests/action/TestActionHelper.h index 243f030a..bd88df80 100644 --- a/tests/src/fsfw_tests/unit/action/TestActionHelper.h +++ b/unittests/action/TestActionHelper.h @@ -6,7 +6,7 @@ #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" class ActionHelperOwnerMockBase : public HasActionsIF { public: @@ -26,7 +26,7 @@ class ActionHelperOwnerMockBase : public HasActionsIF { } this->size = size; memcpy(buffer, data, size); - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void clearBuffer() { diff --git a/unittests/cfdp/CMakeLists.txt b/unittests/cfdp/CMakeLists.txt new file mode 100644 index 00000000..1867a534 --- /dev/null +++ b/unittests/cfdp/CMakeLists.txt @@ -0,0 +1,5 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE testCfdp.cpp testOtherTlvs.cpp + testTlv.cpp testLvs.cpp) + +add_subdirectory(handler) +add_subdirectory(pdu) diff --git a/unittests/cfdp/handler/CMakeLists.txt b/unittests/cfdp/handler/CMakeLists.txt new file mode 100644 index 00000000..0993a398 --- /dev/null +++ b/unittests/cfdp/handler/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE testDistributor.cpp + testFaultHandler.cpp) diff --git a/unittests/cfdp/handler/testDistributor.cpp b/unittests/cfdp/handler/testDistributor.cpp new file mode 100644 index 00000000..8b6c46af --- /dev/null +++ b/unittests/cfdp/handler/testDistributor.cpp @@ -0,0 +1,99 @@ +#include + +#include "fsfw/cfdp/CfdpDistributor.h" +#include "fsfw/cfdp/pdu/MetadataPduCreator.h" +#include "fsfw/cfdp/tlv/StringLv.h" +#include "fsfw/storagemanager/LocalPool.h" +#include "fsfw/tcdistribution/definitions.h" +#include "mocks/AcceptsTcMock.h" +#include "mocks/MessageQueueMock.h" +#include "mocks/StorageManagerMock.h" + +TEST_CASE("CFDP Distributor", "[cfdp][distributor]") { + LocalPool::LocalPoolConfig cfg = {{5, 32}, {2, 64}}; + StorageManagerMock pool(objects::NO_OBJECT, cfg); + auto queue = MessageQueueMock(1); + CfdpDistribCfg distribCfg(1, pool, &queue); + auto distributor = CfdpDistributor(distribCfg); + auto obswEntityId = cfdp::EntityId(UnsignedByteField(2)); + auto groundEntityId = cfdp::EntityId(UnsignedByteField(1)); + MessageQueueId_t receiverQueueId = 3; + auto tcAcceptor = AcceptsTcMock("CFDP Receiver", 0, receiverQueueId); + + // Set up Metadata PDU for generate test data. + cfdp::FileSize fileSize(12); + const cfdp::EntityId& sourceId(groundEntityId); + const cfdp::EntityId& destId(obswEntityId); + cfdp::TransactionSeqNum seqNum(UnsignedByteField(12)); + auto pduConf = PduConfig(sourceId, destId, cfdp::TransmissionMode::UNACKNOWLEDGED, seqNum); + std::string sourceFileString = "hello.txt"; + cfdp::StringLv sourceFileName(sourceFileString); + std::string destFileString = "hello2.txt"; + cfdp::StringLv destFileName(destFileString); + MetadataInfo metadataInfo(false, cfdp::ChecksumType::CRC_32, fileSize, sourceFileName, + destFileName); + MetadataPduCreator creator(pduConf, metadataInfo); + uint8_t* dataPtr = nullptr; + + SECTION("State") { + CHECK(distributor.initialize() == returnvalue::OK); + CHECK(std::strcmp(distributor.getName(), "CFDP Distributor") == 0); + CHECK(distributor.getIdentifier() == 0); + CHECK(distributor.getRequestQueue() == queue.getId()); + } + + SECTION("Packet Forwarding") { + CHECK(distributor.initialize() == returnvalue::OK); + CHECK(distributor.registerTcDestination(obswEntityId, tcAcceptor) == returnvalue::OK); + size_t serLen = 0; + store_address_t storeId; + CHECK(pool.LocalPool::getFreeElement(&storeId, creator.getSerializedSize(), &dataPtr) == + returnvalue::OK); + REQUIRE(creator.SerializeIF::serializeBe(dataPtr, serLen, creator.getSerializedSize()) == + returnvalue::OK); + TmTcMessage msg(storeId); + queue.addReceivedMessage(msg); + CHECK(distributor.performOperation(0) == returnvalue::OK); + CHECK(queue.wasMessageSent()); + CHECK(queue.numberOfSentMessages() == 1); + // The packet is forwarded, with no need to delete the data + CHECK(pool.hasDataAtId(storeId)); + TmTcMessage sentMsg; + CHECK(queue.getNextSentMessage(receiverQueueId, sentMsg) == returnvalue::OK); + CHECK(sentMsg.getStorageId() == storeId); + } + + SECTION("No Destination found") { + CHECK(distributor.initialize() == returnvalue::OK); + size_t serLen = 0; + store_address_t storeId; + CHECK(pool.LocalPool::getFreeElement(&storeId, creator.getSerializedSize(), &dataPtr) == + returnvalue::OK); + REQUIRE(creator.SerializeIF::serializeBe(dataPtr, serLen, creator.getSerializedSize()) == + returnvalue::OK); + TmTcMessage msg(storeId); + queue.addReceivedMessage(msg); + CHECK(distributor.performOperation(0) == tmtcdistrib::NO_DESTINATION_FOUND); + } + + SECTION("Getting data fails") { + pool.nextModifyDataCallFails.first = true; + pool.nextModifyDataCallFails.second = StorageManagerIF::DATA_DOES_NOT_EXIST; + size_t serLen = 0; + store_address_t storeId; + CHECK(distributor.registerTcDestination(obswEntityId, tcAcceptor) == returnvalue::OK); + CHECK(pool.LocalPool::getFreeElement(&storeId, creator.getSerializedSize(), &dataPtr) == + returnvalue::OK); + REQUIRE(creator.SerializeIF::serializeBe(dataPtr, serLen, creator.getSerializedSize()) == + returnvalue::OK); + TmTcMessage msg(storeId); + queue.addReceivedMessage(msg); + CHECK(distributor.performOperation(0) == StorageManagerIF::DATA_DOES_NOT_EXIST); + } + + SECTION("Duplicate registration") { + CHECK(distributor.initialize() == returnvalue::OK); + CHECK(distributor.registerTcDestination(obswEntityId, tcAcceptor) == returnvalue::OK); + CHECK(distributor.registerTcDestination(obswEntityId, tcAcceptor) == returnvalue::FAILED); + } +} \ No newline at end of file diff --git a/unittests/cfdp/handler/testFaultHandler.cpp b/unittests/cfdp/handler/testFaultHandler.cpp new file mode 100644 index 00000000..5da9a70d --- /dev/null +++ b/unittests/cfdp/handler/testFaultHandler.cpp @@ -0,0 +1,89 @@ +#include + +#include "mocks/cfdp/FaultHandlerMock.h" + +TEST_CASE("CFDP Fault Handler", "[cfdp]") { + using namespace cfdp; + auto fhMock = FaultHandlerMock(); + cfdp::FaultHandlerCode fhCode; + cfdp::TransactionId id; + + SECTION("State") { + // Verify initial condition + CHECK(fhMock.getFaultHandler(ConditionCode::UNSUPPORTED_CHECKSUM_TYPE, fhCode)); + CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR); + CHECK(fhMock.getFaultHandler(ConditionCode::POSITIVE_ACK_LIMIT_REACHED, fhCode)); + CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR); + CHECK(fhMock.getFaultHandler(ConditionCode::KEEP_ALIVE_LIMIT_REACHED, fhCode)); + CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR); + CHECK(fhMock.getFaultHandler(ConditionCode::INVALID_TRANSMISSION_MODE, fhCode)); + CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR); + CHECK(fhMock.getFaultHandler(ConditionCode::FILESTORE_REJECTION, fhCode)); + CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR); + CHECK(fhMock.getFaultHandler(ConditionCode::FILE_CHECKSUM_FAILURE, fhCode)); + CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR); + CHECK(fhMock.getFaultHandler(ConditionCode::FILE_SIZE_ERROR, fhCode)); + CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR); + CHECK(fhMock.getFaultHandler(ConditionCode::NAK_LIMIT_REACHED, fhCode)); + CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR); + CHECK(fhMock.getFaultHandler(ConditionCode::INACTIVITY_DETECTED, fhCode)); + CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR); + CHECK(fhMock.getFaultHandler(ConditionCode::CHECK_LIMIT_REACHED, fhCode)); + CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR); + } + + SECTION("Call Handler, Ignore Fault") { + auto& info = fhMock.getFhInfo(FaultHandlerCode::IGNORE_ERROR); + CHECK(fhMock.reportFault(id, ConditionCode::CHECK_LIMIT_REACHED)); + CHECK(info.callCount == 1); + CHECK(info.condCodes.back() == ConditionCode::CHECK_LIMIT_REACHED); + fhMock.reportFault(id, ConditionCode::FILE_CHECKSUM_FAILURE); + CHECK(info.callCount == 2); + CHECK(info.condCodes.back() == ConditionCode::FILE_CHECKSUM_FAILURE); + } + + SECTION("Invalid Reported Code") { CHECK(not fhMock.reportFault(id, ConditionCode::NO_ERROR)); } + + SECTION("Invalid FH code") { + CHECK(not fhMock.setFaultHandler(ConditionCode::KEEP_ALIVE_LIMIT_REACHED, + FaultHandlerCode::RESERVED)); + CHECK(fhMock.getFaultHandler(ConditionCode::KEEP_ALIVE_LIMIT_REACHED, fhCode)); + CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR); + CHECK(not fhMock.setFaultHandler(ConditionCode::NO_ERROR, FaultHandlerCode::IGNORE_ERROR)); + CHECK(not fhMock.getFaultHandler(ConditionCode::NO_ERROR, fhCode)); + } + + SECTION("Set Other Fault Handler") { + CHECK(fhMock.setFaultHandler(ConditionCode::FILE_CHECKSUM_FAILURE, + FaultHandlerCode::NOTICE_OF_CANCELLATION)); + CHECK(fhMock.setFaultHandler(ConditionCode::INACTIVITY_DETECTED, + FaultHandlerCode::ABANDON_TRANSACTION)); + CHECK(fhMock.setFaultHandler(ConditionCode::KEEP_ALIVE_LIMIT_REACHED, + FaultHandlerCode::NOTICE_OF_SUSPENSION)); + auto& ignoreInfo = fhMock.getFhInfo(FaultHandlerCode::IGNORE_ERROR); + auto& cancellationInfo = fhMock.getFhInfo(FaultHandlerCode::NOTICE_OF_CANCELLATION); + auto& suspensionInfo = fhMock.getFhInfo(FaultHandlerCode::NOTICE_OF_SUSPENSION); + auto& abandonInfo = fhMock.getFhInfo(FaultHandlerCode::ABANDON_TRANSACTION); + + CHECK(fhMock.reportFault(id, ConditionCode::FILE_CHECKSUM_FAILURE)); + CHECK(cancellationInfo.callCount == 1); + CHECK(cancellationInfo.condCodes.back() == ConditionCode::FILE_CHECKSUM_FAILURE); + CHECK(ignoreInfo.callCount == 0); + CHECK(suspensionInfo.callCount == 0); + CHECK(abandonInfo.callCount == 0); + + CHECK(fhMock.reportFault(id, ConditionCode::INACTIVITY_DETECTED)); + CHECK(cancellationInfo.callCount == 1); + CHECK(ignoreInfo.callCount == 0); + CHECK(suspensionInfo.callCount == 0); + CHECK(abandonInfo.callCount == 1); + CHECK(abandonInfo.condCodes.back() == ConditionCode::INACTIVITY_DETECTED); + + CHECK(fhMock.reportFault(id, ConditionCode::KEEP_ALIVE_LIMIT_REACHED)); + CHECK(cancellationInfo.callCount == 1); + CHECK(ignoreInfo.callCount == 0); + CHECK(suspensionInfo.callCount == 1); + CHECK(suspensionInfo.condCodes.back() == ConditionCode::KEEP_ALIVE_LIMIT_REACHED); + CHECK(abandonInfo.callCount == 1); + } +} \ No newline at end of file diff --git a/unittests/cfdp/pdu/CMakeLists.txt b/unittests/cfdp/pdu/CMakeLists.txt new file mode 100644 index 00000000..02981217 --- /dev/null +++ b/unittests/cfdp/pdu/CMakeLists.txt @@ -0,0 +1,13 @@ +target_sources( + ${FSFW_TEST_TGT} + PRIVATE testAckPdu.cpp + testAckPdu.cpp + testEofPdu.cpp + testNakPdu.cpp + testFinishedPdu.cpp + testPromptPdu.cpp + testKeepAlivePdu.cpp + testMetadataPdu.cpp + testFileData.cpp + testCfdpHeader.cpp + testFileDirective.cpp) diff --git a/unittests/cfdp/pdu/testAckPdu.cpp b/unittests/cfdp/pdu/testAckPdu.cpp new file mode 100644 index 00000000..10b264ec --- /dev/null +++ b/unittests/cfdp/pdu/testAckPdu.cpp @@ -0,0 +1,100 @@ +#include +#include + +#include "fsfw/cfdp/pdu/AckPduCreator.h" +#include "fsfw/cfdp/pdu/AckPduReader.h" +#include "fsfw/globalfunctions/arrayprinter.h" + +TEST_CASE("ACK PDU", "[cfdp][pdu]") { + using namespace cfdp; + ReturnValue_t result; + std::array buf = {}; + uint8_t* bufptr = buf.data(); + size_t maxsz = buf.size(); + size_t sz = 0; + auto seqNum = TransactionSeqNum(WidthInBytes::TWO_BYTES, 15); + auto sourceId = EntityId(WidthInBytes::TWO_BYTES, 1); + auto destId = EntityId(WidthInBytes::TWO_BYTES, 2); + auto pduConf = PduConfig(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum); + AckInfo ackInfo(FileDirective::EOF_DIRECTIVE, ConditionCode::NO_ERROR, + AckTransactionStatus::ACTIVE); + auto ackSerializer = AckPduCreator(ackInfo, pduConf); + result = ackSerializer.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + + SECTION("Serialize") { + REQUIRE(buf[sz - 3] == cfdp::FileDirective::ACK); + REQUIRE((buf[sz - 2] >> 4) == FileDirective::EOF_DIRECTIVE); + REQUIRE((buf[sz - 2] & 0x0f) == 0); + REQUIRE(buf[sz - 1] == AckTransactionStatus::ACTIVE); + ackInfo.setAckedDirective(FileDirective::FINISH); + ackInfo.setAckedConditionCode(ConditionCode::FILESTORE_REJECTION); + ackInfo.setTransactionStatus(AckTransactionStatus::TERMINATED); + auto ackSerializer2 = AckPduCreator(ackInfo, pduConf); + bufptr = buf.data(); + sz = 0; + result = ackSerializer2.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + REQUIRE(buf[sz - 3] == cfdp::FileDirective::ACK); + REQUIRE((buf[sz - 2] >> 4) == FileDirective::FINISH); + REQUIRE((buf[sz - 2] & 0x0f) == 0b0001); + REQUIRE((buf[sz - 1] >> 4) == ConditionCode::FILESTORE_REJECTION); + REQUIRE((buf[sz - 1] & 0b11) == AckTransactionStatus::TERMINATED); + + bufptr = buf.data(); + sz = 0; + ackInfo.setAckedDirective(FileDirective::KEEP_ALIVE); + auto ackSerializer3 = AckPduCreator(ackInfo, pduConf); + result = ackSerializer3.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK); + // Invalid file directive + REQUIRE(result != returnvalue::OK); + + ackInfo.setAckedDirective(FileDirective::FINISH); + // buffer too small + result = ackSerializer.serialize(&bufptr, &sz, 8, SerializeIF::Endianness::NETWORK); + REQUIRE(result == SerializeIF::BUFFER_TOO_SHORT); + } + + SECTION("Deserialize") { + AckInfo ackInfo2; + auto reader = AckPduReader(buf.data(), sz, ackInfo2); + result = reader.parseData(); + REQUIRE(result == returnvalue::OK); + REQUIRE(ackInfo2.getAckedDirective() == FileDirective::EOF_DIRECTIVE); + REQUIRE(ackInfo2.getAckedConditionCode() == ConditionCode::NO_ERROR); + REQUIRE(ackInfo2.getDirectiveSubtypeCode() == 0); + REQUIRE(ackInfo2.getTransactionStatus() == AckTransactionStatus::ACTIVE); + + AckInfo newInfo = AckInfo(FileDirective::FINISH, ConditionCode::FILESTORE_REJECTION, + AckTransactionStatus::TERMINATED); + auto ackSerializer2 = AckPduCreator(newInfo, pduConf); + bufptr = buf.data(); + sz = 0; + result = ackSerializer2.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + + auto reader2 = AckPduReader(buf.data(), sz, ackInfo2); + result = reader2.parseData(); + REQUIRE(result == returnvalue::OK); + REQUIRE(ackInfo2.getAckedDirective() == FileDirective::FINISH); + REQUIRE(ackInfo2.getAckedConditionCode() == ConditionCode::FILESTORE_REJECTION); + REQUIRE(ackInfo2.getDirectiveSubtypeCode() == 0b0001); + REQUIRE(ackInfo2.getTransactionStatus() == AckTransactionStatus::TERMINATED); + + uint8_t prevVal = buf[sz - 2]; + buf[sz - 2] = FileDirective::INVALID_DIRECTIVE << 4; + result = reader2.parseData(); + REQUIRE(result == cfdp::INVALID_ACK_DIRECTIVE_FIELDS); + buf[sz - 2] = FileDirective::FINISH << 4 | 0b1111; + result = reader2.parseData(); + REQUIRE(result == cfdp::INVALID_ACK_DIRECTIVE_FIELDS); + buf[sz - 2] = prevVal; + buf[sz - 3] = cfdp::FileDirective::INVALID_DIRECTIVE; + result = reader2.parseData(); + REQUIRE(result == cfdp::INVALID_DIRECTIVE_FIELD); + buf[sz - 3] = cfdp::FileDirective::ACK; + auto maxSizeTooSmall = AckPduReader(buf.data(), sz - 2, ackInfo2); + result = maxSizeTooSmall.parseData(); + REQUIRE(result == SerializeIF::STREAM_TOO_SHORT); + } +} diff --git a/unittests/cfdp/pdu/testCfdpHeader.cpp b/unittests/cfdp/pdu/testCfdpHeader.cpp new file mode 100644 index 00000000..1fc7dfd4 --- /dev/null +++ b/unittests/cfdp/pdu/testCfdpHeader.cpp @@ -0,0 +1,327 @@ +#include +#include + +#include "fsfw/cfdp/pdu/FinishedInfo.h" +#include "fsfw/cfdp/pdu/FinishedPduCreator.h" +#include "fsfw/cfdp/pdu/HeaderCreator.h" +#include "fsfw/cfdp/pdu/PduHeaderReader.h" +#include "fsfw/returnvalues/returnvalue.h" + +using namespace returnvalue; + +TEST_CASE("CFDP Header", "[cfdp]") { + using namespace cfdp; + std::array serBuf{}; + ReturnValue_t result; + cfdp::TransactionSeqNum seqNum = TransactionSeqNum(cfdp::WidthInBytes::ONE_BYTE, 2); + cfdp::EntityId sourceId = EntityId(cfdp::WidthInBytes::ONE_BYTE, 0); + cfdp::EntityId destId = EntityId(cfdp::WidthInBytes::ONE_BYTE, 1); + PduConfig pduConf = + PduConfig(sourceId, destId, cfdp::TransmissionMode::ACKNOWLEDGED, seqNum, false); + uint8_t* serTarget = serBuf.data(); + const uint8_t* deserTarget = serTarget; + size_t serSize = 0; + auto creator = HeaderCreator(pduConf, cfdp::PduType::FILE_DIRECTIVE, 0); + + SECTION("Header State") { + REQUIRE(seqNum.getSerializedSize() == 1); + REQUIRE(creator.getPduDataFieldLen() == 0); + REQUIRE(creator.getSerializedSize() == 7); + REQUIRE(creator.getWholePduSize() == 7); + REQUIRE(creator.getCrcFlag() == false); + REQUIRE(creator.getDirection() == cfdp::Direction::TOWARDS_RECEIVER); + REQUIRE(creator.getLargeFileFlag() == false); + REQUIRE(creator.getLenEntityIds() == 1); + REQUIRE(creator.getLenSeqNum() == 1); + REQUIRE(creator.getPduType() == cfdp::PduType::FILE_DIRECTIVE); + REQUIRE(creator.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::NOT_PRESENT); + REQUIRE(creator.getSegmentationControl() == false); + REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::ACKNOWLEDGED); + cfdp::TransactionSeqNum seqNumLocal; + creator.getTransactionSeqNum(seqNumLocal); + REQUIRE(seqNumLocal.getWidth() == cfdp::WidthInBytes::ONE_BYTE); + REQUIRE(seqNumLocal.getValue() == 2); + cfdp::EntityId sourceDestId; + creator.getSourceId(sourceDestId); + REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE); + REQUIRE(sourceDestId.getValue() == 0); + creator.getDestId(sourceDestId); + REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE); + REQUIRE(sourceDestId.getValue() == 1); + } + + SECTION("Deserialization fails") { + const uint8_t** dummyPtr = nullptr; + REQUIRE(creator.deSerialize(dummyPtr, &serSize, SerializeIF::Endianness::NETWORK) == + returnvalue::FAILED); + } + + SECTION("Serialization fails") { + REQUIRE(creator.serialize(nullptr, &serSize, serBuf.size(), SerializeIF::Endianness::NETWORK) == + returnvalue::FAILED); + } + + SECTION("Buffer Too Short") { + for (uint8_t idx = 0; idx < 7; idx++) { + result = creator.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::BIG); + REQUIRE(result == static_cast(SerializeIF::BUFFER_TOO_SHORT)); + } + } + + SECTION("Set Data Field Len") { + // Set PDU data field len + creator.setPduDataFieldLen(0x0ff0); + REQUIRE(creator.getPduDataFieldLen() == 0x0ff0); + REQUIRE(creator.getSerializedSize() == 7); + REQUIRE(creator.getWholePduSize() == 7 + 0x0ff0); + serTarget = serBuf.data(); + serSize = 0; + result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG); + REQUIRE(serBuf[1] == 0x0f); + REQUIRE(serBuf[2] == 0xf0); + } + + SECTION("Serialize with Fields Flipped") { + pduConf.crcFlag = true; + pduConf.largeFile = true; + pduConf.direction = cfdp::Direction::TOWARDS_SENDER; + pduConf.mode = cfdp::TransmissionMode::UNACKNOWLEDGED; + creator.setSegmentationControl(cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION); + creator.setPduType(cfdp::PduType::FILE_DATA); + creator.setSegmentMetadataFlag(cfdp::SegmentMetadataFlag::PRESENT); + serTarget = serBuf.data(); + serSize = 0; + + SECTION("Regular") { + // Everything except version bit flipped to one now + REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(), + SerializeIF::Endianness::BIG) == returnvalue::OK); + CHECK(serBuf[0] == 0x3f); + CHECK(serBuf[3] == 0x88); + REQUIRE(creator.getCrcFlag() == true); + REQUIRE(creator.getDirection() == cfdp::Direction::TOWARDS_SENDER); + REQUIRE(creator.getLargeFileFlag() == true); + REQUIRE(creator.getLenEntityIds() == 1); + REQUIRE(creator.getLenSeqNum() == 1); + REQUIRE(creator.getPduType() == cfdp::PduType::FILE_DATA); + REQUIRE(creator.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT); + REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED); + REQUIRE(creator.getSegmentationControl() == true); + } + + SECTION("Other variable sized fields") { + pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff); + pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00); + pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff); + REQUIRE(pduConf.sourceId.getSerializedSize() == 4); + REQUIRE(creator.getSerializedSize() == 14); + REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(), + SerializeIF::Endianness::BIG) == returnvalue::OK); + REQUIRE(creator.getCrcFlag() == true); + REQUIRE(creator.getDirection() == cfdp::Direction::TOWARDS_SENDER); + REQUIRE(creator.getLargeFileFlag() == true); + REQUIRE(creator.getLenEntityIds() == 4); + REQUIRE(creator.getLenSeqNum() == 2); + REQUIRE(creator.getPduType() == cfdp::PduType::FILE_DATA); + REQUIRE(creator.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT); + REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED); + REQUIRE(creator.getSegmentationControl() == true); + // Last three bits are 2 now (length of seq number) and bit 1 to bit 3 is 4 (len entity IDs) + REQUIRE(serBuf[3] == 0b10111001); + uint32_t entityId = 0; + size_t deSerSize = 0; + SerializeAdapter::deSerialize(&entityId, serBuf.data() + 4, &deSerSize, + SerializeIF::Endianness::NETWORK); + CHECK(deSerSize == 4); + CHECK(entityId == 0xff00ff00); + uint16_t seqNumRaw = 0; + SerializeAdapter::deSerialize(&seqNumRaw, serBuf.data() + 8, &deSerSize, + SerializeIF::Endianness::NETWORK); + CHECK(deSerSize == 2); + CHECK(seqNumRaw == 0x0fff); + SerializeAdapter::deSerialize(&entityId, serBuf.data() + 10, &deSerSize, + SerializeIF::Endianness::NETWORK); + CHECK(deSerSize == 4); + CHECK(entityId == 0x00ff00ff); + } + + SECTION("Buffer Too Short") { + pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff); + pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00); + pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff); + for (uint8_t idx = 0; idx < 14; idx++) { + REQUIRE(creator.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::BIG) == + SerializeIF::BUFFER_TOO_SHORT); + } + } + } + + SECTION("Invalid Variable Sized Fields") { + result = pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 0xfff); + REQUIRE(result == returnvalue::FAILED); + result = pduConf.sourceId.setValue(cfdp::WidthInBytes::TWO_BYTES, 0xfffff); + REQUIRE(result == returnvalue::FAILED); + result = pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xfffffffff); + REQUIRE(result == returnvalue::FAILED); + } + + SECTION("Header Serialization") { + result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG); + REQUIRE(result == returnvalue::OK); + REQUIRE(serSize == 7); + // Only version bits are set + REQUIRE(serBuf[0] == 0b00100000); + // PDU data field length is 0 + REQUIRE(serBuf[1] == 0); + REQUIRE(serBuf[2] == 0); + // Entity and Transaction Sequence number are 1 byte large + REQUIRE(serBuf[3] == 0b00000000); + // Source ID + REQUIRE(serBuf[4] == 0); + // Transaction Seq Number + REQUIRE(serBuf[5] == 2); + // Dest ID + REQUIRE(serBuf[6] == 1); + + uint8_t oneByteSourceId = 32; + serTarget = &oneByteSourceId; + size_t deserLen = 1; + pduConf.sourceId.deSerialize(cfdp::WidthInBytes::ONE_BYTE, + const_cast(&serTarget), &deserLen, + SerializeIF::Endianness::MACHINE); + REQUIRE(pduConf.sourceId.getValue() == 32); + + uint16_t twoByteSourceId = 0xf0f0; + serTarget = reinterpret_cast(&twoByteSourceId); + deserLen = 2; + pduConf.sourceId.deSerialize(cfdp::WidthInBytes::TWO_BYTES, + const_cast(&serTarget), &deserLen, + SerializeIF::Endianness::MACHINE); + REQUIRE(pduConf.sourceId.getValue() == 0xf0f0); + + uint32_t fourByteSourceId = 0xf0f0f0f0; + serTarget = reinterpret_cast(&fourByteSourceId); + deserLen = 4; + pduConf.sourceId.deSerialize(cfdp::WidthInBytes::FOUR_BYTES, + const_cast(&serTarget), &deserLen, + SerializeIF::Endianness::MACHINE); + REQUIRE(pduConf.sourceId.getValue() == 0xf0f0f0f0); + + pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 1); + serTarget = serBuf.data(); + serSize = 1; + result = pduConf.sourceId.serialize(&serTarget, &serSize, 1, SerializeIF::Endianness::MACHINE); + REQUIRE(result == static_cast(SerializeIF::BUFFER_TOO_SHORT)); + } + + SECTION("Header Deserialization 0") { + REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG) == + returnvalue::OK); + REQUIRE(serBuf[1] == 0); + REQUIRE(serBuf[2] == 0); + // Entity and Transaction Sequence number are 1 byte large + REQUIRE(serBuf[3] == 0b00000000); + REQUIRE(serSize == 7); + // Deser call not strictly necessary + auto reader = PduHeaderReader(serBuf.data(), serBuf.size()); + + ReturnValue_t serResult = reader.parseData(); + REQUIRE(serResult == returnvalue::OK); + REQUIRE(reader.getPduDataFieldLen() == 0); + REQUIRE(reader.getHeaderSize() == 7); + REQUIRE(reader.getWholePduSize() == 7); + REQUIRE(reader.getCrcFlag() == false); + REQUIRE(reader.getDirection() == cfdp::Direction::TOWARDS_RECEIVER); + REQUIRE(reader.getLargeFileFlag() == false); + REQUIRE(reader.getLenEntityIds() == 1); + REQUIRE(reader.getLenSeqNum() == 1); + REQUIRE(reader.getPduType() == cfdp::PduType::FILE_DIRECTIVE); + REQUIRE(reader.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::NOT_PRESENT); + REQUIRE(reader.getSegmentationControl() == false); + REQUIRE(reader.getTransmissionMode() == cfdp::TransmissionMode::ACKNOWLEDGED); + // No PDU data contained, so the PDU data field is empty + REQUIRE(reader.getPduDataField() == nullptr); + + size_t deSerSize = reader.getWholePduSize(); + serTarget = serBuf.data(); + const auto** serTargetConst = const_cast(&serTarget); + result = reader.parseData(); + REQUIRE(result == returnvalue::OK); + } + + SECTION("Header Deserialization 1") { + pduConf.crcFlag = true; + pduConf.largeFile = true; + pduConf.direction = cfdp::Direction::TOWARDS_SENDER; + pduConf.mode = cfdp::TransmissionMode::UNACKNOWLEDGED; + creator.setSegmentationControl(cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION); + creator.setPduType(cfdp::PduType::FILE_DATA); + creator.setSegmentMetadataFlag(cfdp::SegmentMetadataFlag::PRESENT); + result = pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff); + REQUIRE(result == returnvalue::OK); + result = pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00); + REQUIRE(result == returnvalue::OK); + result = pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff); + REQUIRE(result == returnvalue::OK); + serTarget = serBuf.data(); + serSize = 0; + result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG); + PduHeaderReader reader(serBuf.data(), serBuf.size()); + REQUIRE(reader.parseData() == returnvalue::OK); + // Everything except version bit flipped to one now + REQUIRE(serBuf[0] == 0x3f); + REQUIRE(serBuf[3] == 0b10111001); + REQUIRE(reader.getWholePduSize() == 14); + + REQUIRE(reader.getCrcFlag() == true); + REQUIRE(reader.getDirection() == cfdp::Direction::TOWARDS_SENDER); + REQUIRE(reader.getLargeFileFlag() == true); + REQUIRE(reader.getLenEntityIds() == 4); + REQUIRE(reader.getLenSeqNum() == 2); + REQUIRE(reader.getPduType() == cfdp::PduType::FILE_DATA); + REQUIRE(reader.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT); + REQUIRE(reader.getSegmentationControl() == true); + REQUIRE(reader.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED); + // Again, no data field set because this is a header only + REQUIRE(reader.getPduDataField() == nullptr); + + cfdp::TransactionSeqNum seqNumLocal; + reader.getTransactionSeqNum(seqNumLocal); + REQUIRE(seqNumLocal.getWidth() == cfdp::WidthInBytes::TWO_BYTES); + REQUIRE(seqNumLocal.getValue() == 0x0fff); + cfdp::EntityId sourceDestId; + reader.getSourceId(sourceDestId); + REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::FOUR_BYTES); + REQUIRE(sourceDestId.getValue() == 0xff00ff00); + reader.getDestId(sourceDestId); + REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::FOUR_BYTES); + REQUIRE(sourceDestId.getValue() == 0x00ff00ff); + CHECK(reader.setReadOnlyData(nullptr, -1) != returnvalue::OK); + REQUIRE(reader.getHeaderSize() == 14); + + SECTION("Manipulate Source Dest ID") { + serTarget = serBuf.data(); + serSize = 0; + pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 22); + pduConf.destId.setValue(cfdp::WidthInBytes::ONE_BYTE, 48); + result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG); + reader.getSourceId(sourceDestId); + REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE); + REQUIRE(sourceDestId.getValue() == 22); + } + } + + SECTION("Verify data field pointer") { + FinishedInfo info(cfdp::ConditionCode::INACTIVITY_DETECTED, + cfdp::FileDeliveryCode::DATA_INCOMPLETE, + cfdp::FileDeliveryStatus::DISCARDED_DELIBERATELY); + FinishPduCreator finishCreator(pduConf, info); + REQUIRE(finishCreator.serialize(serBuf.data(), serSize, serBuf.size()) == OK); + // This PDU contains the directive code and some finishes PDU properties packed into one byte + // in addition to the header + REQUIRE(finishCreator.getSerializedSize() == 9); + PduHeaderReader reader(serBuf.data(), serBuf.size()); + REQUIRE(reader.parseData() == returnvalue::OK); + REQUIRE(reader.getPduDataField() == serBuf.data() + 7); + } +} diff --git a/tests/src/fsfw_tests/unit/cfdp/testEofPdu.cpp b/unittests/cfdp/pdu/testEofPdu.cpp similarity index 73% rename from tests/src/fsfw_tests/unit/cfdp/testEofPdu.cpp rename to unittests/cfdp/pdu/testEofPdu.cpp index d400af5a..83e61780 100644 --- a/tests/src/fsfw_tests/unit/cfdp/testEofPdu.cpp +++ b/unittests/cfdp/pdu/testEofPdu.cpp @@ -1,14 +1,14 @@ #include #include -#include "fsfw/cfdp/pdu/EofPduDeserializer.h" -#include "fsfw/cfdp/pdu/EofPduSerializer.h" +#include "fsfw/cfdp/pdu/EofPduCreator.h" +#include "fsfw/cfdp/pdu/EofPduReader.h" #include "fsfw/globalfunctions/arrayprinter.h" -TEST_CASE("EOF PDU", "[EofPdu]") { +TEST_CASE("EOF PDU", "[cfdp][pdu]") { using namespace cfdp; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; std::array buf = {}; uint8_t* bufPtr = buf.data(); size_t sz = 0; @@ -20,24 +20,24 @@ TEST_CASE("EOF PDU", "[EofPdu]") { TransactionSeqNum seqNum(WidthInBytes::TWO_BYTES, 15); EntityId sourceId(WidthInBytes::TWO_BYTES, 1); - PduConfig pduConf(TransmissionModes::ACKNOWLEDGED, seqNum, sourceId, destId); + PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum); - auto eofSerializer = EofPduSerializer(pduConf, eofInfo); + auto eofSerializer = EofPduCreator(pduConf, eofInfo); SECTION("Serialize") { result = eofSerializer.serialize(&bufPtr, &sz, buf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(((buf[1] << 8) | buf[2]) == 10); uint32_t checksum = 0; result = SerializeAdapter::deSerialize(&checksum, buf.data() + sz - 8, nullptr, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(checksum == 5); uint32_t fileSizeVal = 0; result = SerializeAdapter::deSerialize(&fileSizeVal, buf.data() + sz - 4, nullptr, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(fileSizeVal == 12); - REQUIRE(buf[sz - 10] == cfdp::FileDirectives::EOF_DIRECTIVE); + REQUIRE(buf[sz - 10] == cfdp::FileDirective::EOF_DIRECTIVE); REQUIRE(buf[sz - 9] == 0x00); REQUIRE(sz == 20); @@ -45,20 +45,20 @@ TEST_CASE("EOF PDU", "[EofPdu]") { eofInfo.setFileSize(0x10ffffff10, true); pduConf.largeFile = true; // Should serialize with fault location now - auto serializeWithFaultLocation = EofPduSerializer(pduConf, eofInfo); + auto serializeWithFaultLocation = EofPduCreator(pduConf, eofInfo); bufPtr = buf.data(); sz = 0; result = serializeWithFaultLocation.serialize(&bufPtr, &sz, buf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(sz == 28); - REQUIRE(buf[10] == cfdp::FileDirectives::EOF_DIRECTIVE); + REQUIRE(buf[10] == cfdp::FileDirective::EOF_DIRECTIVE); REQUIRE(buf[11] >> 4 == cfdp::ConditionCode::FILESTORE_REJECTION); uint64_t fileSizeLarge = 0; result = SerializeAdapter::deSerialize(&fileSizeLarge, buf.data() + 16, nullptr, SerializeIF::Endianness::NETWORK); REQUIRE(fileSizeLarge == 0x10ffffff10); - REQUIRE(buf[sz - 4] == cfdp::TlvTypes::ENTITY_ID); + REQUIRE(buf[sz - 4] == cfdp::TlvType::ENTITY_ID); // width of entity ID is 2 REQUIRE(buf[sz - 3] == 2); uint16_t entityIdRaw = 0; @@ -80,12 +80,12 @@ TEST_CASE("EOF PDU", "[EofPdu]") { SECTION("Deserialize") { result = eofSerializer.serialize(&bufPtr, &sz, buf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); EntityIdTlv tlv(destId); EofInfo emptyInfo(&tlv); - auto deserializer = EofPduDeserializer(buf.data(), buf.size(), emptyInfo); + auto deserializer = EofPduReader(buf.data(), buf.size(), emptyInfo); result = deserializer.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(emptyInfo.getConditionCode() == cfdp::ConditionCode::NO_ERROR); REQUIRE(emptyInfo.getChecksum() == 5); REQUIRE(emptyInfo.getFileSize().getSize() == 12); @@ -94,25 +94,25 @@ TEST_CASE("EOF PDU", "[EofPdu]") { eofInfo.setFileSize(0x10ffffff10, true); pduConf.largeFile = true; // Should serialize with fault location now - auto serializeWithFaultLocation = EofPduSerializer(pduConf, eofInfo); + auto serializeWithFaultLocation = EofPduCreator(pduConf, eofInfo); bufPtr = buf.data(); sz = 0; result = serializeWithFaultLocation.serialize(&bufPtr, &sz, buf.size(), SerializeIF::Endianness::NETWORK); - auto deserializer2 = EofPduDeserializer(buf.data(), buf.size(), emptyInfo); + auto deserializer2 = EofPduReader(buf.data(), buf.size(), emptyInfo); result = deserializer2.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(emptyInfo.getConditionCode() == cfdp::ConditionCode::FILESTORE_REJECTION); REQUIRE(emptyInfo.getChecksum() == 5); REQUIRE(emptyInfo.getFileSize().getSize() == 0x10ffffff10); - REQUIRE(emptyInfo.getFaultLoc()->getType() == cfdp::TlvTypes::ENTITY_ID); + REQUIRE(emptyInfo.getFaultLoc()->getType() == cfdp::TlvType::ENTITY_ID); REQUIRE(emptyInfo.getFaultLoc()->getSerializedSize() == 4); uint16_t destId = emptyInfo.getFaultLoc()->getEntityId().getValue(); REQUIRE(destId == 2); for (size_t maxSz = 0; maxSz < deserializer2.getWholePduSize() - 1; maxSz++) { - auto invalidDeser = EofPduDeserializer(buf.data(), maxSz, emptyInfo); + auto invalidDeser = EofPduReader(buf.data(), maxSz, emptyInfo); result = invalidDeser.parseData(); - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); + REQUIRE(result != returnvalue::OK); } } } diff --git a/tests/src/fsfw_tests/unit/cfdp/testFileData.cpp b/unittests/cfdp/pdu/testFileData.cpp similarity index 85% rename from tests/src/fsfw_tests/unit/cfdp/testFileData.cpp rename to unittests/cfdp/pdu/testFileData.cpp index 1f6a09e9..39139378 100644 --- a/tests/src/fsfw_tests/unit/cfdp/testFileData.cpp +++ b/unittests/cfdp/pdu/testFileData.cpp @@ -1,15 +1,15 @@ #include #include -#include "fsfw/cfdp/pdu/FileDataDeserializer.h" -#include "fsfw/cfdp/pdu/FileDataSerializer.h" +#include "fsfw/cfdp/pdu/FileDataCreator.h" +#include "fsfw/cfdp/pdu/FileDataReader.h" #include "fsfw/globalfunctions/arrayprinter.h" #include "fsfw/serviceinterface.h" -TEST_CASE("File Data PDU", "[FileDataPdu]") { +TEST_CASE("File Data PDU", "[cfdp][pdu]") { using namespace cfdp; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; std::array fileBuffer = {}; std::array fileDataBuffer = {}; uint8_t* buffer = fileDataBuffer.data(); @@ -17,7 +17,7 @@ TEST_CASE("File Data PDU", "[FileDataPdu]") { EntityId destId(WidthInBytes::TWO_BYTES, 2); TransactionSeqNum seqNum(WidthInBytes::TWO_BYTES, 15); EntityId sourceId(WidthInBytes::TWO_BYTES, 1); - PduConfig pduConf(TransmissionModes::ACKNOWLEDGED, seqNum, sourceId, destId); + PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum); for (uint8_t idx = 0; idx < 10; idx++) { fileBuffer[idx] = idx; @@ -26,10 +26,10 @@ TEST_CASE("File Data PDU", "[FileDataPdu]") { FileDataInfo info(offset, fileBuffer.data(), 10); SECTION("Serialization") { - FileDataSerializer serializer(pduConf, info); + FileDataCreator serializer(pduConf, info); result = serializer.serialize(&buffer, &sz, fileDataBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(sz == 24); // 10 file bytes plus 4 byte offset REQUIRE(((fileDataBuffer[1] << 8) | fileDataBuffer[2]) == 14); @@ -39,7 +39,7 @@ TEST_CASE("File Data PDU", "[FileDataPdu]") { buffer = fileDataBuffer.data(); result = SerializeAdapter::deSerialize(&offsetRaw, buffer + 10, nullptr, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(offsetRaw == 50); buffer = fileDataBuffer.data() + 14; for (size_t idx = 0; idx < 10; idx++) { @@ -62,13 +62,13 @@ TEST_CASE("File Data PDU", "[FileDataPdu]") { result = serializer.serialize(&buffer, &sz, fileDataBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(((fileDataBuffer[1] << 8) | fileDataBuffer[2]) == 25); // First bit: Seg Ctrl is set // Bits 1 to 3 length of enitity IDs is 2 // Bit 4: Segment metadata flag is set // Bit 5 to seven: length of transaction seq num is 2 - REQUIRE(fileDataBuffer[3] == 0b10101010); + REQUIRE(fileDataBuffer[3] == 0b10011001); REQUIRE((fileDataBuffer[10] >> 6) & 0b11 == cfdp::RecordContinuationState::CONTAINS_START_AND_END); // Segment metadata length @@ -88,7 +88,7 @@ TEST_CASE("File Data PDU", "[FileDataPdu]") { buffer = fileDataBuffer.data(); sz = 0; result = serializer.serialize(&buffer, &invalidStartSz, sz, SerializeIF::Endianness::NETWORK); - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); + REQUIRE(result != returnvalue::OK); } info.setSegmentMetadataFlag(true); @@ -102,16 +102,16 @@ TEST_CASE("File Data PDU", "[FileDataPdu]") { } SECTION("Deserialization") { - FileDataSerializer serializer(pduConf, info); + FileDataCreator serializer(pduConf, info); result = serializer.serialize(&buffer, &sz, fileDataBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); FileSize emptyOffset; FileDataInfo emptyInfo(emptyOffset); - FileDataDeserializer deserializer(fileDataBuffer.data(), fileDataBuffer.size(), emptyInfo); + FileDataReader deserializer(fileDataBuffer.data(), fileDataBuffer.size(), emptyInfo); result = deserializer.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(deserializer.getWholePduSize() == 24); REQUIRE(deserializer.getPduDataFieldLen() == 14); REQUIRE(deserializer.getSegmentationControl() == @@ -136,10 +136,10 @@ TEST_CASE("File Data PDU", "[FileDataPdu]") { sz = 0; result = serializer.serialize(&buffer, &sz, fileDataBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); result = deserializer.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(emptyInfo.getOffset().getSize() == 50); REQUIRE(emptyInfo.hasSegmentMetadata() == true); @@ -164,7 +164,7 @@ TEST_CASE("File Data PDU", "[FileDataPdu]") { // Starting at 15, the file data is parsed. There is not leading file data length // field to the parser can't check whether the remaining length is valid if (invalidPduField < 15) { - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); + REQUIRE(result != returnvalue::OK); } } } diff --git a/unittests/cfdp/pdu/testFileDirective.cpp b/unittests/cfdp/pdu/testFileDirective.cpp new file mode 100644 index 00000000..17e0d699 --- /dev/null +++ b/unittests/cfdp/pdu/testFileDirective.cpp @@ -0,0 +1,85 @@ +#include +#include + +#include "fsfw/cfdp/pdu/FileDirectiveCreator.h" +#include "fsfw/cfdp/pdu/FileDirectiveReader.h" + +TEST_CASE("CFDP File Directive", "[cfdp][pdu]") { + using namespace cfdp; + std::array serBuf{}; + ReturnValue_t result; + cfdp::TransactionSeqNum seqNum = TransactionSeqNum(cfdp::WidthInBytes::ONE_BYTE, 2); + cfdp::EntityId sourceId = EntityId(cfdp::WidthInBytes::ONE_BYTE, 0); + cfdp::EntityId destId = EntityId(cfdp::WidthInBytes::ONE_BYTE, 1); + PduConfig pduConf = + PduConfig(sourceId, destId, cfdp::TransmissionMode::ACKNOWLEDGED, seqNum, false); + uint8_t* serTarget = serBuf.data(); + const uint8_t* deserTarget = serTarget; + size_t serSize = 0; + auto fdSer = FileDirectiveCreator(pduConf, FileDirective::ACK, 4); + + SECTION("Serialization") { + REQUIRE(fdSer.getSerializedSize() == 8); + serTarget = serBuf.data(); + serSize = 0; + result = fdSer.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + // Only version bits are set + REQUIRE(serBuf[0] == 0b00100000); + // PDU data field length is 5 (4 + Directive code octet) + REQUIRE(serBuf[1] == 0); + REQUIRE(serBuf[2] == 5); + // Entity and Transaction Sequence number are 1 byte large + REQUIRE(serBuf[3] == 0b00000000); + // Source ID + REQUIRE(serBuf[4] == 0); + // Transaction Seq Number + REQUIRE(serBuf[5] == 2); + // Dest ID + REQUIRE(serBuf[6] == 1); + REQUIRE(serBuf[7] == FileDirective::ACK); + } + + SECTION("Serialization fails") { + REQUIRE(fdSer.serialize(nullptr, nullptr, 85, SerializeIF::Endianness::NETWORK) == + returnvalue::FAILED); + } + + SECTION("Buffer Too Short") { + for (uint8_t idx = 0; idx < 8; idx++) { + serTarget = serBuf.data(); + serSize = 0; + REQUIRE(fdSer.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::NETWORK) == + SerializeIF::BUFFER_TOO_SHORT); + } + } + + SECTION("Deserialize") { + CHECK(fdSer.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::NETWORK) == + returnvalue::OK); + serTarget = serBuf.data(); + + REQUIRE(fdSer.deSerialize(&deserTarget, &serSize, SerializeIF::Endianness::NETWORK) == + returnvalue::FAILED); + deserTarget = serBuf.data(); + CHECK(serSize == 8); + auto fdDeser = FileDirectiveReader(deserTarget, serBuf.size()); + REQUIRE(fdDeser.isNull()); + REQUIRE(not fdDeser); + REQUIRE(fdDeser.getEndianness() == SerializeIF::Endianness::NETWORK); + fdDeser.setEndianness(SerializeIF::Endianness::MACHINE); + REQUIRE(fdDeser.getEndianness() == SerializeIF::Endianness::MACHINE); + fdDeser.setEndianness(SerializeIF::Endianness::NETWORK); + REQUIRE(fdDeser.parseData() == returnvalue::OK); + REQUIRE(not fdDeser.isNull()); + REQUIRE(fdDeser); + REQUIRE(fdDeser.getFileDirective() == FileDirective::ACK); + REQUIRE(fdDeser.getPduDataFieldLen() == 5); + REQUIRE(fdDeser.getHeaderSize() == 8); + REQUIRE(fdDeser.getPduType() == cfdp::PduType::FILE_DIRECTIVE); + + serBuf[7] = 0xff; + // Invalid file directive + REQUIRE(fdDeser.parseData() == cfdp::INVALID_DIRECTIVE_FIELD); + } +} diff --git a/tests/src/fsfw_tests/unit/cfdp/testFinishedPdu.cpp b/unittests/cfdp/pdu/testFinishedPdu.cpp similarity index 72% rename from tests/src/fsfw_tests/unit/cfdp/testFinishedPdu.cpp rename to unittests/cfdp/pdu/testFinishedPdu.cpp index 143eaf2a..b8b395cb 100644 --- a/tests/src/fsfw_tests/unit/cfdp/testFinishedPdu.cpp +++ b/unittests/cfdp/pdu/testFinishedPdu.cpp @@ -1,41 +1,41 @@ #include #include -#include "fsfw/cfdp/pdu/FinishedPduDeserializer.h" -#include "fsfw/cfdp/pdu/FinishedPduSerializer.h" +#include "fsfw/cfdp/pdu/FinishedPduCreator.h" +#include "fsfw/cfdp/pdu/FinishedPduReader.h" #include "fsfw/globalfunctions/arrayprinter.h" -TEST_CASE("Finished PDU", "[FinishedPdu]") { +TEST_CASE("Finished PDU", "[cfdp][pdu]") { using namespace cfdp; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; std::array fnBuffer = {}; uint8_t* buffer = fnBuffer.data(); size_t sz = 0; EntityId destId(WidthInBytes::TWO_BYTES, 2); TransactionSeqNum seqNum(WidthInBytes::TWO_BYTES, 15); EntityId sourceId(WidthInBytes::TWO_BYTES, 1); - PduConfig pduConf(TransmissionModes::ACKNOWLEDGED, seqNum, sourceId, destId); + PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum); cfdp::Lv emptyFsMsg; FinishedInfo info(cfdp::ConditionCode::INACTIVITY_DETECTED, - cfdp::FinishedDeliveryCode::DATA_INCOMPLETE, - cfdp::FinishedFileStatus::DISCARDED_DELIBERATELY); + cfdp::FileDeliveryCode::DATA_INCOMPLETE, + cfdp::FileDeliveryStatus::DISCARDED_DELIBERATELY); SECTION("Serialize") { - FinishPduSerializer serializer(pduConf, info); + FinishPduCreator serializer(pduConf, info); result = serializer.serialize(&buffer, &sz, fnBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(serializer.getSerializedSize() == 12); REQUIRE(((fnBuffer[1] << 8) | fnBuffer[2]) == 2); - REQUIRE(fnBuffer[10] == cfdp::FileDirectives::FINISH); + REQUIRE(fnBuffer[10] == cfdp::FileDirective::FINISH); REQUIRE(((fnBuffer[sz - 1] >> 4) & 0x0f) == cfdp::ConditionCode::INACTIVITY_DETECTED); - REQUIRE(((fnBuffer[sz - 1] >> 2) & 0x01) == cfdp::FinishedDeliveryCode::DATA_INCOMPLETE); - REQUIRE((fnBuffer[sz - 1] & 0b11) == cfdp::FinishedFileStatus::DISCARDED_DELIBERATELY); + REQUIRE(((fnBuffer[sz - 1] >> 2) & 0x01) == cfdp::FileDeliveryCode::DATA_INCOMPLETE); + REQUIRE((fnBuffer[sz - 1] & 0b11) == cfdp::FileDeliveryStatus::DISCARDED_DELIBERATELY); REQUIRE(sz == 12); // Add a filestore response std::string firstName = "hello.txt"; - cfdp::Lv firstNameLv(reinterpret_cast(firstName.data()), firstName.size()); + cfdp::StringLv firstNameLv(firstName); FilestoreResponseTlv response(cfdp::FilestoreActionCode::DELETE_FILE, cfdp::FSR_APPEND_FILE_1_NOT_EXISTS, firstNameLv, nullptr); FilestoreResponseTlv* responsePtr = &response; @@ -47,13 +47,13 @@ TEST_CASE("Finished PDU", "[FinishedPdu]") { sz = 0; buffer = fnBuffer.data(); result = serializer.serialize(&buffer, &sz, fnBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(serializer.getSerializedSize() == 12 + 14); REQUIRE(serializer.getPduDataFieldLen() == 16); // Add two filestore responses and a fault location parameter std::string secondName = "hello2.txt"; - cfdp::Lv secondNameLv(reinterpret_cast(secondName.data()), secondName.size()); + cfdp::StringLv secondNameLv(secondName); FilestoreResponseTlv response2(cfdp::FilestoreActionCode::DENY_FILE, cfdp::FSR_SUCCESS, secondNameLv, nullptr); REQUIRE(response2.getSerializedSize() == 15); @@ -69,39 +69,39 @@ TEST_CASE("Finished PDU", "[FinishedPdu]") { sz = 0; buffer = fnBuffer.data(); result = serializer.serialize(&buffer, &sz, fnBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); info.setConditionCode(cfdp::ConditionCode::FILESTORE_REJECTION); REQUIRE(serializer.getSerializedSize() == 12 + 14 + 15 + 4); REQUIRE(sz == 12 + 14 + 15 + 4); - info.setFileStatus(cfdp::FinishedFileStatus::DISCARDED_FILESTORE_REJECTION); - REQUIRE(info.getFileStatus() == cfdp::FinishedFileStatus::DISCARDED_FILESTORE_REJECTION); - info.setDeliveryCode(cfdp::FinishedDeliveryCode::DATA_INCOMPLETE); - REQUIRE(info.getDeliveryCode() == cfdp::FinishedDeliveryCode::DATA_INCOMPLETE); + info.setFileStatus(cfdp::FileDeliveryStatus::DISCARDED_FILESTORE_REJECTION); + REQUIRE(info.getFileStatus() == cfdp::FileDeliveryStatus::DISCARDED_FILESTORE_REJECTION); + info.setDeliveryCode(cfdp::FileDeliveryCode::DATA_INCOMPLETE); + REQUIRE(info.getDeliveryCode() == cfdp::FileDeliveryCode::DATA_INCOMPLETE); for (size_t maxSz = 0; maxSz < 45; maxSz++) { sz = 0; buffer = fnBuffer.data(); result = serializer.serialize(&buffer, &sz, maxSz, SerializeIF::Endianness::NETWORK); - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); + REQUIRE(result != returnvalue::OK); } } SECTION("Deserialize") { FinishedInfo emptyInfo; - FinishPduSerializer serializer(pduConf, info); + FinishPduCreator serializer(pduConf, info); result = serializer.serialize(&buffer, &sz, fnBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - FinishPduDeserializer deserializer(fnBuffer.data(), fnBuffer.size(), emptyInfo); + REQUIRE(result == returnvalue::OK); + FinishPduReader deserializer(fnBuffer.data(), fnBuffer.size(), emptyInfo); result = deserializer.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(emptyInfo.getFileStatus() == cfdp::FinishedFileStatus::DISCARDED_DELIBERATELY); + REQUIRE(result == returnvalue::OK); + REQUIRE(emptyInfo.getFileStatus() == cfdp::FileDeliveryStatus::DISCARDED_DELIBERATELY); REQUIRE(emptyInfo.getConditionCode() == cfdp::ConditionCode::INACTIVITY_DETECTED); - REQUIRE(emptyInfo.getDeliveryCode() == cfdp::FinishedDeliveryCode::DATA_INCOMPLETE); + REQUIRE(emptyInfo.getDeliveryCode() == cfdp::FileDeliveryCode::DATA_INCOMPLETE); // Add a filestore response sz = 0; buffer = fnBuffer.data(); std::string firstName = "hello.txt"; - cfdp::Lv firstNameLv(reinterpret_cast(firstName.data()), firstName.size()); + cfdp::StringLv firstNameLv(firstName); FilestoreResponseTlv response(cfdp::FilestoreActionCode::DELETE_FILE, cfdp::FSR_NOT_PERFORMED, firstNameLv, nullptr); FilestoreResponseTlv* responsePtr = &response; @@ -110,13 +110,13 @@ TEST_CASE("Finished PDU", "[FinishedPdu]") { serializer.updateDirectiveFieldLen(); REQUIRE(serializer.getPduDataFieldLen() == 16); result = serializer.serialize(&buffer, &sz, fnBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); FilestoreResponseTlv emptyResponse(firstNameLv, nullptr); responsePtr = &emptyResponse; emptyInfo.setFilestoreResponsesArray(&responsePtr, nullptr, &len); - FinishPduDeserializer deserializer2(fnBuffer.data(), fnBuffer.size(), emptyInfo); + FinishPduReader deserializer2(fnBuffer.data(), fnBuffer.size(), emptyInfo); result = deserializer2.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(emptyInfo.getFsResponsesLen() == 1); FilestoreResponseTlv** responseArray = nullptr; emptyInfo.getFilestoreResonses(&responseArray, nullptr, nullptr); @@ -130,7 +130,7 @@ TEST_CASE("Finished PDU", "[FinishedPdu]") { // Add two filestore responses and a fault location parameter std::string secondName = "hello2.txt"; - cfdp::Lv secondNameLv(reinterpret_cast(secondName.data()), secondName.size()); + cfdp::StringLv secondNameLv(secondName); FilestoreResponseTlv response2(cfdp::FilestoreActionCode::DENY_FILE, cfdp::FSR_SUCCESS, secondNameLv, nullptr); REQUIRE(response2.getSerializedSize() == 15); @@ -145,16 +145,16 @@ TEST_CASE("Finished PDU", "[FinishedPdu]") { sz = 0; buffer = fnBuffer.data(); result = serializer.serialize(&buffer, &sz, fnBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); EntityId emptyId; EntityIdTlv emptyFaultLoc(emptyId); emptyInfo.setFaultLocation(&emptyFaultLoc); response.setFilestoreMessage(&emptyFsMsg); emptyInfo.setFilestoreResponsesArray(responses.data(), &len, &len); response2.setFilestoreMessage(&emptyFsMsg); - FinishPduDeserializer deserializer3(fnBuffer.data(), fnBuffer.size(), emptyInfo); + FinishPduReader deserializer3(fnBuffer.data(), fnBuffer.size(), emptyInfo); result = deserializer3.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); auto& infoRef = deserializer3.getInfo(); REQUIRE(deserializer3.getWholePduSize() == 45); @@ -176,14 +176,14 @@ TEST_CASE("Finished PDU", "[FinishedPdu]") { fnBuffer[11] = tmp; // Invalid TLV type, should be entity ID - fnBuffer[sz - 4] = cfdp::TlvTypes::FILESTORE_REQUEST; + fnBuffer[sz - 4] = cfdp::TlvType::FILESTORE_REQUEST; result = deserializer3.parseData(); REQUIRE(result == cfdp::INVALID_TLV_TYPE); for (size_t maxSz = 0; maxSz < 45; maxSz++) { - FinishPduDeserializer faultyDeser(fnBuffer.data(), maxSz, emptyInfo); + FinishPduReader faultyDeser(fnBuffer.data(), maxSz, emptyInfo); result = faultyDeser.parseData(); - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); + REQUIRE(result != returnvalue::OK); } } } diff --git a/tests/src/fsfw_tests/unit/cfdp/testKeepAlivePdu.cpp b/unittests/cfdp/pdu/testKeepAlivePdu.cpp similarity index 62% rename from tests/src/fsfw_tests/unit/cfdp/testKeepAlivePdu.cpp rename to unittests/cfdp/pdu/testKeepAlivePdu.cpp index 8ec8c66c..d07bccae 100644 --- a/tests/src/fsfw_tests/unit/cfdp/testKeepAlivePdu.cpp +++ b/unittests/cfdp/pdu/testKeepAlivePdu.cpp @@ -1,32 +1,32 @@ #include #include -#include "fsfw/cfdp/pdu/KeepAlivePduDeserializer.h" -#include "fsfw/cfdp/pdu/KeepAlivePduSerializer.h" +#include "fsfw/cfdp/pdu/KeepAlivePduCreator.h" +#include "fsfw/cfdp/pdu/KeepAlivePduReader.h" #include "fsfw/globalfunctions/arrayprinter.h" -TEST_CASE("Keep Alive PDU", "[KeepAlivePdu]") { +TEST_CASE("Keep Alive PDU", "[cfdp][pdu]") { using namespace cfdp; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; std::array kaBuffer = {}; uint8_t* buffer = kaBuffer.data(); size_t sz = 0; EntityId destId(WidthInBytes::TWO_BYTES, 2); TransactionSeqNum seqNum(WidthInBytes::TWO_BYTES, 15); EntityId sourceId(WidthInBytes::TWO_BYTES, 1); - PduConfig pduConf(TransmissionModes::ACKNOWLEDGED, seqNum, sourceId, destId); + PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum); FileSize progress(0x50); SECTION("Serialize") { - KeepAlivePduSerializer serializer(pduConf, progress); + KeepAlivePduCreator serializer(pduConf, progress); result = serializer.serialize(&buffer, &sz, kaBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(kaBuffer[10] == cfdp::FileDirectives::KEEP_ALIVE); + REQUIRE(result == returnvalue::OK); + REQUIRE(kaBuffer[10] == cfdp::FileDirective::KEEP_ALIVE); uint32_t fsRaw = 0; result = SerializeAdapter::deSerialize(&fsRaw, kaBuffer.data() + 11, nullptr, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(fsRaw == 0x50); REQUIRE(sz == 15); REQUIRE(serializer.getWholePduSize() == 15); @@ -37,43 +37,45 @@ TEST_CASE("Keep Alive PDU", "[KeepAlivePdu]") { buffer = kaBuffer.data(); sz = 0; result = serializer.serialize(&buffer, &sz, kaBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(serializer.getWholePduSize() == 19); REQUIRE(serializer.getPduDataFieldLen() == 9); uint64_t fsRawLarge = 0; result = SerializeAdapter::deSerialize(&fsRawLarge, kaBuffer.data() + 11, nullptr, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(fsRawLarge == 0x50); for (size_t invalidMaxSz = 0; invalidMaxSz < sz; invalidMaxSz++) { buffer = kaBuffer.data(); sz = 0; result = serializer.serialize(&buffer, &sz, invalidMaxSz, SerializeIF::Endianness::NETWORK); - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); + REQUIRE(result != returnvalue::OK); } } SECTION("Deserialize") { - KeepAlivePduSerializer serializer(pduConf, progress); + KeepAlivePduCreator serializer(pduConf, progress); result = serializer.serialize(&buffer, &sz, kaBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); // Set another file size progress.setFileSize(200, false); - KeepAlivePduDeserializer deserializer(kaBuffer.data(), kaBuffer.size(), progress); - result = deserializer.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - auto& progRef = deserializer.getProgress(); + KeepAlivePduReader reader(kaBuffer.data(), kaBuffer.size(), progress); + result = reader.parseData(); + REQUIRE(result == returnvalue::OK); + auto& progRef = reader.getProgress(); // Should have been overwritten REQUIRE(progRef.getSize() == 0x50); - sz = deserializer.getWholePduSize(); + sz = reader.getWholePduSize(); // invalid max size for (size_t invalidMaxSz = 0; invalidMaxSz < sz; invalidMaxSz++) { - deserializer.setData(kaBuffer.data(), invalidMaxSz); - result = deserializer.parseData(); - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); + ReturnValue_t setResult = reader.setReadOnlyData(kaBuffer.data(), invalidMaxSz); + if (setResult == returnvalue::OK) { + result = reader.parseData(); + REQUIRE(result != returnvalue::OK); + } } } } diff --git a/tests/src/fsfw_tests/unit/cfdp/testMetadataPdu.cpp b/unittests/cfdp/pdu/testMetadataPdu.cpp similarity index 73% rename from tests/src/fsfw_tests/unit/cfdp/testMetadataPdu.cpp rename to unittests/cfdp/pdu/testMetadataPdu.cpp index 331d64a9..a9f8bf86 100644 --- a/tests/src/fsfw_tests/unit/cfdp/testMetadataPdu.cpp +++ b/unittests/cfdp/pdu/testMetadataPdu.cpp @@ -1,28 +1,27 @@ -#include - #include #include +#include -#include "fsfw/cfdp/pdu/MetadataPduDeserializer.h" -#include "fsfw/cfdp/pdu/MetadataPduSerializer.h" +#include "fsfw/cfdp/pdu/MetadataPduCreator.h" +#include "fsfw/cfdp/pdu/MetadataPduReader.h" #include "fsfw/cfdp/tlv/FilestoreResponseTlv.h" +#include "fsfw/cfdp/tlv/MessageToUserTlv.h" #include "fsfw/globalfunctions/arrayprinter.h" -TEST_CASE("Metadata PDU", "[MetadataPdu]") { +TEST_CASE("Metadata PDU", "[cfdp][pdu]") { using namespace cfdp; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; std::array mdBuffer = {}; uint8_t* buffer = mdBuffer.data(); size_t sz = 0; EntityId destId(WidthInBytes::TWO_BYTES, 2); TransactionSeqNum seqNum(WidthInBytes::TWO_BYTES, 15); EntityId sourceId(WidthInBytes::TWO_BYTES, 1); - PduConfig pduConf(TransmissionModes::ACKNOWLEDGED, seqNum, sourceId, destId); + PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum); std::string firstFileName = "hello.txt"; - cfdp::Lv sourceFileName(reinterpret_cast(firstFileName.data()), - firstFileName.size()); - cfdp::Lv destFileName(nullptr, 0); + cfdp::StringLv sourceFileName(firstFileName); + cfdp::StringLv destFileName; FileSize fileSize(35); MetadataInfo info(false, ChecksumType::MODULAR, fileSize, sourceFileName, destFileName); @@ -39,21 +38,21 @@ TEST_CASE("Metadata PDU", "[MetadataPdu]") { REQUIRE(options[1]->getSerializedSize() == 5); SECTION("Serialize") { - MetadataPduSerializer serializer(pduConf, info); + MetadataPduCreator serializer(pduConf, info); result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(serializer.getWholePduSize() == 27); REQUIRE(info.getSourceFileName().getSerializedSize() == 10); REQUIRE(info.getDestFileName().getSerializedSize() == 1); REQUIRE(info.getSerializedSize() == 16); REQUIRE((mdBuffer[1] << 8 | mdBuffer[2]) == 17); - REQUIRE(mdBuffer[10] == FileDirectives::METADATA); + REQUIRE(mdBuffer[10] == FileDirective::METADATA); // no closure requested and checksum type is modular => 0x00 REQUIRE(mdBuffer[11] == 0x00); uint32_t fileSizeRaw = 0; result = SerializeAdapter::deSerialize(&fileSizeRaw, mdBuffer.data() + 12, nullptr, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(fileSizeRaw == 35); REQUIRE(mdBuffer[16] == 9); REQUIRE(mdBuffer[17] == 'h'); @@ -68,11 +67,10 @@ TEST_CASE("Metadata PDU", "[MetadataPdu]") { REQUIRE(mdBuffer[26] == 0); std::string otherFileName = "hello2.txt"; - cfdp::Lv otherFileNameLv(reinterpret_cast(otherFileName.data()), - otherFileName.size()); + cfdp::StringLv otherFileNameLv(otherFileName.data(), otherFileName.size()); info.setSourceFileName(otherFileNameLv); size_t sizeOfOptions = options.size(); - info.setOptionsArray(options.data(), &sizeOfOptions, &sizeOfOptions); + info.setOptionsArray(options.data(), sizeOfOptions, sizeOfOptions); REQUIRE(info.getMaxOptionsLen() == 2); info.setMaxOptionsLen(3); REQUIRE(info.getMaxOptionsLen() == 3); @@ -83,7 +81,7 @@ TEST_CASE("Metadata PDU", "[MetadataPdu]") { serializer.updateDirectiveFieldLen(); result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE((mdBuffer[1] << 8 | mdBuffer[2]) == 37); auto checksumType = static_cast(mdBuffer[11] & 0x0f); REQUIRE(checksumType == cfdp::ChecksumType::CRC_32C); @@ -115,22 +113,22 @@ TEST_CASE("Metadata PDU", "[MetadataPdu]") { } SECTION("Deserialize") { - MetadataPduSerializer serializer(pduConf, info); + MetadataPduCreator serializer(pduConf, info); result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); - MetadataPduDeserializer deserializer(mdBuffer.data(), mdBuffer.size(), info); + MetadataPduReader deserializer(mdBuffer.data(), mdBuffer.size(), info); result = deserializer.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); size_t fullSize = deserializer.getWholePduSize(); for (size_t maxSz = 0; maxSz < fullSize; maxSz++) { - MetadataPduDeserializer invalidSzDeser(mdBuffer.data(), maxSz, info); + MetadataPduReader invalidSzDeser(mdBuffer.data(), maxSz, info); result = invalidSzDeser.parseData(); - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); + REQUIRE(result != returnvalue::OK); } size_t sizeOfOptions = options.size(); size_t maxSize = 4; - info.setOptionsArray(options.data(), &sizeOfOptions, &maxSize); + info.setOptionsArray(options.data(), sizeOfOptions, maxSize); REQUIRE(info.getOptionsLen() == 2); info.setChecksumType(cfdp::ChecksumType::CRC_32C); info.setClosureRequested(true); @@ -140,14 +138,14 @@ TEST_CASE("Metadata PDU", "[MetadataPdu]") { info.setSourceFileName(sourceFileName); result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); - MetadataPduDeserializer deserializer2(mdBuffer.data(), mdBuffer.size(), info); + MetadataPduReader deserializer2(mdBuffer.data(), mdBuffer.size(), info); result = deserializer2.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(options[0]->getType() == cfdp::TlvTypes::FILESTORE_RESPONSE); + REQUIRE(result == returnvalue::OK); + REQUIRE(options[0]->getType() == cfdp::TlvType::FILESTORE_RESPONSE); REQUIRE(options[0]->getSerializedSize() == 14); - REQUIRE(options[1]->getType() == cfdp::TlvTypes::MSG_TO_USER); + REQUIRE(options[1]->getType() == cfdp::TlvType::MSG_TO_USER); REQUIRE(options[1]->getSerializedSize() == 5); for (size_t invalidFieldLen = 0; invalidFieldLen < 36; invalidFieldLen++) { @@ -162,18 +160,20 @@ TEST_CASE("Metadata PDU", "[MetadataPdu]") { } // This is the precise length where there are no options or one option if (invalidFieldLen != 17 and invalidFieldLen != 31) { - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); + REQUIRE(result != returnvalue::OK); } } mdBuffer[1] = (36 >> 8) & 0xff; mdBuffer[2] = 36 & 0xff; - info.setOptionsArray(nullptr, nullptr, nullptr); + info.setOptionsArray(nullptr, std::nullopt, std::nullopt); REQUIRE(deserializer2.parseData() == cfdp::METADATA_CANT_PARSE_OPTIONS); - info.setOptionsArray(options.data(), &sizeOfOptions, nullptr); + info.setOptionsArray(options.data(), sizeOfOptions, std::nullopt); for (size_t maxSz = 0; maxSz < 46; maxSz++) { - MetadataPduDeserializer invalidSzDeser(mdBuffer.data(), maxSz, info); - result = invalidSzDeser.parseData(); - REQUIRE(result == SerializeIF::STREAM_TOO_SHORT); + MetadataPduReader invalidSzDeser(mdBuffer.data(), maxSz, info); + if (not invalidSzDeser.isNull()) { + result = invalidSzDeser.parseData(); + REQUIRE(result == SerializeIF::STREAM_TOO_SHORT); + } } } } diff --git a/tests/src/fsfw_tests/unit/cfdp/testNakPdu.cpp b/unittests/cfdp/pdu/testNakPdu.cpp similarity index 78% rename from tests/src/fsfw_tests/unit/cfdp/testNakPdu.cpp rename to unittests/cfdp/pdu/testNakPdu.cpp index 38b45300..7974dab1 100644 --- a/tests/src/fsfw_tests/unit/cfdp/testNakPdu.cpp +++ b/unittests/cfdp/pdu/testNakPdu.cpp @@ -1,43 +1,43 @@ #include #include -#include "fsfw/cfdp/pdu/NakPduDeserializer.h" -#include "fsfw/cfdp/pdu/NakPduSerializer.h" +#include "fsfw/cfdp/pdu/NakPduCreator.h" +#include "fsfw/cfdp/pdu/NakPduReader.h" #include "fsfw/cfdp/pdu/PduConfig.h" #include "fsfw/globalfunctions/arrayprinter.h" -TEST_CASE("NAK PDU", "[NakPdu]") { +TEST_CASE("NAK PDU", "[cfdp][pdu]") { using namespace cfdp; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; std::array nakBuffer = {}; uint8_t* buffer = nakBuffer.data(); size_t sz = 0; EntityId destId(WidthInBytes::TWO_BYTES, 2); TransactionSeqNum seqNum(WidthInBytes::TWO_BYTES, 15); EntityId sourceId(WidthInBytes::TWO_BYTES, 1); - PduConfig pduConf(TransmissionModes::ACKNOWLEDGED, seqNum, sourceId, destId); + PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum); FileSize startOfScope(50); FileSize endOfScope(1050); NakInfo info(startOfScope, endOfScope); SECTION("Serializer") { - NakPduSerializer serializer(pduConf, info); + NakPduCreator serializer(pduConf, info); result = serializer.serialize(&buffer, &sz, nakBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(serializer.getSerializedSize() == 19); - REQUIRE(serializer.FileDirectiveSerializer::getSerializedSize() == 11); + REQUIRE(serializer.FileDirectiveCreator::getSerializedSize() == 11); REQUIRE(sz == 19); REQUIRE(serializer.getPduDataFieldLen() == 9); REQUIRE(((nakBuffer[1] << 8) | nakBuffer[2]) == 0x09); - REQUIRE(nakBuffer[10] == cfdp::FileDirectives::NAK); + REQUIRE(nakBuffer[10] == cfdp::FileDirective::NAK); uint32_t scope = 0; result = SerializeAdapter::deSerialize(&scope, nakBuffer.data() + 11, nullptr, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(scope == 50); result = SerializeAdapter::deSerialize(&scope, nakBuffer.data() + 15, nullptr, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(scope == 1050); NakInfo::SegmentRequest segReq0(cfdp::FileSize(2020), cfdp::FileSize(2520)); @@ -50,26 +50,26 @@ TEST_CASE("NAK PDU", "[NakPdu]") { size_t sz = 0; serializer.updateDirectiveFieldLen(); result = serializer.serialize(&buffer, &sz, nakBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(serializer.getSerializedSize() == 35); REQUIRE(serializer.getPduDataFieldLen() == 25); REQUIRE(((nakBuffer[1] << 8) | nakBuffer[2]) == 25); uint32_t segReqScopes = 0; result = SerializeAdapter::deSerialize(&segReqScopes, nakBuffer.data() + 19, nullptr, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(segReqScopes == 2020); result = SerializeAdapter::deSerialize(&segReqScopes, nakBuffer.data() + 23, nullptr, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(segReqScopes == 2520); result = SerializeAdapter::deSerialize(&segReqScopes, nakBuffer.data() + 27, nullptr, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(segReqScopes == 2932); result = SerializeAdapter::deSerialize(&segReqScopes, nakBuffer.data() + 31, nullptr, SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(segReqScopes == 3021); for (size_t maxSz = 0; maxSz < 35; maxSz++) { @@ -87,15 +87,15 @@ TEST_CASE("NAK PDU", "[NakPdu]") { } SECTION("Deserializer") { - NakPduSerializer serializer(pduConf, info); + NakPduCreator serializer(pduConf, info); result = serializer.serialize(&buffer, &sz, nakBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); info.getStartOfScope().setFileSize(0, false); info.getEndOfScope().setFileSize(0, false); - NakPduDeserializer deserializer(nakBuffer.data(), nakBuffer.size(), info); + NakPduReader deserializer(nakBuffer.data(), nakBuffer.size(), info); result = deserializer.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(deserializer.getWholePduSize() == 19); REQUIRE(info.getStartOfScope().getSize() == 50); REQUIRE(info.getEndOfScope().getSize() == 1050); @@ -110,11 +110,11 @@ TEST_CASE("NAK PDU", "[NakPdu]") { size_t sz = 0; serializer.updateDirectiveFieldLen(); result = serializer.serialize(&buffer, &sz, nakBuffer.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); - NakPduDeserializer deserializeWithSegReqs(nakBuffer.data(), nakBuffer.size(), info); + NakPduReader deserializeWithSegReqs(nakBuffer.data(), nakBuffer.size(), info); result = deserializeWithSegReqs.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); NakInfo::SegmentRequest* segReqsPtr = nullptr; size_t readSegReqs = 0; info.getSegmentRequests(&segReqsPtr, &readSegReqs, nullptr); @@ -126,14 +126,14 @@ TEST_CASE("NAK PDU", "[NakPdu]") { REQUIRE(deserializeWithSegReqs.getPduDataFieldLen() == 25); REQUIRE(info.getSegmentRequestsLen() == 2); for (size_t idx = 0; idx < 34; idx++) { - NakPduDeserializer faultyDeserializer(nakBuffer.data(), idx, info); + NakPduReader faultyDeserializer(nakBuffer.data(), idx, info); result = faultyDeserializer.parseData(); - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); + REQUIRE(result != returnvalue::OK); } for (size_t pduFieldLen = 0; pduFieldLen < 25; pduFieldLen++) { nakBuffer[1] = (pduFieldLen >> 8) & 0xff; nakBuffer[2] = pduFieldLen & 0xff; - NakPduDeserializer faultyDeserializer(nakBuffer.data(), nakBuffer.size(), info); + NakPduReader faultyDeserializer(nakBuffer.data(), nakBuffer.size(), info); result = faultyDeserializer.parseData(); if (pduFieldLen == 9) { REQUIRE(info.getSegmentRequestsLen() == 0); @@ -143,7 +143,7 @@ TEST_CASE("NAK PDU", "[NakPdu]") { REQUIRE(info.getSegmentRequestsLen() == 2); } if (pduFieldLen != 9 and pduFieldLen != 17 and pduFieldLen != 25) { - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); + REQUIRE(result != returnvalue::OK); } } info.setMaxSegmentRequestLen(5); diff --git a/tests/src/fsfw_tests/unit/cfdp/testPromptPdu.cpp b/unittests/cfdp/pdu/testPromptPdu.cpp similarity index 58% rename from tests/src/fsfw_tests/unit/cfdp/testPromptPdu.cpp rename to unittests/cfdp/pdu/testPromptPdu.cpp index 9f406aec..6032f44e 100644 --- a/tests/src/fsfw_tests/unit/cfdp/testPromptPdu.cpp +++ b/unittests/cfdp/pdu/testPromptPdu.cpp @@ -1,65 +1,69 @@ #include #include -#include "fsfw/cfdp/pdu/PromptPduDeserializer.h" -#include "fsfw/cfdp/pdu/PromptPduSerializer.h" +#include "fsfw/cfdp/pdu/PromptPduCreator.h" +#include "fsfw/cfdp/pdu/PromptPduReader.h" #include "fsfw/globalfunctions/arrayprinter.h" -TEST_CASE("Prompt PDU", "[PromptPdu]") { +TEST_CASE("Prompt PDU", "[cfdp][pdu]") { using namespace cfdp; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; std::array rawBuf = {}; uint8_t* buffer = rawBuf.data(); size_t sz = 0; EntityId destId(WidthInBytes::TWO_BYTES, 2); TransactionSeqNum seqNum(WidthInBytes::TWO_BYTES, 15); EntityId sourceId(WidthInBytes::TWO_BYTES, 1); - PduConfig pduConf(TransmissionModes::ACKNOWLEDGED, seqNum, sourceId, destId); + PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum); SECTION("Serialize") { - PromptPduSerializer serializer(pduConf, cfdp::PromptResponseRequired::PROMPT_KEEP_ALIVE); + PromptPduCreator serializer(pduConf, cfdp::PromptResponseRequired::PROMPT_KEEP_ALIVE); result = serializer.serialize(&buffer, &sz, rawBuf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(serializer.getWholePduSize() == 12); REQUIRE(sz == 12); REQUIRE(serializer.getPduDataFieldLen() == 2); - REQUIRE(rawBuf[10] == FileDirectives::PROMPT); - REQUIRE((rawBuf[sz - 1] >> 7) & 0x01 == cfdp::PromptResponseRequired::PROMPT_KEEP_ALIVE); + REQUIRE(rawBuf[10] == FileDirective::PROMPT); + REQUIRE(((rawBuf[sz - 1] >> 7) & 0x01) == cfdp::PromptResponseRequired::PROMPT_KEEP_ALIVE); for (size_t invalidMaxSz = 0; invalidMaxSz < sz; invalidMaxSz++) { uint8_t* buffer = rawBuf.data(); size_t sz = 0; result = serializer.serialize(&buffer, &sz, invalidMaxSz, SerializeIF::Endianness::NETWORK); - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); + REQUIRE(result != returnvalue::OK); } for (size_t invalidSz = 1; invalidSz < sz; invalidSz++) { size_t locSz = invalidSz; uint8_t* buffer = rawBuf.data(); result = serializer.serialize(&buffer, &locSz, sz, SerializeIF::Endianness::NETWORK); - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); + REQUIRE(result != returnvalue::OK); } } SECTION("Deserialize") { - PromptPduSerializer serializer(pduConf, cfdp::PromptResponseRequired::PROMPT_KEEP_ALIVE); + PromptPduCreator serializer(pduConf, cfdp::PromptResponseRequired::PROMPT_KEEP_ALIVE); result = serializer.serialize(&buffer, &sz, rawBuf.size(), SerializeIF::Endianness::NETWORK); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); - PromptPduDeserializer deserializer(rawBuf.data(), rawBuf.size()); + PromptPduReader deserializer(rawBuf.data(), rawBuf.size()); result = deserializer.parseData(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(deserializer.getPromptResponseRequired() == cfdp::PromptResponseRequired::PROMPT_KEEP_ALIVE); sz = deserializer.getWholePduSize(); + // Set invalid size rawBuf[2] = 1; result = deserializer.parseData(); + size_t sz2 = deserializer.getWholePduSize(); REQUIRE(result == SerializeIF::STREAM_TOO_SHORT); rawBuf[2] = 2; for (size_t invalidMaxSz = 0; invalidMaxSz < sz; invalidMaxSz++) { - deserializer.setData(rawBuf.data(), invalidMaxSz); - result = deserializer.parseData(); - REQUIRE(result != HasReturnvaluesIF::RETURN_OK); + ReturnValue_t setResult = deserializer.setReadOnlyData(rawBuf.data(), invalidMaxSz); + if (setResult == returnvalue::OK) { + result = deserializer.parseData(); + REQUIRE(result != returnvalue::OK); + } } } } diff --git a/unittests/cfdp/testCfdp.cpp b/unittests/cfdp/testCfdp.cpp new file mode 100644 index 00000000..467b5b2d --- /dev/null +++ b/unittests/cfdp/testCfdp.cpp @@ -0,0 +1,105 @@ +#include +#include +#include + +#include "fsfw/cfdp/FileSize.h" +#include "fsfw/cfdp/pdu/FileDirectiveCreator.h" +#include "fsfw/cfdp/pdu/FileDirectiveReader.h" +#include "fsfw/globalfunctions/arrayprinter.h" +#include "fsfw/serialize/SerializeAdapter.h" + +TEST_CASE("CFDP Base", "[cfdp]") { + using namespace cfdp; + std::array serBuf{}; + ReturnValue_t result; + cfdp::TransactionSeqNum seqNum = TransactionSeqNum(cfdp::WidthInBytes::ONE_BYTE, 2); + cfdp::EntityId sourceId = EntityId(cfdp::WidthInBytes::ONE_BYTE, 0); + cfdp::EntityId destId = EntityId(cfdp::WidthInBytes::ONE_BYTE, 1); + PduConfig pduConf = + PduConfig(sourceId, destId, cfdp::TransmissionMode::ACKNOWLEDGED, seqNum, false); + uint8_t* serTarget = serBuf.data(); + const uint8_t* deserTarget = serTarget; + size_t serSize = 0; + + SECTION("File Directive") { + auto fdSer = FileDirectiveCreator(pduConf, FileDirective::ACK, 4); + REQUIRE(fdSer.getSerializedSize() == 8); + serTarget = serBuf.data(); + serSize = 0; + result = fdSer.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + // Only version bits are set + REQUIRE(serBuf[0] == 0b00100000); + // PDU data field length is 5 (4 + Directive code octet) + REQUIRE(serBuf[1] == 0); + REQUIRE(serBuf[2] == 5); + // Entity and Transaction Sequence number are 1 byte large, value minus one is stored + REQUIRE(serBuf[3] == 0b00000000); + // Source ID + REQUIRE(serBuf[4] == 0); + // Transaction Seq Number + REQUIRE(serBuf[5] == 2); + // Dest ID + REQUIRE(serBuf[6] == 1); + REQUIRE(serBuf[7] == FileDirective::ACK); + + serTarget = serBuf.data(); + size_t deserSize = 20; + serSize = 0; + REQUIRE(fdSer.deSerialize(&deserTarget, &deserSize, SerializeIF::Endianness::NETWORK) == + returnvalue::FAILED); + REQUIRE(fdSer.serialize(nullptr, nullptr, 85, SerializeIF::Endianness::NETWORK) == + returnvalue::FAILED); + for (uint8_t idx = 0; idx < 8; idx++) { + serTarget = serBuf.data(); + serSize = 0; + REQUIRE(fdSer.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::NETWORK) == + SerializeIF::BUFFER_TOO_SHORT); + } + + deserTarget = serBuf.data(); + deserSize = 0; + auto fdDeser = FileDirectiveReader(deserTarget, serBuf.size()); + REQUIRE(fdDeser.getEndianness() == SerializeIF::Endianness::NETWORK); + fdDeser.setEndianness(SerializeIF::Endianness::MACHINE); + REQUIRE(fdDeser.getEndianness() == SerializeIF::Endianness::MACHINE); + fdDeser.setEndianness(SerializeIF::Endianness::NETWORK); + REQUIRE(fdDeser.parseData() == returnvalue::OK); + REQUIRE(fdDeser.getFileDirective() == FileDirective::ACK); + REQUIRE(fdDeser.getPduDataFieldLen() == 5); + REQUIRE(fdDeser.getHeaderSize() == 8); + REQUIRE(fdDeser.getPduType() == cfdp::PduType::FILE_DIRECTIVE); + + serBuf[7] = 0xff; + // Invalid file directive + REQUIRE(fdDeser.parseData() == cfdp::INVALID_DIRECTIVE_FIELD); + } + + SECTION("File Size") { + std::array fssBuf = {}; + uint8_t* buffer = fssBuf.data(); + size_t size = 0; + cfdp::FileSize fss; + REQUIRE(fss.getSize() == 0); + fss.setFileSize(0x20, false); + result = fss.serialize(&buffer, &size, fssBuf.size(), SerializeIF::Endianness::MACHINE); + REQUIRE(result == returnvalue::OK); + uint32_t fileSize = 0; + result = SerializeAdapter::deSerialize(&fileSize, fssBuf.data(), nullptr, + SerializeIF::Endianness::MACHINE); + REQUIRE(result == returnvalue::OK); + REQUIRE(fileSize == 0x20); + } + + SECTION("Var Length Field") { + VarLenField defaultField; + CHECK(defaultField.getValue() == 0); + CHECK(defaultField.getWidth() == WidthInBytes::ONE_BYTE); + VarLenField explicitField(WidthInBytes::FOUR_BYTES, 12); + CHECK(explicitField.getWidth() == WidthInBytes::FOUR_BYTES); + CHECK(explicitField.getValue() == 12); + VarLenField fromUnsignedByteField(UnsignedByteField(12)); + CHECK(fromUnsignedByteField.getWidth() == WidthInBytes::TWO_BYTES); + CHECK(fromUnsignedByteField.getValue() == 12); + } +} diff --git a/unittests/cfdp/testLvs.cpp b/unittests/cfdp/testLvs.cpp new file mode 100644 index 00000000..22094568 --- /dev/null +++ b/unittests/cfdp/testLvs.cpp @@ -0,0 +1,116 @@ +#include +#include + +#include "fsfw/cfdp.h" +#include "fsfw/cfdp/VarLenFields.h" + +TEST_CASE("CFDP LV", "[cfdp][lv]") { + using namespace cfdp; + ReturnValue_t result = returnvalue::OK; + std::array rawBuf{}; + uint8_t* serPtr = rawBuf.data(); + const uint8_t* deserPtr = rawBuf.data(); + size_t deserSize = 0; + cfdp::EntityId sourceId = EntityId(cfdp::WidthInBytes::TWO_BYTES, 0x0ff0); + + SECTION("LV Serialization") { + std::array lvRawBuf{}; + serPtr = lvRawBuf.data(); + REQUIRE(sourceId.serialize(&serPtr, &deserSize, lvRawBuf.size(), + SerializeIF::Endianness::NETWORK) == returnvalue::OK); + REQUIRE(deserSize == 2); + + auto lv = cfdp::Lv(lvRawBuf.data(), 2); + REQUIRE(lv.getSerializedSize() == 3); + + SECTION("Copy") { + auto lvCopy = cfdp::Lv(lv); + REQUIRE(lvCopy.getSerializedSize() == 3); + REQUIRE(lv.getValue(nullptr) == lvCopy.getValue(nullptr)); + } + + serPtr = rawBuf.data(); + deserSize = 0; + REQUIRE(lv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK) == + returnvalue::OK); + REQUIRE(deserSize == 3); + REQUIRE(rawBuf[0] == 2); + uint16_t sourceIdRaw = 0; + REQUIRE(SerializeAdapter::deSerialize(&sourceIdRaw, rawBuf.data() + 1, &deserSize, + SerializeIF::Endianness::BIG) == returnvalue::OK); + REQUIRE(sourceIdRaw == 0x0ff0); + } + + SECTION("Empty Serialization") { + auto lvEmpty = Lv(); + REQUIRE(lvEmpty.getSerializedSize() == 1); + serPtr = rawBuf.data(); + deserSize = 0; + result = + lvEmpty.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + REQUIRE(deserSize == 1); + deserPtr = rawBuf.data(); + result = lvEmpty.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::BIG); + REQUIRE(result == returnvalue::OK); + REQUIRE(lvEmpty.getSerializedSize() == 1); + } + + SECTION("Uninit LV") { + std::array lvRawBuf{}; + serPtr = lvRawBuf.data(); + REQUIRE(sourceId.serialize(&serPtr, &deserSize, lvRawBuf.size(), + SerializeIF::Endianness::NETWORK) == returnvalue::OK); + auto lv = cfdp::Lv(lvRawBuf.data(), 2); + serPtr = rawBuf.data(); + deserSize = 0; + result = lv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + Lv uninitLv; + deserPtr = rawBuf.data(); + deserSize = 3; + result = uninitLv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::BIG); + REQUIRE(result == returnvalue::OK); + REQUIRE(uninitLv.getSerializedSize() == 3); + const uint8_t* storedValue = uninitLv.getValue(nullptr); + uint16_t sourceIdRaw = 0; + REQUIRE(SerializeAdapter::deSerialize(&sourceIdRaw, storedValue, &deserSize, + SerializeIF::Endianness::BIG) == returnvalue::OK); + REQUIRE(sourceIdRaw == 0x0ff0); + } + + SECTION("Invalid Input") { + Lv uninitLv; + REQUIRE(uninitLv.deSerialize(nullptr, nullptr, SerializeIF::Endianness::BIG) == + returnvalue::FAILED); + serPtr = rawBuf.data(); + deserSize = 0; + REQUIRE(uninitLv.serialize(&serPtr, &deserSize, 0, SerializeIF::Endianness::BIG) == + SerializeIF::BUFFER_TOO_SHORT); + REQUIRE(uninitLv.serialize(nullptr, nullptr, 12, SerializeIF::Endianness::BIG)); + deserSize = 0; + REQUIRE(uninitLv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::BIG) == + SerializeIF::STREAM_TOO_SHORT); + } + + SECTION("String LV String") { + std::string filename = "hello.txt"; + StringLv sourceFileName(filename); + REQUIRE(sourceFileName.getSerializedSize() == 1 + filename.size()); + REQUIRE(sourceFileName.serializeBe(rawBuf.data(), deserSize, rawBuf.size()) == returnvalue::OK); + REQUIRE(rawBuf[0] == filename.size()); + std::string filenameFromRaw(reinterpret_cast(rawBuf.data() + 1), filename.size()); + REQUIRE(filenameFromRaw == filename); + } + + SECTION("String LV Const Char") { + const char filename[] = "hello.txt"; + StringLv sourceFileName(filename, sizeof(filename) - 1); + REQUIRE(sourceFileName.getSerializedSize() == 1 + sizeof(filename) - 1); + REQUIRE(sourceFileName.serializeBe(rawBuf.data(), deserSize, rawBuf.size()) == returnvalue::OK); + REQUIRE(rawBuf[0] == sizeof(filename) - 1); + rawBuf[deserSize] = '\0'; + const char* filenameFromRaw = reinterpret_cast(rawBuf.data() + 1); + REQUIRE(std::strcmp(filename, filenameFromRaw) == 0); + } +} diff --git a/unittests/cfdp/testOtherTlvs.cpp b/unittests/cfdp/testOtherTlvs.cpp new file mode 100644 index 00000000..88413195 --- /dev/null +++ b/unittests/cfdp/testOtherTlvs.cpp @@ -0,0 +1,137 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "fsfw/cfdp/pdu/PduConfig.h" +#include "fsfw/cfdp/tlv/Lv.h" +#include "fsfw/cfdp/tlv/Tlv.h" +#include "fsfw/globalfunctions/arrayprinter.h" + +TEST_CASE("CFDP Other TLVs", "[cfdp][tlv]") { + using namespace cfdp; + ReturnValue_t result; + std::array rawBuf{}; + uint8_t* serPtr = rawBuf.data(); + const uint8_t* deserPtr = rawBuf.data(); + size_t deserSize = 0; + cfdp::EntityId sourceId = EntityId(cfdp::WidthInBytes::TWO_BYTES, 0x0ff0); + + SECTION("Filestore Response TLV") { + std::string name = "hello.txt"; + cfdp::StringLv firstName(name); + std::string name2 = "hello2.txt"; + cfdp::StringLv secondName(name2); + std::string msg = "12345"; + cfdp::Lv fsMsg(reinterpret_cast(msg.data()), msg.size()); + FilestoreResponseTlv response(cfdp::FilestoreActionCode::APPEND_FILE, cfdp::FSR_SUCCESS, + firstName, &fsMsg); + response.setSecondFileName(&secondName); + REQUIRE(response.getLengthField() == 10 + 11 + 6 + 1); + REQUIRE(response.getSerializedSize() == response.getLengthField() + 2); + + cfdp::Tlv rawResponse; + std::array serBuf = {}; + result = response.convertToTlv(rawResponse, serBuf.data(), serBuf.size(), + SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + REQUIRE(rawResponse.getType() == cfdp::TlvType::FILESTORE_RESPONSE); + cfdp::StringLv emptyMsg; + cfdp::StringLv emptySecondName; + FilestoreResponseTlv emptyTlv(firstName, &emptyMsg); + emptyTlv.setSecondFileName(&emptySecondName); + result = emptyTlv.deSerialize(rawResponse, SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + REQUIRE(emptyTlv.getActionCode() == cfdp::FilestoreActionCode::APPEND_FILE); + REQUIRE(emptyTlv.getStatusCode() == cfdp::FSR_SUCCESS); + size_t firstNameLen = 0; + const char* firstNamePtr = + reinterpret_cast(emptyTlv.getFirstFileName().getValue(&firstNameLen)); + auto helloString = std::string(firstNamePtr, firstNameLen); + REQUIRE(helloString == "hello.txt"); + } + + SECTION("Filestore Request TLV") { + std::string name = "hello.txt"; + cfdp::StringLv firstName(name); + std::string name2 = "hello2.txt"; + cfdp::StringLv secondName(name2); + FilestoreRequestTlv request(cfdp::FilestoreActionCode::APPEND_FILE, firstName); + + // second name not set yet + REQUIRE(request.getLengthField() == 10 + 1); + REQUIRE(request.getSerializedSize() == request.getLengthField() + 2); + + std::array serBuf = {}; + uint8_t* ptr = serBuf.data(); + size_t sz = 0; + result = request.serialize(&ptr, &sz, serBuf.size(), SerializeIF::Endianness::NETWORK); + REQUIRE(result == cfdp::FILESTORE_REQUIRES_SECOND_FILE); + + ptr = serBuf.data(); + sz = 0; + request.setSecondFileName(&secondName); + size_t expectedSz = request.getLengthField(); + REQUIRE(expectedSz == 10 + 11 + 1); + REQUIRE(request.getSerializedSize() == expectedSz + 2); + result = request.serialize(&ptr, &sz, serBuf.size(), SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + REQUIRE(sz == expectedSz + 2); + + FilestoreRequestTlv emptyRequest(firstName); + emptyRequest.setSecondFileName(&secondName); + const uint8_t* constptr = serBuf.data(); + result = emptyRequest.deSerialize(&constptr, &sz, SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + + cfdp::Tlv rawRequest; + ptr = serBuf.data(); + sz = 0; + result = request.convertToTlv(rawRequest, serBuf.data(), serBuf.size(), + SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + REQUIRE(rawRequest.getType() == cfdp::TlvType::FILESTORE_REQUEST); + + emptyRequest.setActionCode(cfdp::FilestoreActionCode::DELETE_FILE); + result = emptyRequest.deSerialize(rawRequest, SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + REQUIRE(emptyRequest.getType() == cfdp::TlvType::FILESTORE_REQUEST); + REQUIRE(emptyRequest.getActionCode() == cfdp::FilestoreActionCode::APPEND_FILE); + } + + SECTION("Other") { + MessageToUserTlv emptyTlv; + uint8_t flowLabel = 1; + FlowLabelTlv flowLabelTlv(&flowLabel, 1); + + FaultHandlerOverrideTlv faultOverrideTlv(cfdp::ConditionCode::FILESTORE_REJECTION, + cfdp::FaultHandlerCode::NOTICE_OF_CANCELLATION); + size_t sz = 0; + result = + faultOverrideTlv.serialize(&serPtr, &sz, rawBuf.size(), SerializeIF::Endianness::NETWORK); + REQUIRE(faultOverrideTlv.getSerializedSize() == 3); + REQUIRE(sz == 3); + REQUIRE(result == returnvalue::OK); + + FaultHandlerOverrideTlv emptyOverrideTlv; + result = emptyOverrideTlv.deSerialize(&deserPtr, &sz, SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + + EntityId entId(cfdp::WidthInBytes::TWO_BYTES, 0x42); + EntityId emptyId; + EntityIdTlv idTlv(emptyId); + serPtr = rawBuf.data(); + result = idTlv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK); + cfdp::Tlv rawTlv(cfdp::TlvType::ENTITY_ID, rawBuf.data() + 2, 2); + REQUIRE(result == returnvalue::OK); + deserPtr = rawBuf.data(); + result = idTlv.deSerialize(rawTlv, SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + } +} diff --git a/unittests/cfdp/testTlv.cpp b/unittests/cfdp/testTlv.cpp new file mode 100644 index 00000000..979bfac5 --- /dev/null +++ b/unittests/cfdp/testTlv.cpp @@ -0,0 +1,128 @@ +#include +#include + +#include "fsfw/cfdp.h" +#include "fsfw/cfdp/VarLenFields.h" + +TEST_CASE("CFDP TLV", "[cfdp][tlv]") { + using namespace cfdp; + ReturnValue_t result; + std::array rawBuf{}; + uint8_t* serPtr = rawBuf.data(); + const uint8_t* deserPtr = rawBuf.data(); + size_t deserSize = 0; + cfdp::EntityId sourceId = EntityId(cfdp::WidthInBytes::TWO_BYTES, 0x0ff0); + + SECTION("Entity ID Serialization") { + REQUIRE(sourceId.serialize(&serPtr, &deserSize, rawBuf.size(), + SerializeIF::Endianness::NETWORK) == returnvalue::OK); + REQUIRE(deserSize == 2); + } + + SECTION("TLV Serialization") { + std::array tlvBuf{}; + REQUIRE(sourceId.serializeBe(tlvBuf.data(), deserSize, tlvBuf.size()) == returnvalue::OK); + auto tlv = Tlv(TlvType::ENTITY_ID, tlvBuf.data(), deserSize); + REQUIRE(tlv.getSerializedSize() == 4); + REQUIRE(tlv.getLengthField() == 2); + deserSize = 0; + REQUIRE(tlv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK) == + returnvalue::OK); + REQUIRE(deserSize == 4); + REQUIRE(rawBuf[0] == TlvType::ENTITY_ID); + REQUIRE(rawBuf[1] == 2); + uint16_t entityId = 0; + REQUIRE(SerializeAdapter::deSerialize(&entityId, rawBuf.data() + 2, &deserSize, + SerializeIF::Endianness::NETWORK) == returnvalue::OK); + REQUIRE(entityId == 0x0ff0); + } + + SECTION("TLV Other Value") { + auto tlv = Tlv(TlvType::ENTITY_ID, rawBuf.data(), deserSize); + // Set new value + sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 12); + REQUIRE(sourceId.serialize(&serPtr, &deserSize, rawBuf.size(), + SerializeIF::Endianness::NETWORK) == returnvalue::OK); + tlv.setValue(rawBuf.data(), cfdp::WidthInBytes::FOUR_BYTES); + serPtr = rawBuf.data(); + deserSize = 0; + result = tlv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + REQUIRE(rawBuf[0] == TlvType::ENTITY_ID); + REQUIRE(rawBuf[1] == 4); + + REQUIRE(result == returnvalue::OK); + } + + SECTION("TLV Invalid") { + auto tlvInvalid = Tlv(cfdp::TlvType::INVALID_TLV, rawBuf.data(), 0); + REQUIRE(tlvInvalid.serialize(&serPtr, &deserSize, rawBuf.size(), + SerializeIF::Endianness::NETWORK) != returnvalue::OK); + tlvInvalid = Tlv(cfdp::TlvType::ENTITY_ID, nullptr, 3); + REQUIRE(tlvInvalid.serialize(&serPtr, &deserSize, rawBuf.size(), + SerializeIF::Endianness::NETWORK) != returnvalue::OK); + REQUIRE(tlvInvalid.serialize(&serPtr, &deserSize, 0, SerializeIF::Endianness::NETWORK) != + returnvalue::OK); + REQUIRE(tlvInvalid.getSerializedSize() == 0); + REQUIRE(tlvInvalid.serialize(nullptr, nullptr, 0, SerializeIF::Endianness::NETWORK) != + returnvalue::OK); + } + + SECTION("TLV Zero Length Field") { + Tlv zeroLenField(TlvType::FAULT_HANDLER, nullptr, 0); + REQUIRE(zeroLenField.getSerializedSize() == 2); + serPtr = rawBuf.data(); + deserSize = 0; + REQUIRE(zeroLenField.serialize(&serPtr, &deserSize, rawBuf.size(), + SerializeIF::Endianness::NETWORK) == returnvalue::OK); + REQUIRE(rawBuf[0] == TlvType::FAULT_HANDLER); + REQUIRE(rawBuf[1] == 0); + } + + SECTION("TLV Deserialization") { + // Serialization was tested before, generate raw data now + std::array tlvRawBuf{}; + serPtr = tlvRawBuf.data(); + result = + sourceId.serialize(&serPtr, &deserSize, tlvRawBuf.size(), SerializeIF::Endianness::NETWORK); + auto tlvSerialization = Tlv(TlvType::ENTITY_ID, tlvRawBuf.data(), deserSize); + serPtr = rawBuf.data(); + deserSize = 0; + result = tlvSerialization.serialize(&serPtr, &deserSize, rawBuf.size(), + SerializeIF::Endianness::NETWORK); + Tlv tlv; + deserPtr = rawBuf.data(); + result = tlv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + REQUIRE(tlv.getSerializedSize() == 4); + REQUIRE(tlv.getType() == TlvType::ENTITY_ID); + deserPtr = tlv.getValue(); + uint16_t entityId = 0; + deserSize = 0; + SerializeAdapter::deSerialize(&entityId, deserPtr, &deserSize, + SerializeIF::Endianness::NETWORK); + REQUIRE(entityId == 0x0ff0); + + REQUIRE(tlv.deSerialize(nullptr, nullptr, SerializeIF::Endianness::NETWORK) != returnvalue::OK); + deserPtr = rawBuf.data(); + deserSize = 0; + REQUIRE(tlv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK) == + SerializeIF::STREAM_TOO_SHORT); + // Set invalid TLV + rawBuf[0] = TlvType::INVALID_TLV; + deserSize = 4; + REQUIRE(tlv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK) != + returnvalue::OK); + + Tlv zeroLenField(TlvType::FAULT_HANDLER, nullptr, 0); + serPtr = rawBuf.data(); + deserSize = 0; + REQUIRE(zeroLenField.serialize(&serPtr, &deserSize, rawBuf.size(), + SerializeIF::Endianness::NETWORK) == returnvalue::OK); + deserPtr = rawBuf.data(); + result = zeroLenField.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK); + REQUIRE(result == returnvalue::OK); + REQUIRE(zeroLenField.getSerializedSize() == 2); + REQUIRE(deserSize == 0); + } +} diff --git a/unittests/container/CMakeLists.txt b/unittests/container/CMakeLists.txt new file mode 100644 index 00000000..d65e5993 --- /dev/null +++ b/unittests/container/CMakeLists.txt @@ -0,0 +1,10 @@ +target_sources( + ${FSFW_TEST_TGT} + PRIVATE RingBufferTest.cpp + TestArrayList.cpp + TestDynamicFifo.cpp + TestFifo.cpp + TestFixedArrayList.cpp + TestFixedMap.cpp + TestFixedOrderedMultimap.cpp + TestPlacementFactory.cpp) diff --git a/tests/src/fsfw_tests/unit/container/RingBufferTest.cpp b/unittests/container/RingBufferTest.cpp similarity index 58% rename from tests/src/fsfw_tests/unit/container/RingBufferTest.cpp rename to unittests/container/RingBufferTest.cpp index a83fa2ac..49fa1ab0 100644 --- a/tests/src/fsfw_tests/unit/container/RingBufferTest.cpp +++ b/unittests/container/RingBufferTest.cpp @@ -3,49 +3,51 @@ #include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" -TEST_CASE("Ring Buffer Test", "[RingBufferTest]") { +TEST_CASE("Ring Buffer Test", "[containers]") { uint8_t testData[13] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; uint8_t readBuffer[10] = {13, 13, 13, 13, 13, 13, 13, 13, 13, 13}; SimpleRingBuffer ringBuffer(10, false, 5); SECTION("Simple Test") { REQUIRE(ringBuffer.availableWriteSpace() == 9); - REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK); - REQUIRE(ringBuffer.writeData(testData, 3) == retval::CATCH_FAILED); - REQUIRE(ringBuffer.readData(readBuffer, 5, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 9) == returnvalue::OK); + REQUIRE(ringBuffer.writeData(testData, 3) == returnvalue::FAILED); + REQUIRE(ringBuffer.readData(readBuffer, 5, true) == returnvalue::OK); for (uint8_t i = 0; i < 5; i++) { CHECK(readBuffer[i] == i); } REQUIRE(ringBuffer.availableWriteSpace() == 5); ringBuffer.clear(); REQUIRE(ringBuffer.availableWriteSpace() == 9); - REQUIRE(ringBuffer.writeData(testData, 4) == retval::CATCH_OK); - REQUIRE(ringBuffer.readData(readBuffer, 4, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 4) == returnvalue::OK); + REQUIRE(ringBuffer.readData(readBuffer, 4, true) == returnvalue::OK); for (uint8_t i = 0; i < 4; i++) { CHECK(readBuffer[i] == i); } - REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK); - REQUIRE(ringBuffer.readData(readBuffer, 9, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 9) == returnvalue::OK); + REQUIRE(ringBuffer.readData(readBuffer, 9, true) == returnvalue::OK); for (uint8_t i = 0; i < 9; i++) { CHECK(readBuffer[i] == i); } + REQUIRE(ringBuffer.writeData(testData, 1024) == returnvalue::FAILED); + REQUIRE(ringBuffer.writeData(nullptr, 5) == returnvalue::FAILED); } SECTION("Get Free Element Test") { REQUIRE(ringBuffer.availableWriteSpace() == 9); - REQUIRE(ringBuffer.writeData(testData, 8) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 8) == returnvalue::OK); REQUIRE(ringBuffer.availableWriteSpace() == 1); - REQUIRE(ringBuffer.readData(readBuffer, 8, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.readData(readBuffer, 8, true) == returnvalue::OK); REQUIRE(ringBuffer.availableWriteSpace() == 9); uint8_t *testPtr = nullptr; - REQUIRE(ringBuffer.getFreeElement(&testPtr, 10) == retval::CATCH_FAILED); + REQUIRE(ringBuffer.getFreeElement(&testPtr, 10) == returnvalue::FAILED); REQUIRE(ringBuffer.writeTillWrap() == 2); // too many excess bytes. - REQUIRE(ringBuffer.getFreeElement(&testPtr, 8) == retval::CATCH_FAILED); - REQUIRE(ringBuffer.getFreeElement(&testPtr, 5) == retval::CATCH_OK); + REQUIRE(ringBuffer.getFreeElement(&testPtr, 8) == returnvalue::FAILED); + REQUIRE(ringBuffer.getFreeElement(&testPtr, 5) == returnvalue::OK); REQUIRE(ringBuffer.getExcessBytes() == 3); std::memcpy(testPtr, testData, 5); ringBuffer.confirmBytesWritten(5); @@ -57,19 +59,19 @@ TEST_CASE("Ring Buffer Test", "[RingBufferTest]") { } SECTION("Read Remaining Test") { - REQUIRE(ringBuffer.writeData(testData, 3) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 3) == returnvalue::OK); REQUIRE(ringBuffer.getAvailableReadData() == 3); - REQUIRE(ringBuffer.readData(readBuffer, 5, false, false, nullptr) == retval::CATCH_FAILED); + REQUIRE(ringBuffer.readData(readBuffer, 5, false, false, nullptr) == returnvalue::FAILED); size_t trueSize = 0; - REQUIRE(ringBuffer.readData(readBuffer, 5, false, true, &trueSize) == retval::CATCH_OK); + REQUIRE(ringBuffer.readData(readBuffer, 5, false, true, &trueSize) == returnvalue::OK); REQUIRE(trueSize == 3); for (uint8_t i = 0; i < 3; i++) { CHECK(readBuffer[i] == i); } trueSize = 0; - REQUIRE(ringBuffer.deleteData(5, false, &trueSize) == retval::CATCH_FAILED); + REQUIRE(ringBuffer.deleteData(5, false, &trueSize) == returnvalue::FAILED); REQUIRE(trueSize == 0); - REQUIRE(ringBuffer.deleteData(5, true, &trueSize) == retval::CATCH_OK); + REQUIRE(ringBuffer.deleteData(5, true, &trueSize) == returnvalue::OK); REQUIRE(trueSize == 3); } } @@ -82,21 +84,21 @@ TEST_CASE("Ring Buffer Test2", "[RingBufferTest2]") { SECTION("Simple Test") { REQUIRE(ringBuffer.availableWriteSpace() == 9); - REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK); - REQUIRE(ringBuffer.readData(readBuffer, 5, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 9) == returnvalue::OK); + REQUIRE(ringBuffer.readData(readBuffer, 5, true) == returnvalue::OK); for (uint8_t i = 0; i < 5; i++) { CHECK(readBuffer[i] == i); } REQUIRE(ringBuffer.availableWriteSpace() == 5); ringBuffer.clear(); REQUIRE(ringBuffer.availableWriteSpace() == 9); - REQUIRE(ringBuffer.writeData(testData, 4) == retval::CATCH_OK); - REQUIRE(ringBuffer.readData(readBuffer, 4, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 4) == returnvalue::OK); + REQUIRE(ringBuffer.readData(readBuffer, 4, true) == returnvalue::OK); for (uint8_t i = 0; i < 4; i++) { CHECK(readBuffer[i] == i); } - REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK); - REQUIRE(ringBuffer.readData(readBuffer, 9, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 9) == returnvalue::OK); + REQUIRE(ringBuffer.readData(readBuffer, 9, true) == returnvalue::OK); for (uint8_t i = 0; i < 9; i++) { CHECK(readBuffer[i] == i); } @@ -104,17 +106,17 @@ TEST_CASE("Ring Buffer Test2", "[RingBufferTest2]") { SECTION("Get Free Element Test") { REQUIRE(ringBuffer.availableWriteSpace() == 9); - REQUIRE(ringBuffer.writeData(testData, 8) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 8) == returnvalue::OK); REQUIRE(ringBuffer.availableWriteSpace() == 1); - REQUIRE(ringBuffer.readData(readBuffer, 8, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.readData(readBuffer, 8, true) == returnvalue::OK); REQUIRE(ringBuffer.availableWriteSpace() == 9); uint8_t *testPtr = nullptr; - REQUIRE(ringBuffer.getFreeElement(&testPtr, 10) == retval::CATCH_FAILED); + REQUIRE(ringBuffer.getFreeElement(&testPtr, 10) == returnvalue::FAILED); REQUIRE(ringBuffer.writeTillWrap() == 2); // too many excess bytes. - REQUIRE(ringBuffer.getFreeElement(&testPtr, 8) == retval::CATCH_FAILED); - REQUIRE(ringBuffer.getFreeElement(&testPtr, 5) == retval::CATCH_OK); + REQUIRE(ringBuffer.getFreeElement(&testPtr, 8) == returnvalue::FAILED); + REQUIRE(ringBuffer.getFreeElement(&testPtr, 5) == returnvalue::OK); REQUIRE(ringBuffer.getExcessBytes() == 3); std::memcpy(testPtr, testData, 5); ringBuffer.confirmBytesWritten(5); @@ -126,36 +128,37 @@ TEST_CASE("Ring Buffer Test2", "[RingBufferTest2]") { } SECTION("Read Remaining Test") { - REQUIRE(ringBuffer.writeData(testData, 3) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 3) == returnvalue::OK); REQUIRE(ringBuffer.getAvailableReadData() == 3); - REQUIRE(ringBuffer.readData(readBuffer, 5, false, false, nullptr) == retval::CATCH_FAILED); + REQUIRE(ringBuffer.readData(readBuffer, 5, false, false, nullptr) == returnvalue::FAILED); size_t trueSize = 0; - REQUIRE(ringBuffer.readData(readBuffer, 5, false, true, &trueSize) == retval::CATCH_OK); + REQUIRE(ringBuffer.readData(readBuffer, 5, false, true, &trueSize) == returnvalue::OK); REQUIRE(trueSize == 3); for (uint8_t i = 0; i < 3; i++) { CHECK(readBuffer[i] == i); } trueSize = 0; - REQUIRE(ringBuffer.deleteData(5, false, &trueSize) == retval::CATCH_FAILED); + REQUIRE(ringBuffer.deleteData(5, false, &trueSize) == returnvalue::FAILED); REQUIRE(trueSize == 0); - REQUIRE(ringBuffer.deleteData(5, true, &trueSize) == retval::CATCH_OK); + REQUIRE(ringBuffer.deleteData(5, true, &trueSize) == returnvalue::OK); REQUIRE(trueSize == 3); } SECTION("Overflow") { REQUIRE(ringBuffer.availableWriteSpace() == 9); - // Writing more than the buffer is large, technically thats allowed - // But it is senseless and has undesired impact on read call - REQUIRE(ringBuffer.writeData(testData, 13) == retval::CATCH_OK); - REQUIRE(ringBuffer.getAvailableReadData() == 3); + // We don't allow writing of Data that is larger than the ring buffer in total + REQUIRE(ringBuffer.getMaxSize() == 9); + REQUIRE(ringBuffer.writeData(testData, 13) == returnvalue::FAILED); + REQUIRE(ringBuffer.getAvailableReadData() == 0); ringBuffer.clear(); uint8_t *ptr = nullptr; - REQUIRE(ringBuffer.getFreeElement(&ptr, 13) == retval::CATCH_OK); + // With excess Bytes 13 Bytes can be written to this Buffer + REQUIRE(ringBuffer.getFreeElement(&ptr, 13) == returnvalue::OK); REQUIRE(ptr != nullptr); memcpy(ptr, testData, 13); ringBuffer.confirmBytesWritten(13); REQUIRE(ringBuffer.getAvailableReadData() == 3); - REQUIRE(ringBuffer.readData(readBuffer, 3, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.readData(readBuffer, 3, true) == returnvalue::OK); for (auto i = 0; i < 3; i++) { REQUIRE(readBuffer[i] == testData[i + 10]); } @@ -170,21 +173,21 @@ TEST_CASE("Ring Buffer Test3", "[RingBufferTest3]") { SECTION("Simple Test") { REQUIRE(ringBuffer.availableWriteSpace() == 9); - REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK); - REQUIRE(ringBuffer.readData(readBuffer, 5, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 9) == returnvalue::OK); + REQUIRE(ringBuffer.readData(readBuffer, 5, true) == returnvalue::OK); for (uint8_t i = 0; i < 5; i++) { CHECK(readBuffer[i] == i); } REQUIRE(ringBuffer.availableWriteSpace() == 5); ringBuffer.clear(); REQUIRE(ringBuffer.availableWriteSpace() == 9); - REQUIRE(ringBuffer.writeData(testData, 4) == retval::CATCH_OK); - REQUIRE(ringBuffer.readData(readBuffer, 4, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 4) == returnvalue::OK); + REQUIRE(ringBuffer.readData(readBuffer, 4, true) == returnvalue::OK); for (uint8_t i = 0; i < 4; i++) { CHECK(readBuffer[i] == i); } - REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK); - REQUIRE(ringBuffer.readData(readBuffer, 9, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 9) == returnvalue::OK); + REQUIRE(ringBuffer.readData(readBuffer, 9, true) == returnvalue::OK); for (uint8_t i = 0; i < 9; i++) { CHECK(readBuffer[i] == i); } @@ -192,19 +195,19 @@ TEST_CASE("Ring Buffer Test3", "[RingBufferTest3]") { SECTION("Get Free Element Test") { REQUIRE(ringBuffer.availableWriteSpace() == 9); - REQUIRE(ringBuffer.writeData(testData, 8) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 8) == returnvalue::OK); REQUIRE(ringBuffer.availableWriteSpace() == 1); - REQUIRE(ringBuffer.readData(readBuffer, 8, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.readData(readBuffer, 8, true) == returnvalue::OK); REQUIRE(ringBuffer.availableWriteSpace() == 9); uint8_t *testPtr = nullptr; - REQUIRE(ringBuffer.getFreeElement(&testPtr, 10) == retval::CATCH_OK); + REQUIRE(ringBuffer.getFreeElement(&testPtr, 10) == returnvalue::OK); REQUIRE(ringBuffer.getExcessBytes() == 8); REQUIRE(ringBuffer.writeTillWrap() == 2); // too many excess bytes. - REQUIRE(ringBuffer.getFreeElement(&testPtr, 8) == retval::CATCH_FAILED); + REQUIRE(ringBuffer.getFreeElement(&testPtr, 8) == returnvalue::FAILED); // Less Execss bytes overwrites before - REQUIRE(ringBuffer.getFreeElement(&testPtr, 3) == retval::CATCH_OK); + REQUIRE(ringBuffer.getFreeElement(&testPtr, 3) == returnvalue::OK); REQUIRE(ringBuffer.getExcessBytes() == 1); std::memcpy(testPtr, testData, 3); ringBuffer.confirmBytesWritten(3); @@ -216,36 +219,38 @@ TEST_CASE("Ring Buffer Test3", "[RingBufferTest3]") { } SECTION("Read Remaining Test") { - REQUIRE(ringBuffer.writeData(testData, 3) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 3) == returnvalue::OK); REQUIRE(ringBuffer.getAvailableReadData() == 3); - REQUIRE(ringBuffer.readData(readBuffer, 5, false, false, nullptr) == retval::CATCH_FAILED); + REQUIRE(ringBuffer.readData(readBuffer, 5, false, false, nullptr) == returnvalue::FAILED); size_t trueSize = 0; - REQUIRE(ringBuffer.readData(readBuffer, 5, false, true, &trueSize) == retval::CATCH_OK); + REQUIRE(ringBuffer.readData(readBuffer, 5, false, true, &trueSize) == returnvalue::OK); REQUIRE(trueSize == 3); for (uint8_t i = 0; i < 3; i++) { CHECK(readBuffer[i] == i); } trueSize = 0; - REQUIRE(ringBuffer.deleteData(5, false, &trueSize) == retval::CATCH_FAILED); + REQUIRE(ringBuffer.deleteData(5, false, &trueSize) == returnvalue::FAILED); REQUIRE(trueSize == 0); - REQUIRE(ringBuffer.deleteData(5, true, &trueSize) == retval::CATCH_OK); + REQUIRE(ringBuffer.deleteData(5, true, &trueSize) == returnvalue::OK); REQUIRE(trueSize == 3); } SECTION("Overflow") { REQUIRE(ringBuffer.availableWriteSpace() == 9); - // Writing more than the buffer is large, technically thats allowed - // But it is senseless and has undesired impact on read call - REQUIRE(ringBuffer.writeData(testData, 13) == retval::CATCH_OK); - REQUIRE(ringBuffer.getAvailableReadData() == 3); + // Writing more than the buffer is large. + // This write will be rejected and is seen as a configuration mistake + REQUIRE(ringBuffer.writeData(testData, 13) == returnvalue::FAILED); + REQUIRE(ringBuffer.getAvailableReadData() == 0); ringBuffer.clear(); + // Using FreeElement allows the usage of excessBytes but + // should be used with caution uint8_t *ptr = nullptr; - REQUIRE(ringBuffer.getFreeElement(&ptr, 13) == retval::CATCH_OK); + REQUIRE(ringBuffer.getFreeElement(&ptr, 13) == returnvalue::OK); REQUIRE(ptr != nullptr); memcpy(ptr, testData, 13); ringBuffer.confirmBytesWritten(13); REQUIRE(ringBuffer.getAvailableReadData() == 3); - REQUIRE(ringBuffer.readData(readBuffer, 3, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.readData(readBuffer, 3, true) == returnvalue::OK); for (auto i = 0; i < 3; i++) { REQUIRE(readBuffer[i] == testData[i + 10]); } @@ -259,22 +264,22 @@ TEST_CASE("Ring Buffer Test4", "[RingBufferTest4]") { SECTION("Simple Test") { REQUIRE(ringBuffer.availableWriteSpace() == 9); - REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK); - REQUIRE(ringBuffer.writeData(testData, 3) == retval::CATCH_FAILED); - REQUIRE(ringBuffer.readData(readBuffer, 5, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 9) == returnvalue::OK); + REQUIRE(ringBuffer.writeData(testData, 3) == returnvalue::FAILED); + REQUIRE(ringBuffer.readData(readBuffer, 5, true) == returnvalue::OK); for (uint8_t i = 0; i < 5; i++) { CHECK(readBuffer[i] == i); } REQUIRE(ringBuffer.availableWriteSpace() == 5); ringBuffer.clear(); REQUIRE(ringBuffer.availableWriteSpace() == 9); - REQUIRE(ringBuffer.writeData(testData, 4) == retval::CATCH_OK); - REQUIRE(ringBuffer.readData(readBuffer, 4, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 4) == returnvalue::OK); + REQUIRE(ringBuffer.readData(readBuffer, 4, true) == returnvalue::OK); for (uint8_t i = 0; i < 4; i++) { CHECK(readBuffer[i] == i); } - REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK); - REQUIRE(ringBuffer.readData(readBuffer, 9, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 9) == returnvalue::OK); + REQUIRE(ringBuffer.readData(readBuffer, 9, true) == returnvalue::OK); for (uint8_t i = 0; i < 9; i++) { CHECK(readBuffer[i] == i); } @@ -282,16 +287,16 @@ TEST_CASE("Ring Buffer Test4", "[RingBufferTest4]") { SECTION("Get Free Element Test") { REQUIRE(ringBuffer.availableWriteSpace() == 9); - REQUIRE(ringBuffer.writeData(testData, 8) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 8) == returnvalue::OK); REQUIRE(ringBuffer.availableWriteSpace() == 1); - REQUIRE(ringBuffer.readData(readBuffer, 8, true) == retval::CATCH_OK); + REQUIRE(ringBuffer.readData(readBuffer, 8, true) == returnvalue::OK); REQUIRE(ringBuffer.availableWriteSpace() == 9); uint8_t *testPtr = nullptr; - REQUIRE(ringBuffer.getFreeElement(&testPtr, 10) == retval::CATCH_FAILED); + REQUIRE(ringBuffer.getFreeElement(&testPtr, 10) == returnvalue::FAILED); REQUIRE(ringBuffer.writeTillWrap() == 2); - REQUIRE(ringBuffer.getFreeElement(&testPtr, 8) == retval::CATCH_OK); - REQUIRE(ringBuffer.getFreeElement(&testPtr, 5) == retval::CATCH_OK); + REQUIRE(ringBuffer.getFreeElement(&testPtr, 8) == returnvalue::OK); + REQUIRE(ringBuffer.getFreeElement(&testPtr, 5) == returnvalue::OK); REQUIRE(ringBuffer.getExcessBytes() == 3); std::memcpy(testPtr, testData, 5); ringBuffer.confirmBytesWritten(5); @@ -303,19 +308,19 @@ TEST_CASE("Ring Buffer Test4", "[RingBufferTest4]") { } SECTION("Read Remaining Test") { - REQUIRE(ringBuffer.writeData(testData, 3) == retval::CATCH_OK); + REQUIRE(ringBuffer.writeData(testData, 3) == returnvalue::OK); REQUIRE(ringBuffer.getAvailableReadData() == 3); - REQUIRE(ringBuffer.readData(readBuffer, 5, false, false, nullptr) == retval::CATCH_FAILED); + REQUIRE(ringBuffer.readData(readBuffer, 5, false, false, nullptr) == returnvalue::FAILED); size_t trueSize = 0; - REQUIRE(ringBuffer.readData(readBuffer, 5, false, true, &trueSize) == retval::CATCH_OK); + REQUIRE(ringBuffer.readData(readBuffer, 5, false, true, &trueSize) == returnvalue::OK); REQUIRE(trueSize == 3); for (uint8_t i = 0; i < 3; i++) { CHECK(readBuffer[i] == i); } trueSize = 0; - REQUIRE(ringBuffer.deleteData(5, false, &trueSize) == retval::CATCH_FAILED); + REQUIRE(ringBuffer.deleteData(5, false, &trueSize) == returnvalue::FAILED); REQUIRE(trueSize == 0); - REQUIRE(ringBuffer.deleteData(5, true, &trueSize) == retval::CATCH_OK); + REQUIRE(ringBuffer.deleteData(5, true, &trueSize) == returnvalue::OK); REQUIRE(trueSize == 3); } } diff --git a/tests/src/fsfw_tests/unit/container/TestArrayList.cpp b/unittests/container/TestArrayList.cpp similarity index 79% rename from tests/src/fsfw_tests/unit/container/TestArrayList.cpp rename to unittests/container/TestArrayList.cpp index 2c5a37d9..0c327685 100644 --- a/tests/src/fsfw_tests/unit/container/TestArrayList.cpp +++ b/unittests/container/TestArrayList.cpp @@ -1,14 +1,14 @@ #include -#include +#include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" /** * @brief Array List test */ -TEST_CASE("Array List", "[ArrayListTest]") { +TEST_CASE("Array List", "[containers]") { // perform set-up here ArrayList list(20); struct TestClass { @@ -25,7 +25,7 @@ TEST_CASE("Array List", "[ArrayListTest]") { SECTION("SimpleTest") { REQUIRE(list.maxSize() == 20); REQUIRE(list.size == 0); - REQUIRE(list.insert(10) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(list.insert(10) == static_cast(returnvalue::OK)); REQUIRE(list[0] == 10); REQUIRE(list.front() != nullptr); REQUIRE((*list.front()) == 10); @@ -41,9 +41,9 @@ TEST_CASE("Array List", "[ArrayListTest]") { // This is an invalid element but its not a nullptr REQUIRE(list.back() != nullptr); for (auto i = 0; i < 20; i++) { - REQUIRE(list.insert(i) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(list.insert(i) == static_cast(returnvalue::OK)); } - REQUIRE(list.insert(20) == static_cast(ArrayList::FULL)); + REQUIRE(list.insert(20) == static_cast(containers::LIST_FULL)); ArrayList::Iterator it = list.begin(); REQUIRE((*it) == 0); it++; @@ -64,7 +64,7 @@ TEST_CASE("Array List", "[ArrayListTest]") { SECTION("Const Iterator") { ArrayList::Iterator it = list.begin(); for (auto i = 0; i < 10; i++) { - REQUIRE(list.insert(i) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(list.insert(i) == static_cast(returnvalue::OK)); } it++; const uint16_t* number = it.value; @@ -74,8 +74,7 @@ TEST_CASE("Array List", "[ArrayListTest]") { SECTION("Const Iterator") { ArrayList::Iterator it = complexList.begin(); for (auto i = 0; i < 10; i++) { - REQUIRE(complexList.insert(TestClass(i, i + 1)) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(complexList.insert(TestClass(i, i + 1)) == static_cast(returnvalue::OK)); } it++; const TestClass* secondTest = it.value; diff --git a/tests/src/fsfw_tests/unit/container/TestDynamicFifo.cpp b/unittests/container/TestDynamicFifo.cpp similarity index 59% rename from tests/src/fsfw_tests/unit/container/TestDynamicFifo.cpp rename to unittests/container/TestDynamicFifo.cpp index 540ea31e..d32f7e5e 100644 --- a/tests/src/fsfw_tests/unit/container/TestDynamicFifo.cpp +++ b/unittests/container/TestDynamicFifo.cpp @@ -1,12 +1,12 @@ #include #include -#include +#include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" -TEST_CASE("Dynamic Fifo Tests", "[TestDynamicFifo]") { +TEST_CASE("Dynamic Fifo Tests", "[containers]") { INFO("Dynamic Fifo Tests"); struct Test { uint64_t number1; @@ -35,13 +35,13 @@ TEST_CASE("Dynamic Fifo Tests", "[TestDynamicFifo]") { REQUIRE(fifo.empty()); REQUIRE(not fifo.full()); - REQUIRE(fifo.insert(structOne) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(fifo.insert(structTwo) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(fifo.insert(structThree) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.insert(structOne) == static_cast(returnvalue::OK)); + REQUIRE(fifo.insert(structTwo) == static_cast(returnvalue::OK)); + REQUIRE(fifo.insert(structThree) == static_cast(returnvalue::OK)); REQUIRE(fifo.insert(structTwo) == static_cast(FIFOBase::FULL)); struct Test testptr; - REQUIRE(fifo.peek(&testptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.peek(&testptr) == static_cast(returnvalue::OK)); bool equal = testptr == structOne; REQUIRE(equal); REQUIRE(fifo.size() == 3); @@ -52,7 +52,7 @@ TEST_CASE("Dynamic Fifo Tests", "[TestDynamicFifo]") { testptr.number1 = 0; testptr.number2 = 0; testptr.number3 = 0; - REQUIRE(fifo.retrieve(&testptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.retrieve(&testptr) == static_cast(returnvalue::OK)); equal = testptr == list[i]; REQUIRE(equal); REQUIRE(fifo.size() == i); @@ -66,29 +66,26 @@ TEST_CASE("Dynamic Fifo Tests", "[TestDynamicFifo]") { REQUIRE(fifo.empty()); REQUIRE(fifo.pop() == static_cast(FIFOBase::EMPTY)); - REQUIRE(fifo.insert(structOne) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.insert(structOne) == static_cast(returnvalue::OK)); REQUIRE(fifo.size() == 1); - REQUIRE(fifo.insert(structTwo) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.insert(structTwo) == static_cast(returnvalue::OK)); REQUIRE(fifo.size() == 2); - REQUIRE(fifo.pop() == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.pop() == static_cast(returnvalue::OK)); REQUIRE(fifo.size() == 1); testptr.number1 = 0; testptr.number2 = 0; testptr.number3 = 0; - REQUIRE(fifo.peek(&testptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.peek(&testptr) == static_cast(returnvalue::OK)); equal = testptr == structTwo; REQUIRE(equal); - REQUIRE(fifo.pop() == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.pop() == static_cast(returnvalue::OK)); REQUIRE(fifo.size() == 0); REQUIRE(fifo.empty()); - // struct Test* ptr = nullptr; - // REQUIRE(fifo.retrieve(ptr) == static_cast(HasReturnvaluesIF::RETURN_FAILED)); - // REQUIRE(fifo.peek(ptr) == static_cast(HasReturnvaluesIF::RETURN_FAILED)); }; SECTION("Copy Test") { - REQUIRE(fifo.insert(structOne) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(fifo.insert(structTwo) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(fifo.insert(structThree) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.insert(structOne) == static_cast(returnvalue::OK)); + REQUIRE(fifo.insert(structTwo) == static_cast(returnvalue::OK)); + REQUIRE(fifo.insert(structThree) == static_cast(returnvalue::OK)); REQUIRE(fifo.size() == 3); REQUIRE(fifo.full()); REQUIRE(not fifo.empty()); @@ -100,9 +97,9 @@ TEST_CASE("Dynamic Fifo Tests", "[TestDynamicFifo]") { }; SECTION("Assignment Test") { - REQUIRE(fifo.insert(structOne) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(fifo.insert(structTwo) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(fifo.insert(structThree) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.insert(structOne) == static_cast(returnvalue::OK)); + REQUIRE(fifo.insert(structTwo) == static_cast(returnvalue::OK)); + REQUIRE(fifo.insert(structThree) == static_cast(returnvalue::OK)); REQUIRE(fifo.size() == 3); REQUIRE(fifo.full()); REQUIRE(not fifo.empty()); @@ -114,7 +111,7 @@ TEST_CASE("Dynamic Fifo Tests", "[TestDynamicFifo]") { REQUIRE(not fifo2.empty()); for (size_t i = 2; i < 3; i--) { struct Test testptr = {0, 0, 0}; - REQUIRE(fifo2.retrieve(&testptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo2.retrieve(&testptr) == static_cast(returnvalue::OK)); bool equal = testptr == list[i]; REQUIRE(equal); REQUIRE(fifo2.size() == i); @@ -122,9 +119,9 @@ TEST_CASE("Dynamic Fifo Tests", "[TestDynamicFifo]") { }; SECTION("Assignment Test Smaller") { - REQUIRE(fifo.insert(structOne) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(fifo.insert(structTwo) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(fifo.insert(structThree) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.insert(structOne) == static_cast(returnvalue::OK)); + REQUIRE(fifo.insert(structTwo) == static_cast(returnvalue::OK)); + REQUIRE(fifo.insert(structThree) == static_cast(returnvalue::OK)); REQUIRE(fifo.size() == 3); REQUIRE(fifo.full()); REQUIRE(not fifo.empty()); @@ -136,7 +133,7 @@ TEST_CASE("Dynamic Fifo Tests", "[TestDynamicFifo]") { REQUIRE(not fifo2.empty()); for (size_t i = 2; i < 3; i--) { struct Test testptr = {0, 0, 0}; - REQUIRE(fifo2.retrieve(&testptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo2.retrieve(&testptr) == static_cast(returnvalue::OK)); bool equal = testptr == list[i]; REQUIRE(equal); REQUIRE(fifo2.size() == i); diff --git a/tests/src/fsfw_tests/unit/container/TestFifo.cpp b/unittests/container/TestFifo.cpp similarity index 61% rename from tests/src/fsfw_tests/unit/container/TestFifo.cpp rename to unittests/container/TestFifo.cpp index a9eb7956..bfd9391f 100644 --- a/tests/src/fsfw_tests/unit/container/TestFifo.cpp +++ b/unittests/container/TestFifo.cpp @@ -1,12 +1,12 @@ #include #include -#include +#include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" -TEST_CASE("Static Fifo Tests", "[TestFifo]") { +TEST_CASE("Static Fifo Tests", "[containers]") { INFO("Fifo Tests"); struct Test { uint64_t number1; @@ -35,13 +35,13 @@ TEST_CASE("Static Fifo Tests", "[TestFifo]") { REQUIRE(fifo.empty()); REQUIRE(not fifo.full()); - REQUIRE(fifo.insert(structOne) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(fifo.insert(structTwo) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(fifo.insert(structThree) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.insert(structOne) == static_cast(returnvalue::OK)); + REQUIRE(fifo.insert(structTwo) == static_cast(returnvalue::OK)); + REQUIRE(fifo.insert(structThree) == static_cast(returnvalue::OK)); REQUIRE(fifo.insert(structTwo) == static_cast(FIFOBase::FULL)); struct Test testptr; - REQUIRE(fifo.peek(&testptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.peek(&testptr) == static_cast(returnvalue::OK)); bool equal = testptr == structOne; REQUIRE(equal); REQUIRE(fifo.size() == 3); @@ -52,7 +52,7 @@ TEST_CASE("Static Fifo Tests", "[TestFifo]") { testptr.number1 = 0; testptr.number2 = 0; testptr.number3 = 0; - REQUIRE(fifo.retrieve(&testptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.retrieve(&testptr) == static_cast(returnvalue::OK)); equal = testptr == list[i]; REQUIRE(equal); REQUIRE(fifo.size() == i); @@ -66,11 +66,11 @@ TEST_CASE("Static Fifo Tests", "[TestFifo]") { REQUIRE(fifo.empty()); REQUIRE(fifo.pop() == static_cast(FIFOBase::EMPTY)); - REQUIRE(fifo.insert(structOne) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.insert(structOne) == static_cast(returnvalue::OK)); REQUIRE(fifo.size() == 1); - REQUIRE(fifo.insert(structTwo) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.insert(structTwo) == static_cast(returnvalue::OK)); REQUIRE(fifo.size() == 2); - REQUIRE(fifo.pop() == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.pop() == static_cast(returnvalue::OK)); REQUIRE(fifo.size() == 1); testptr.number1 = 0; testptr.number2 = 0; @@ -78,20 +78,20 @@ TEST_CASE("Static Fifo Tests", "[TestFifo]") { // Test that retrieve and peek will not cause a nullptr dereference struct Test* ptr = nullptr; - REQUIRE(fifo.retrieve(ptr) == static_cast(HasReturnvaluesIF::RETURN_FAILED)); - REQUIRE(fifo.peek(ptr) == static_cast(HasReturnvaluesIF::RETURN_FAILED)); + REQUIRE(fifo.retrieve(ptr) == static_cast(returnvalue::FAILED)); + REQUIRE(fifo.peek(ptr) == static_cast(returnvalue::FAILED)); - REQUIRE(fifo.peek(&testptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.peek(&testptr) == static_cast(returnvalue::OK)); equal = testptr == structTwo; REQUIRE(equal); - REQUIRE(fifo.pop() == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.pop() == static_cast(returnvalue::OK)); REQUIRE(fifo.size() == 0); REQUIRE(fifo.empty()); }; SECTION("Copy Test") { - REQUIRE(fifo.insert(structOne) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(fifo.insert(structTwo) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(fifo.insert(structThree) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.insert(structOne) == static_cast(returnvalue::OK)); + REQUIRE(fifo.insert(structTwo) == static_cast(returnvalue::OK)); + REQUIRE(fifo.insert(structThree) == static_cast(returnvalue::OK)); REQUIRE(fifo.size() == 3); REQUIRE(fifo.full()); REQUIRE(not fifo.empty()); @@ -102,7 +102,7 @@ TEST_CASE("Static Fifo Tests", "[TestFifo]") { REQUIRE(not fifo2.empty()); for (size_t i = 2; i < 3; i--) { struct Test testptr = {0, 0, 0}; - REQUIRE(fifo2.retrieve(&testptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo2.retrieve(&testptr) == static_cast(returnvalue::OK)); bool equal = testptr == list[i]; REQUIRE(equal); REQUIRE(fifo2.size() == i); @@ -110,9 +110,9 @@ TEST_CASE("Static Fifo Tests", "[TestFifo]") { }; SECTION("Assignment Test") { - REQUIRE(fifo.insert(structOne) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(fifo.insert(structTwo) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(fifo.insert(structThree) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo.insert(structOne) == static_cast(returnvalue::OK)); + REQUIRE(fifo.insert(structTwo) == static_cast(returnvalue::OK)); + REQUIRE(fifo.insert(structThree) == static_cast(returnvalue::OK)); REQUIRE(fifo.size() == 3); REQUIRE(fifo.full()); REQUIRE(not fifo.empty()); @@ -124,7 +124,7 @@ TEST_CASE("Static Fifo Tests", "[TestFifo]") { REQUIRE(not fifo2.empty()); for (size_t i = 2; i < 3; i--) { struct Test testptr = {0, 0, 0}; - REQUIRE(fifo2.retrieve(&testptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(fifo2.retrieve(&testptr) == static_cast(returnvalue::OK)); bool equal = testptr == list[i]; REQUIRE(equal); REQUIRE(fifo2.size() == i); diff --git a/tests/src/fsfw_tests/unit/container/TestFixedArrayList.cpp b/unittests/container/TestFixedArrayList.cpp similarity index 65% rename from tests/src/fsfw_tests/unit/container/TestFixedArrayList.cpp rename to unittests/container/TestFixedArrayList.cpp index 42ae01d5..f3131c64 100644 --- a/tests/src/fsfw_tests/unit/container/TestFixedArrayList.cpp +++ b/unittests/container/TestFixedArrayList.cpp @@ -1,16 +1,16 @@ #include -#include +#include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" -TEST_CASE("FixedArrayList Tests", "[TestFixedArrayList]") { +TEST_CASE("FixedArrayList Tests", "[containers]") { INFO("FixedArrayList Tests"); using testList = FixedArrayList; testList list; REQUIRE(list.size == 0); - REQUIRE(list.insert(10) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(list.insert(10) == static_cast(returnvalue::OK)); REQUIRE(list.size == 1); REQUIRE(list.maxSize() == 260); SECTION("Copy Constructor") { @@ -29,9 +29,9 @@ TEST_CASE("FixedArrayList Tests", "[TestFixedArrayList]") { }; SECTION("Fill") { for (auto i = 1; i < 260; i++) { - REQUIRE(list.insert(i) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(list.insert(i) == static_cast(returnvalue::OK)); } - REQUIRE(list.insert(260) == static_cast(ArrayList::FULL)); + REQUIRE(list.insert(260) == static_cast(containers::LIST_FULL)); list.clear(); REQUIRE(list.size == 0); } diff --git a/tests/src/fsfw_tests/unit/container/TestFixedMap.cpp b/unittests/container/TestFixedMap.cpp similarity index 66% rename from tests/src/fsfw_tests/unit/container/TestFixedMap.cpp rename to unittests/container/TestFixedMap.cpp index 4c3cad1e..83ff975d 100644 --- a/tests/src/fsfw_tests/unit/container/TestFixedMap.cpp +++ b/unittests/container/TestFixedMap.cpp @@ -1,13 +1,15 @@ #include -#include +#include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" template class FixedMap; -TEST_CASE("FixedMap Tests", "[TestFixedMap]") { +using namespace returnvalue; + +TEST_CASE("FixedMap Tests", "[containers]") { INFO("FixedMap Tests"); FixedMap map(30); @@ -19,31 +21,29 @@ TEST_CASE("FixedMap Tests", "[TestFixedMap]") { SECTION("Fill and erase") { for (uint16_t i = 0; i < 30; i++) { - REQUIRE(map.insert(std::make_pair(i, i + 1)) == - static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(map.exists(i) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.insert(std::make_pair(i, i + 1)) == static_cast(returnvalue::OK)); + REQUIRE(map.exists(i) == static_cast(returnvalue::OK)); REQUIRE(map.find(i)->second == i + 1); REQUIRE(not map.empty()); } - REQUIRE(map.insert(0, 0) == static_cast(FixedMap::KEY_ALREADY_EXISTS)); - REQUIRE(map.insert(31, 0) == static_cast(FixedMap::MAP_FULL)); - REQUIRE(map.exists(31) == static_cast(FixedMap::KEY_DOES_NOT_EXIST)); + REQUIRE(map.insert(0, 0) == static_cast(containers::KEY_ALREADY_EXISTS)); + REQUIRE(map.insert(31, 0) == static_cast(containers::MAP_FULL)); + REQUIRE(map.exists(31) == static_cast(containers::KEY_DOES_NOT_EXIST)); REQUIRE(map.size() == 30); REQUIRE(map.full()); { uint16_t* ptr; - REQUIRE(map.find(5, &ptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.find(5, &ptr) == static_cast(returnvalue::OK)); REQUIRE(*ptr == 6); REQUIRE(*(map.findValue(6)) == 7); - REQUIRE(map.find(31, &ptr) == - static_cast(FixedMap::KEY_DOES_NOT_EXIST)); + REQUIRE(map.find(31, &ptr) == static_cast(containers::KEY_DOES_NOT_EXIST)); } REQUIRE(map.getSerializedSize() == (sizeof(uint32_t) + 30 * (sizeof(uint32_t) + sizeof(uint16_t)))); - REQUIRE(map.erase(2) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(map.erase(31) == static_cast(FixedMap::KEY_DOES_NOT_EXIST)); - REQUIRE(map.exists(2) == static_cast(FixedMap::KEY_DOES_NOT_EXIST)); + REQUIRE(map.erase(2) == static_cast(returnvalue::OK)); + REQUIRE(map.erase(31) == static_cast(containers::KEY_DOES_NOT_EXIST)); + REQUIRE(map.exists(2) == static_cast(containers::KEY_DOES_NOT_EXIST)); REQUIRE(map.size() == 29); for (auto element : map) { @@ -60,7 +60,7 @@ TEST_CASE("FixedMap Tests", "[TestFixedMap]") { } for (FixedMap::Iterator it = map.begin(); it != map.end(); it++) { - REQUIRE(map.erase(&it) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.erase(&it) == static_cast(returnvalue::OK)); } REQUIRE(map.size() == 0); @@ -73,21 +73,20 @@ TEST_CASE("FixedMap Tests", "[TestFixedMap]") { SECTION("Insert variants") { FixedMap::Iterator it = map.end(); - REQUIRE(map.insert(36, 37, &it) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.insert(36, 37, &it) == static_cast(returnvalue::OK)); REQUIRE(it->first == 36); REQUIRE(it->second == 37); REQUIRE(map.size() == 1); - REQUIRE(map.insert(37, 38, nullptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.insert(37, 38, nullptr) == static_cast(returnvalue::OK)); REQUIRE(map.find(37)->second == 38); REQUIRE(map.size() == 2); - REQUIRE(map.insert(37, 24, nullptr) == - static_cast(FixedMap::KEY_ALREADY_EXISTS)); + REQUIRE(map.insert(37, 24, nullptr) == static_cast(containers::KEY_ALREADY_EXISTS)); REQUIRE(map.find(37)->second != 24); REQUIRE(map.size() == 2); }; SECTION("Serialize and DeSerialize") { - REQUIRE(map.insert(36, 37, nullptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(map.insert(37, 38, nullptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.insert(36, 37, nullptr) == static_cast(returnvalue::OK)); + REQUIRE(map.insert(37, 38, nullptr) == static_cast(returnvalue::OK)); uint8_t buffer[sizeof(uint32_t) + 2 * (sizeof(uint32_t) + sizeof(uint16_t))]; REQUIRE(map.getSerializedSize() == (sizeof(uint32_t) + 2 * (sizeof(uint32_t) + sizeof(uint16_t)))); @@ -97,27 +96,27 @@ TEST_CASE("FixedMap Tests", "[TestFixedMap]") { static_cast(SerializeIF::BUFFER_TOO_SHORT)); loc_ptr = buffer; size = 0; - REQUIRE(map.serialize( - &loc_ptr, &size, sizeof(uint32_t) + 2 * (sizeof(uint32_t) + sizeof(uint16_t)), - SerializeIF::Endianness::BIG) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.serialize(&loc_ptr, &size, + sizeof(uint32_t) + 2 * (sizeof(uint32_t) + sizeof(uint16_t)), + SerializeIF::Endianness::BIG) == static_cast(returnvalue::OK)); REQUIRE(size == 16); uint32_t internal_size = 0; const uint8_t* ptr2 = buffer; REQUIRE( SerializeAdapter::deSerialize(&internal_size, &ptr2, &size, SerializeIF::Endianness::BIG) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + static_cast(returnvalue::OK)); REQUIRE(internal_size == 2); for (uint8_t i = 36; i < 38; i++) { uint32_t first_element = 0; REQUIRE(SerializeAdapter::deSerialize(&first_element, &ptr2, &size, SerializeIF::Endianness::BIG) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + static_cast(returnvalue::OK)); REQUIRE(first_element == i); uint16_t second_element = 0; REQUIRE(SerializeAdapter::deSerialize(&second_element, &ptr2, &size, SerializeIF::Endianness::BIG) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + static_cast(returnvalue::OK)); REQUIRE(second_element == i + 1); } REQUIRE(size == 0); @@ -126,7 +125,7 @@ TEST_CASE("FixedMap Tests", "[TestFixedMap]") { size = 16; REQUIRE(map.size() == 0); REQUIRE(map.deSerialize(&constPtr, &size, SerializeIF::Endianness::BIG) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + static_cast(returnvalue::OK)); REQUIRE(map.size() == 2); REQUIRE(map.find(36)->second == 37); for (auto& element : map) { @@ -138,7 +137,7 @@ TEST_CASE("FixedMap Tests", "[TestFixedMap]") { FixedMap::Iterator it; std::pair pair = std::make_pair(44, 43); it = FixedMap::Iterator(&pair); - REQUIRE(map.erase(&it) == static_cast(FixedMap::KEY_DOES_NOT_EXIST)); + REQUIRE(map.erase(&it) == static_cast(containers::KEY_DOES_NOT_EXIST)); REQUIRE(map.find(45) == map.end()); size_t toLargeMap = 100; const uint8_t* ptr = reinterpret_cast(&toLargeMap); @@ -154,12 +153,12 @@ TEST_CASE("FixedMap Tests", "[TestFixedMap]") { size_t size = 0; size_t max_size = sizeof(uint32_t) + 1 * (sizeof(uint32_t) + sizeof(uint16_t)); REQUIRE(map.serialize(&ptr, &size, max_size, SerializeIF::Endianness::LITTLE) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + static_cast(returnvalue::OK)); map.clear(); REQUIRE(map.size() == 0); const uint8_t* ptr2 = newBuffer; REQUIRE(map.deSerialize(&ptr2, &size, SerializeIF::Endianness::LITTLE) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + static_cast(returnvalue::OK)); REQUIRE(map.size() == 1); REQUIRE(map.find(10)->second == 20); }; diff --git a/tests/src/fsfw_tests/unit/container/TestFixedOrderedMultimap.cpp b/unittests/container/TestFixedOrderedMultimap.cpp similarity index 78% rename from tests/src/fsfw_tests/unit/container/TestFixedOrderedMultimap.cpp rename to unittests/container/TestFixedOrderedMultimap.cpp index 7dd63b34..cadb03e6 100644 --- a/tests/src/fsfw_tests/unit/container/TestFixedOrderedMultimap.cpp +++ b/unittests/container/TestFixedOrderedMultimap.cpp @@ -1,11 +1,11 @@ #include -#include +#include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" -TEST_CASE("FixedOrderedMultimap Tests", "[TestFixedOrderedMultimap]") { +TEST_CASE("FixedOrderedMultimap Tests", "[containers]") { INFO("FixedOrderedMultimap Tests"); FixedOrderedMultimap map(30); @@ -14,9 +14,8 @@ TEST_CASE("FixedOrderedMultimap Tests", "[TestFixedOrderedMultimap]") { SECTION("Test insert, find, exists") { for (uint16_t i = 0; i < 30; i++) { - REQUIRE(map.insert(std::make_pair(i, i + 1)) == - static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(map.exists(i) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.insert(std::make_pair(i, i + 1)) == static_cast(returnvalue::OK)); + REQUIRE(map.exists(i) == static_cast(returnvalue::OK)); REQUIRE(map.find(i)->second == i + 1); } REQUIRE(map.insert(0, 0) == @@ -26,12 +25,12 @@ TEST_CASE("FixedOrderedMultimap Tests", "[TestFixedOrderedMultimap]") { REQUIRE(map.size() == 30); { uint16_t* ptr; - REQUIRE(map.find(5, &ptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.find(5, &ptr) == static_cast(returnvalue::OK)); REQUIRE(*ptr == 6); REQUIRE(map.find(31, &ptr) == static_cast(FixedOrderedMultimap::KEY_DOES_NOT_EXIST)); } - REQUIRE(map.erase(2) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.erase(2) == static_cast(returnvalue::OK)); REQUIRE(map.erase(31) == static_cast(FixedOrderedMultimap::KEY_DOES_NOT_EXIST)); REQUIRE(map.exists(2) == @@ -55,7 +54,7 @@ TEST_CASE("FixedOrderedMultimap Tests", "[TestFixedOrderedMultimap]") { { FixedOrderedMultimap::Iterator it = map.begin(); while (it != map.end()) { - REQUIRE(map.erase(&it) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.erase(&it) == static_cast(returnvalue::OK)); } REQUIRE(map.size() == 0); } @@ -69,16 +68,16 @@ TEST_CASE("FixedOrderedMultimap Tests", "[TestFixedOrderedMultimap]") { SECTION("Test different insert variants") { FixedOrderedMultimap::Iterator it = map.end(); - REQUIRE(map.insert(36, 37, &it) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.insert(36, 37, &it) == static_cast(returnvalue::OK)); REQUIRE(it->first == 36); REQUIRE(it->second == 37); REQUIRE(map.size() == 1); - REQUIRE(map.insert(37, 38, nullptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.insert(37, 38, nullptr) == static_cast(returnvalue::OK)); REQUIRE(map.find(37)->second == 38); REQUIRE(map.size() == 2); - REQUIRE(map.insert(37, 24, nullptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.insert(37, 24, nullptr) == static_cast(returnvalue::OK)); REQUIRE(map.find(37)->second == 38); - REQUIRE(map.insert(0, 1, nullptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.insert(0, 1, nullptr) == static_cast(returnvalue::OK)); REQUIRE(map.find(0)->second == 1); REQUIRE(map.size() == 4); map.clear(); @@ -128,8 +127,8 @@ TEST_CASE("FixedOrderedMultimap Non Trivial Type", "[TestFixedOrderedMultimapNon SECTION("Test insert, find, exists") { for (uint16_t i = 0; i < 30; i++) { REQUIRE(map.insert(std::make_pair(i, TestClass(i + 1, i))) == - static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(map.exists(i) == static_cast(HasReturnvaluesIF::RETURN_OK)); + static_cast(returnvalue::OK)); + REQUIRE(map.exists(i) == static_cast(returnvalue::OK)); bool compare = map.find(i)->second == TestClass(i + 1, i); REQUIRE(compare); } @@ -140,13 +139,13 @@ TEST_CASE("FixedOrderedMultimap Non Trivial Type", "[TestFixedOrderedMultimapNon REQUIRE(map.size() == 30); { TestClass* ptr = nullptr; - REQUIRE(map.find(5, &ptr) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.find(5, &ptr) == static_cast(returnvalue::OK)); bool compare = *ptr == TestClass(6, 5); REQUIRE(compare); REQUIRE(map.find(31, &ptr) == static_cast(FixedOrderedMultimap::KEY_DOES_NOT_EXIST)); } - REQUIRE(map.erase(2) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.erase(2) == static_cast(returnvalue::OK)); REQUIRE(map.erase(31) == static_cast(FixedOrderedMultimap::KEY_DOES_NOT_EXIST)); REQUIRE(map.exists(2) == @@ -174,7 +173,7 @@ TEST_CASE("FixedOrderedMultimap Non Trivial Type", "[TestFixedOrderedMultimapNon { FixedOrderedMultimap::Iterator it = map.begin(); while (it != map.end()) { - REQUIRE(map.erase(&it) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.erase(&it) == static_cast(returnvalue::OK)); } REQUIRE(map.size() == 0); } @@ -188,23 +187,19 @@ TEST_CASE("FixedOrderedMultimap Non Trivial Type", "[TestFixedOrderedMultimapNon SECTION("Test different insert variants") { FixedOrderedMultimap::Iterator it = map.end(); - REQUIRE(map.insert(36, TestClass(37, 36), &it) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.insert(36, TestClass(37, 36), &it) == static_cast(returnvalue::OK)); REQUIRE(it->first == 36); bool compare = it->second == TestClass(37, 36); REQUIRE(compare); REQUIRE(map.size() == 1); - REQUIRE(map.insert(37, TestClass(38, 37), nullptr) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.insert(37, TestClass(38, 37), nullptr) == static_cast(returnvalue::OK)); compare = map.find(37)->second == TestClass(38, 37); REQUIRE(compare); REQUIRE(map.size() == 2); - REQUIRE(map.insert(37, TestClass(24, 37), nullptr) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.insert(37, TestClass(24, 37), nullptr) == static_cast(returnvalue::OK)); compare = map.find(37)->second == TestClass(38, 37); REQUIRE(compare); - REQUIRE(map.insert(0, TestClass(1, 0), nullptr) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(map.insert(0, TestClass(1, 0), nullptr) == static_cast(returnvalue::OK)); compare = map.find(0)->second == TestClass(1, 0); REQUIRE(compare); REQUIRE(map.size() == 4); diff --git a/tests/src/fsfw_tests/unit/container/TestPlacementFactory.cpp b/unittests/container/TestPlacementFactory.cpp similarity index 78% rename from tests/src/fsfw_tests/unit/container/TestPlacementFactory.cpp rename to unittests/container/TestPlacementFactory.cpp index 0140ce05..fa8e1e07 100644 --- a/tests/src/fsfw_tests/unit/container/TestPlacementFactory.cpp +++ b/unittests/container/TestPlacementFactory.cpp @@ -1,13 +1,13 @@ #include #include -#include +#include #include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" -TEST_CASE("PlacementFactory Tests", "[TestPlacementFactory]") { +TEST_CASE("PlacementFactory Tests", "[containers]") { INFO("PlacementFactory Tests"); LocalPool::LocalPoolConfig poolCfg = { @@ -36,13 +36,13 @@ TEST_CASE("PlacementFactory Tests", "[TestPlacementFactory]") { static_cast(StorageManagerIF::DATA_TOO_LARGE)); uint64_t* number2 = factory.generate(12345); REQUIRE(number2 == nullptr); - REQUIRE(factory.destroy(number) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(factory.destroy(number) == static_cast(returnvalue::OK)); REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr) == - static_cast(HasReturnvaluesIF::RETURN_OK)); - REQUIRE(storagePool.deleteData(address) == static_cast(HasReturnvaluesIF::RETURN_OK)); + static_cast(returnvalue::OK)); + REQUIRE(storagePool.deleteData(address) == static_cast(returnvalue::OK)); // Check that PlacementFactory checks for nullptr ptr = nullptr; - REQUIRE(factory.destroy(ptr) == static_cast(HasReturnvaluesIF::RETURN_FAILED)); + REQUIRE(factory.destroy(ptr) == static_cast(returnvalue::FAILED)); } } diff --git a/unittests/datapoollocal/CMakeLists.txt b/unittests/datapoollocal/CMakeLists.txt new file mode 100644 index 00000000..2c7a573f --- /dev/null +++ b/unittests/datapoollocal/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources( + ${FSFW_TEST_TGT} PRIVATE testLocalPoolVariable.cpp testLocalPoolVector.cpp + testDataSet.cpp testLocalPoolManager.cpp) diff --git a/tests/src/fsfw_tests/unit/datapoollocal/DataSetTest.cpp b/unittests/datapoollocal/testDataSet.cpp similarity index 86% rename from tests/src/fsfw_tests/unit/datapoollocal/DataSetTest.cpp rename to unittests/datapoollocal/testDataSet.cpp index 902d59ef..def92ac3 100644 --- a/tests/src/fsfw_tests/unit/datapoollocal/DataSetTest.cpp +++ b/unittests/datapoollocal/testDataSet.cpp @@ -8,16 +8,18 @@ #include #include -#include "LocalPoolOwnerBase.h" -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" +#include "mocks/LocalPoolOwnerBase.h" +#include "mocks/MessageQueueMock.h" #include "tests/TestsConfig.h" +using namespace returnvalue; + TEST_CASE("DataSetTest", "[DataSetTest]") { - LocalPoolOwnerBase* poolOwner = - ObjectManager::instance()->get(objects::TEST_LOCAL_POOL_OWNER_BASE); - REQUIRE(poolOwner != nullptr); - REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); - REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() == retval::CATCH_OK); + auto queue = MessageQueueMock(1); + LocalPoolOwnerBase poolOwner(queue, objects::TEST_LOCAL_POOL_OWNER_BASE); + REQUIRE(poolOwner.initializeHkManager() == OK); + REQUIRE(poolOwner.initializeHkManagerAfterTaskCreation() == OK); LocalPoolStaticTestDataSet localSet; SECTION("BasicTest") { @@ -30,13 +32,13 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { size_t maxSize = localSet.getLocalPoolIdsSerializedSize(true); uint8_t localPoolIdBuff[maxSize]; /* Skip size field */ - lp_id_t* lpIds = reinterpret_cast(localPoolIdBuff + 1); + auto* lpIds = reinterpret_cast(localPoolIdBuff + 1); size_t serSize = 0; - uint8_t* localPoolIdBuffPtr = reinterpret_cast(localPoolIdBuff); + auto* localPoolIdBuffPtr = reinterpret_cast(localPoolIdBuff); /* Test local pool ID serialization */ CHECK(localSet.serializeLocalPoolIds(&localPoolIdBuffPtr, &serSize, maxSize, - SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); + SerializeIF::Endianness::MACHINE) == returnvalue::OK); CHECK(serSize == maxSize); CHECK(localPoolIdBuff[0] == 3); CHECK(lpIds[0] == localSet.localPoolVarUint8.getDataPoolId()); @@ -47,8 +49,7 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { localPoolIdBuffPtr = localPoolIdBuff; serSize = 0; CHECK(localSet.serializeLocalPoolIds(&localPoolIdBuffPtr, &serSize, maxSize, - SerializeIF::Endianness::MACHINE, - false) == retval::CATCH_OK); + SerializeIF::Endianness::MACHINE, false) == OK); CHECK(serSize == maxSize - sizeof(uint8_t)); CHECK(lpIds[0] == localSet.localPoolVarUint8.getDataPoolId()); CHECK(lpIds[1] == localSet.localPoolVarFloat.getDataPoolId()); @@ -57,7 +58,7 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { { /* Test read operation. Values should be all zeros */ PoolReadGuard readHelper(&localSet); - REQUIRE(readHelper.getReadResult() == retval::CATCH_OK); + REQUIRE(readHelper.getReadResult() == returnvalue::OK); CHECK(not localSet.isValid()); CHECK(localSet.localPoolVarUint8.value == 0); CHECK(not localSet.localPoolVarUint8.isValid()); @@ -90,7 +91,7 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { /* Now we read again and check whether our zeroed values were overwritten with the values in the pool */ PoolReadGuard readHelper(&localSet); - REQUIRE(readHelper.getReadResult() == retval::CATCH_OK); + REQUIRE(readHelper.getReadResult() == returnvalue::OK); CHECK(localSet.isValid()); CHECK(localSet.localPoolVarUint8.value == 232); CHECK(localSet.localPoolVarUint8.isValid()); @@ -110,7 +111,7 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { uint8_t buffer[maxSize + 1]; uint8_t* buffPtr = buffer; CHECK(localSet.serialize(&buffPtr, &serSize, maxSize, SerializeIF::Endianness::MACHINE) == - retval::CATCH_OK); + returnvalue::OK); uint8_t rawUint8 = buffer[0]; CHECK(rawUint8 == 232); float rawFloat = 0.0; @@ -128,7 +129,7 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { std::memset(buffer, 0, sizeof(buffer)); const uint8_t* constBuffPtr = buffer; CHECK(localSet.deSerialize(&constBuffPtr, &sizeToDeserialize, - SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); + SerializeIF::Endianness::MACHINE) == returnvalue::OK); /* Check whether deserialization was successfull */ CHECK(localSet.localPoolVarUint8.value == 0); CHECK(localSet.localPoolVarFloat.value == Catch::Approx(0.0)); @@ -156,7 +157,7 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { serSize = 0; buffPtr = buffer; CHECK(localSet.serialize(&buffPtr, &serSize, maxSize, SerializeIF::Endianness::MACHINE) == - retval::CATCH_OK); + returnvalue::OK); CHECK(rawUint8 == 232); std::memcpy(&rawFloat, buffer + sizeof(uint8_t), sizeof(float)); CHECK(rawFloat == Catch::Approx(-2324.322)); @@ -186,7 +187,7 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { sizeToDeserialize = maxSize; constBuffPtr = buffer; CHECK(localSet.deSerialize(&constBuffPtr, &sizeToDeserialize, - SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); + SerializeIF::Endianness::MACHINE) == returnvalue::OK); /* Check whether deserialization was successfull */ CHECK(localSet.localPoolVarUint8.value == 0); CHECK(localSet.localPoolVarFloat.value == Catch::Approx(0.0)); @@ -200,7 +201,7 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { } /* Common fault test cases */ - LocalPoolObjectBase* variableHandle = poolOwner->getPoolObjectHandle(lpool::uint32VarId); + LocalPoolObjectBase* variableHandle = poolOwner.getPoolObjectHandle(lpool::uint32VarId); CHECK(variableHandle != nullptr); CHECK(localSet.registerVariable(variableHandle) == static_cast(DataSetIF::DATA_SET_FULL)); variableHandle = nullptr; @@ -209,14 +210,14 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { } SECTION("MorePoolVariables") { - LocalDataSet set(poolOwner, 2, 10); + LocalDataSet set(&poolOwner, 2, 10); /* Register same variables again to get more than 8 registered variables */ for (uint8_t idx = 0; idx < 8; idx++) { - REQUIRE(set.registerVariable(&localSet.localPoolVarUint8) == retval::CATCH_OK); + REQUIRE(set.registerVariable(&localSet.localPoolVarUint8) == returnvalue::OK); } - REQUIRE(set.registerVariable(&localSet.localPoolVarUint8) == retval::CATCH_OK); - REQUIRE(set.registerVariable(&localSet.localPoolUint16Vec) == retval::CATCH_OK); + REQUIRE(set.registerVariable(&localSet.localPoolVarUint8) == returnvalue::OK); + REQUIRE(set.registerVariable(&localSet.localPoolUint16Vec) == returnvalue::OK); set.setValidityBufferGeneration(true); { @@ -232,9 +233,8 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { /* Already reserve additional space for validity buffer, will be needed later */ uint8_t buffer[maxSize + 1]; uint8_t* buffPtr = buffer; - CHECK(set.serialize(&buffPtr, &serSize, maxSize, SerializeIF::Endianness::MACHINE) == - retval::CATCH_OK); - std::array validityBuffer; + CHECK(set.serialize(&buffPtr, &serSize, maxSize, SerializeIF::Endianness::MACHINE) == OK); + std::array validityBuffer{}; std::memcpy(validityBuffer.data(), buffer + 9 + sizeof(uint16_t) * 3, 2); /* The first 9 variables should be valid */ CHECK(validityBuffer[0] == 0xff); @@ -251,36 +251,32 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { const uint8_t* constBuffPtr = buffer; size_t sizeToDeSerialize = serSize; CHECK(set.deSerialize(&constBuffPtr, &sizeToDeSerialize, SerializeIF::Endianness::MACHINE) == - retval::CATCH_OK); + returnvalue::OK); CHECK(localSet.localPoolVarUint8.isValid() == false); CHECK(localSet.localPoolUint16Vec.isValid() == true); } SECTION("SharedDataSet") { object_id_t sharedSetId = objects::SHARED_SET_ID; - SharedLocalDataSet sharedSet(sharedSetId, poolOwner, lpool::testSetId, 5); + SharedLocalDataSet sharedSet(sharedSetId, &poolOwner, lpool::testSetId, 5); localSet.localPoolVarUint8.setReadWriteMode(pool_rwm_t::VAR_WRITE); localSet.localPoolUint16Vec.setReadWriteMode(pool_rwm_t::VAR_WRITE); - CHECK(sharedSet.registerVariable(&localSet.localPoolVarUint8) == retval::CATCH_OK); - CHECK(sharedSet.registerVariable(&localSet.localPoolUint16Vec) == retval::CATCH_OK); - CHECK(sharedSet.initialize() == retval::CATCH_OK); - CHECK(sharedSet.lockDataset() == retval::CATCH_OK); - CHECK(sharedSet.unlockDataset() == retval::CATCH_OK); + CHECK(sharedSet.registerVariable(&localSet.localPoolVarUint8) == returnvalue::OK); + CHECK(sharedSet.registerVariable(&localSet.localPoolUint16Vec) == returnvalue::OK); + CHECK(sharedSet.initialize() == returnvalue::OK); + CHECK(sharedSet.lockDataset() == returnvalue::OK); + CHECK(sharedSet.unlockDataset() == returnvalue::OK); { // PoolReadGuard rg(&sharedSet); - // CHECK(rg.getReadResult() == retval::CATCH_OK); + // CHECK(rg.getReadResult() == result::OK); localSet.localPoolVarUint8.value = 5; localSet.localPoolUint16Vec.value[0] = 1; localSet.localPoolUint16Vec.value[1] = 2; localSet.localPoolUint16Vec.value[2] = 3; - CHECK(sharedSet.commit() == retval::CATCH_OK); + CHECK(sharedSet.commit() == returnvalue::OK); } sharedSet.setReadCommitProtectionBehaviour(true); } - - /* we need to reset the subscription list because the pool owner - is a global object. */ - CHECK(poolOwner->reset() == retval::CATCH_OK); } diff --git a/unittests/datapoollocal/testLocalPoolManager.cpp b/unittests/datapoollocal/testLocalPoolManager.cpp new file mode 100644 index 00000000..91cd011d --- /dev/null +++ b/unittests/datapoollocal/testLocalPoolManager.cpp @@ -0,0 +1,429 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "CatchDefinitions.h" +#include "mocks/HkReceiverMock.h" +#include "mocks/LocalPoolOwnerBase.h" + +TEST_CASE("Local Pool Manager Tests", "[LocManTest]") { + const MessageQueueId_t defaultDestId = 1; + const MessageQueueId_t hkDest = defaultDestId; + const MessageQueueId_t subscriberId = 2; + auto hkReceiver = HkReceiverMock(hkDest); + auto queue = MessageQueueMock(3); + LocalPoolOwnerBase poolOwner(queue, objects::TEST_LOCAL_POOL_OWNER_BASE); + REQUIRE(poolOwner.initializeHkManager() == returnvalue::OK); + REQUIRE(poolOwner.initializeHkManagerAfterTaskCreation() == returnvalue::OK); + + MessageQueueMock& poolOwnerMock = poolOwner.getMockQueueHandle(); + + // TODO: This is ugly. This should be an arbitrary ctor argument. Fix this in the pool + // manager + poolOwnerMock.setDefaultDestination(defaultDestId); + poolOwner.setHkDestId(hkDest); + + auto* hkMan = poolOwner.getHkManagerHandle(); + + CommandMessage messageSent; + + SECTION("Basic Test") { + { + /* For code coverage, should not crash */ + LocalDataPoolManager manager(nullptr, nullptr); + } + auto owner = poolOwner.poolManager.getOwner(); + REQUIRE(owner != nullptr); + CHECK(owner->getObjectId() == objects::TEST_LOCAL_POOL_OWNER_BASE); + + /* Subscribe for message generation on update. */ + REQUIRE(poolOwner.subscribeWrapperSetUpdate(subscriberId) == returnvalue::OK); + /* Subscribe for an update message. */ + poolOwner.dataset.setChanged(true); + /* Now the update message should be generated. */ + REQUIRE(poolOwner.poolManager.performHkOperation() == returnvalue::OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == returnvalue::OK); + CHECK(messageSent.getCommand() == + static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); + + /* Should have been reset. */ + CHECK(poolOwner.dataset.hasChanged() == false); + poolOwnerMock.clearMessages(true); + /* Set changed again, result should be the same. */ + poolOwner.dataset.setChanged(true); + REQUIRE(poolOwner.poolManager.performHkOperation() == returnvalue::OK); + + REQUIRE(poolOwnerMock.wasMessageSent() == true); + CHECK(poolOwnerMock.numberOfSentMessages() == 1); + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == returnvalue::OK); + CHECK(messageSent.getCommand() == + static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); + + poolOwnerMock.clearMessages(true); + /* Now subscribe for set update HK as well. */ + REQUIRE(poolOwner.subscribeWrapperSetUpdateHk(false, &hkReceiver) == returnvalue::OK); + poolOwner.dataset.setChanged(true); + REQUIRE(poolOwner.poolManager.performHkOperation() == returnvalue::OK); + REQUIRE(poolOwnerMock.wasMessageSent() == true); + CHECK(poolOwnerMock.numberOfSentMessages() == 2); + // first message sent should be the update notification + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == returnvalue::OK); + CHECK(messageSent.getCommand() == + static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); + REQUIRE(poolOwnerMock.getNextSentMessage(messageSent) == returnvalue::OK); + CHECK(messageSent.getCommand() == static_cast(HousekeepingMessage::HK_REPORT)); + /* Clear message to avoid memory leak, our mock won't do it for us (yet) */ + CommandMessageCleaner::clearCommandMessage(&messageSent); + } + + SECTION("SetSnapshotUpdateTest") { + /* Set the variables in the set to certain values. These are checked later. */ + { + PoolReadGuard readHelper(&poolOwner.dataset); + REQUIRE(readHelper.getReadResult() == returnvalue::OK); + poolOwner.dataset.localPoolVarUint8.value = 5; + poolOwner.dataset.localPoolVarFloat.value = -12.242; + poolOwner.dataset.localPoolUint16Vec.value[0] = 2; + poolOwner.dataset.localPoolUint16Vec.value[1] = 32; + poolOwner.dataset.localPoolUint16Vec.value[2] = 42932; + } + + /* Subscribe for snapshot generation on update. */ + REQUIRE(poolOwner.subscribeWrapperSetUpdateSnapshot(subscriberId) == returnvalue::OK); + poolOwner.dataset.setChanged(true); + + /* Store current time, we are going to check the (approximate) time equality later */ + timeval now{}; + Clock::getClock_timeval(&now); + + /* Trigger generation of snapshot */ + REQUIRE(poolOwner.poolManager.performHkOperation() == returnvalue::OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessages() == 1); + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == returnvalue::OK); + /* Check that snapshot was generated */ + CHECK(messageSent.getCommand() == static_cast(HousekeepingMessage::UPDATE_SNAPSHOT_SET)); + /* Now we deserialize the snapshot into a new dataset instance */ + CCSDSTime::CDS_short cdsShort{}; + LocalPoolTestDataSet newSet; + HousekeepingSnapshot snapshot(&cdsShort, &newSet); + store_address_t storeId; + HousekeepingMessage::getUpdateSnapshotSetCommand(&messageSent, &storeId); + ConstAccessorPair accessorPair = tglob::getIpcStoreHandle()->getData(storeId); + REQUIRE(accessorPair.first == returnvalue::OK); + const uint8_t* readOnlyPtr = accessorPair.second.data(); + size_t sizeToDeserialize = accessorPair.second.size(); + CHECK(newSet.localPoolVarFloat.value == 0); + CHECK(newSet.localPoolVarUint8 == 0); + CHECK(newSet.localPoolUint16Vec.value[0] == 0); + CHECK(newSet.localPoolUint16Vec.value[1] == 0); + CHECK(newSet.localPoolUint16Vec.value[2] == 0); + /* Fill the dataset and timestamp */ + REQUIRE(snapshot.deSerialize(&readOnlyPtr, &sizeToDeserialize, + SerializeIF::Endianness::MACHINE) == returnvalue::OK); + /* Now we check that the snapshot is actually correct */ + CHECK(newSet.localPoolVarFloat.value == Catch::Approx(-12.242)); + CHECK(newSet.localPoolVarUint8 == 5); + CHECK(newSet.localPoolUint16Vec.value[0] == 2); + CHECK(newSet.localPoolUint16Vec.value[1] == 32); + CHECK(newSet.localPoolUint16Vec.value[2] == 42932); + + /* Now we check that both times are equal */ + timeval timeFromHK{}; + auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort); + CHECK(result == returnvalue::OK); + timeval difference = timeFromHK - now; + CHECK(timevalOperations::toDouble(difference) < 1.0); + } + + SECTION("VariableSnapshotTest") { + /* Acquire subscription interface */ + ProvidesDataPoolSubscriptionIF* subscriptionIF = poolOwner.getSubscriptionInterface(); + REQUIRE(subscriptionIF != nullptr); + + /* Subscribe for variable snapshot */ + REQUIRE(poolOwner.subscribeWrapperVariableSnapshot(subscriberId, lpool::uint8VarId) == + returnvalue::OK); + auto poolVar = + dynamic_cast*>(poolOwner.getPoolObjectHandle(lpool::uint8VarId)); + REQUIRE(poolVar != nullptr); + + { + PoolReadGuard rg(poolVar); + CHECK(rg.getReadResult() == returnvalue::OK); + poolVar->value = 25; + } + + poolVar->setChanged(true); + /* Store current time, we are going to check the (approximate) time equality later */ + CCSDSTime::CDS_short timeCdsNow{}; + timeval now{}; + Clock::getClock_timeval(&now); + REQUIRE(poolOwner.poolManager.performHkOperation() == returnvalue::OK); + + /* Check update snapshot was sent. */ + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessages() == 1); + + /* Should have been reset. */ + CHECK(poolVar->hasChanged() == false); + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == returnvalue::OK); + CHECK(messageSent.getCommand() == + static_cast(HousekeepingMessage::UPDATE_SNAPSHOT_VARIABLE)); + /* Now we deserialize the snapshot into a new dataset instance */ + CCSDSTime::CDS_short cdsShort{}; + lp_var_t varCopy = lp_var_t(lpool::uint8VarGpid); + HousekeepingSnapshot snapshot(&cdsShort, &varCopy); + store_address_t storeId; + HousekeepingMessage::getUpdateSnapshotVariableCommand(&messageSent, &storeId); + ConstAccessorPair accessorPair = tglob::getIpcStoreHandle()->getData(storeId); + REQUIRE(accessorPair.first == returnvalue::OK); + const uint8_t* readOnlyPtr = accessorPair.second.data(); + size_t sizeToDeserialize = accessorPair.second.size(); + CHECK(varCopy.value == 0); + /* Fill the dataset and timestamp */ + REQUIRE(snapshot.deSerialize(&readOnlyPtr, &sizeToDeserialize, + SerializeIF::Endianness::MACHINE) == returnvalue::OK); + CHECK(varCopy.value == 25); + + /* Now we check that both times are equal */ + timeval timeFromHK{}; + auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort); + CHECK(result == returnvalue::OK); + timeval difference = timeFromHK - now; + CHECK(timevalOperations::toDouble(difference) < 1.0); + } + + SECTION("VariableNotificationTest") { + /* Acquire subscription interface */ + ProvidesDataPoolSubscriptionIF* subscriptionIF = poolOwner.getSubscriptionInterface(); + REQUIRE(subscriptionIF != nullptr); + + /* Subscribe for variable update */ + REQUIRE(poolOwner.subscribeWrapperVariableUpdate(subscriberId, lpool::uint8VarId) == + returnvalue::OK); + auto* poolVar = + dynamic_cast*>(poolOwner.getPoolObjectHandle(lpool::uint8VarId)); + REQUIRE(poolVar != nullptr); + poolVar->setChanged(true); + REQUIRE(poolVar->hasChanged() == true); + REQUIRE(poolOwner.poolManager.performHkOperation() == returnvalue::OK); + + /* Check update notification was sent. */ + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessages() == 1); + /* Should have been reset. */ + CHECK(poolVar->hasChanged() == false); + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == returnvalue::OK); + CHECK(messageSent.getCommand() == + static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE)); + /* Now subscribe for the dataset update (HK and update) again with subscription interface */ + REQUIRE(subscriptionIF->subscribeForSetUpdateMessage(lpool::testSetId, objects::NO_OBJECT, + subscriberId, false) == returnvalue::OK); + REQUIRE(poolOwner.subscribeWrapperSetUpdateHk(false, &hkReceiver) == returnvalue::OK); + + poolOwner.dataset.setChanged(true); + poolOwnerMock.clearMessages(); + REQUIRE(poolOwner.poolManager.performHkOperation() == returnvalue::OK); + /* Now two messages should be sent. */ + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessages() == 2); + poolOwnerMock.clearMessages(true); + + poolOwner.dataset.setChanged(true); + poolOwnerMock.clearMessages(true); + poolVar->setChanged(true); + REQUIRE(poolOwner.poolManager.performHkOperation() == returnvalue::OK); + /* Now three messages should be sent. */ + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessages() == 3); + CHECK(poolOwnerMock.numberOfSentMessagesToDest(subscriberId) == 2); + CHECK(poolOwnerMock.numberOfSentMessagesToDest(hkDest) == 1); + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == returnvalue::OK); + CHECK(messageSent.getCommand() == + static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE)); + REQUIRE(poolOwnerMock.clearLastSentMessage(subscriberId) == returnvalue::OK); + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == returnvalue::OK); + CHECK(messageSent.getCommand() == + static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); + REQUIRE(poolOwnerMock.clearLastSentMessage(subscriberId) == returnvalue::OK); + REQUIRE(poolOwnerMock.getNextSentMessage(messageSent) == returnvalue::OK); + CHECK(messageSent.getCommand() == static_cast(HousekeepingMessage::HK_REPORT)); + REQUIRE(poolOwnerMock.clearLastSentMessage() == returnvalue::OK); + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == MessageQueueIF::EMPTY); + REQUIRE(poolOwnerMock.getNextSentMessage(messageSent) == MessageQueueIF::EMPTY); + } + + SECTION("PeriodicHKAndMessaging") { + /* Now we subcribe for a HK periodic generation. Even when it's difficult to simulate + the temporal behaviour correctly the HK manager should generate a HK packet + immediately and the periodic helper depends on HK op function calls anyway instead of + using the clock, so we could also just call performHkOperation multiple times */ + REQUIRE(poolOwner.subscribePeriodicHk(true) == returnvalue::OK); + REQUIRE(poolOwner.poolManager.performHkOperation() == returnvalue::OK); + /* Now HK packet should be sent as message immediately. */ + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessages() == 1); + CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK); + + LocalPoolDataSetBase* setHandle = poolOwner.getDataSetHandle(lpool::testSid); + REQUIRE(setHandle != nullptr); + CHECK(poolOwner.poolManager.generateHousekeepingPacket(lpool::testSid, setHandle, false) == + returnvalue::OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessages() == 1); + CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK); + + CHECK(setHandle->getReportingEnabled() == true); + CommandMessage hkCmd; + HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + CHECK(setHandle->getReportingEnabled() == false); + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessages() == 1); + CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK); + + HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, true, false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + CHECK(setHandle->getReportingEnabled() == true); + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK); + + HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + CHECK(setHandle->getReportingEnabled() == false); + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK); + + HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4, + false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + /* For non-diagnostics and a specified minimum frequency of 0.2 seconds, the + resulting collection interval should be 1.0 second */ + CHECK(poolOwner.dataset.getCollectionInterval() == 1.0); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); + CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK); + + HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false); + REQUIRE(poolOwner.poolManager.performHkOperation() == returnvalue::OK); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + /* Now HK packet should be sent as message. */ + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setUpdateNotificationSetCommand(&hkCmd, lpool::testSid); + sid_t sidToCheck; + store_address_t storeId; + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + CHECK(poolOwner.changedDataSetCallbackWasCalled(sidToCheck, storeId) == true); + CHECK(sidToCheck == lpool::testSid); + + /* Now we test the handling is the dataset is set to diagnostic */ + poolOwner.dataset.setDiagnostic(true); + + HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == + static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); + /* We still expect a failure message being sent */ + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); + CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK); + + HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4, + false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == + static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); + CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK); + + HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == + static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); + CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK); + + HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, true); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4, + true); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, true, true); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, true); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == + static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, true); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setUpdateNotificationVariableCommand(&hkCmd, lpool::uint8VarGpid); + gp_id_t gpidToCheck; + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + CHECK(poolOwner.changedVariableCallbackWasCalled(gpidToCheck, storeId) == true); + CHECK(gpidToCheck == lpool::uint8VarGpid); + + HousekeepingMessage::setUpdateSnapshotSetCommand(&hkCmd, lpool::testSid, + store_address_t::invalid()); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + CHECK(poolOwner.changedDataSetCallbackWasCalled(sidToCheck, storeId) == true); + CHECK(sidToCheck == lpool::testSid); + + HousekeepingMessage::setUpdateSnapshotVariableCommand(&hkCmd, lpool::uint8VarGpid, + store_address_t::invalid()); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); + CHECK(poolOwner.changedVariableCallbackWasCalled(gpidToCheck, storeId) == true); + CHECK(gpidToCheck == lpool::uint8VarGpid); + + poolOwner.poolManager.printPoolEntry(lpool::uint8VarId); + } + + /* we need to reset the subscription list because the pool owner + is a global object. */ + CHECK(poolOwner.reset() == returnvalue::OK); + poolOwnerMock.clearMessages(true); +} diff --git a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVariableTest.cpp b/unittests/datapoollocal/testLocalPoolVariable.cpp similarity index 83% rename from tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVariableTest.cpp rename to unittests/datapoollocal/testLocalPoolVariable.cpp index 73d51d92..ce125029 100644 --- a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVariableTest.cpp +++ b/unittests/datapoollocal/testLocalPoolVariable.cpp @@ -3,31 +3,32 @@ #include -#include "LocalPoolOwnerBase.h" -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" +#include "mocks/LocalPoolOwnerBase.h" #include "tests/TestsConfig.h" +using namespace returnvalue; + TEST_CASE("LocalPoolVariable", "[LocPoolVarTest]") { - LocalPoolOwnerBase* poolOwner = - ObjectManager::instance()->get(objects::TEST_LOCAL_POOL_OWNER_BASE); - REQUIRE(poolOwner != nullptr); - REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); - REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() == retval::CATCH_OK); + auto queue = MessageQueueMock(1); + LocalPoolOwnerBase poolOwner(queue, objects::TEST_LOCAL_POOL_OWNER_BASE); + REQUIRE(poolOwner.initializeHkManager() == OK); + REQUIRE(poolOwner.initializeHkManagerAfterTaskCreation() == OK); SECTION("Basic Tests") { /* very basic test. */ lp_var_t testVariable = lp_var_t(objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId); - REQUIRE(testVariable.read() == retval::CATCH_OK); + REQUIRE(testVariable.read() == returnvalue::OK); CHECK(testVariable.value == 0); testVariable.value = 5; - REQUIRE(testVariable.commit() == retval::CATCH_OK); - REQUIRE(testVariable.read() == retval::CATCH_OK); + REQUIRE(testVariable.commit() == returnvalue::OK); + REQUIRE(testVariable.read() == returnvalue::OK); REQUIRE(testVariable.value == 5); CHECK(not testVariable.isValid()); testVariable.setValid(true); CHECK(testVariable.isValid()); - CHECK(testVariable.commit(true) == retval::CATCH_OK); + CHECK(testVariable.commit(true) == returnvalue::OK); testVariable.setReadWriteMode(pool_rwm_t::VAR_READ); CHECK(testVariable.getReadWriteMode() == pool_rwm_t::VAR_READ); @@ -43,7 +44,7 @@ TEST_CASE("LocalPoolVariable", "[LocPoolVarTest]") { gp_id_t globPoolId(objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId); lp_var_t testVariable2 = lp_var_t(globPoolId); - REQUIRE(testVariable2.read() == retval::CATCH_OK); + REQUIRE(testVariable2.read() == returnvalue::OK); CHECK(testVariable2 == 5); CHECK(testVariable == testVariable2); testVariable = 10; @@ -55,12 +56,12 @@ TEST_CASE("LocalPoolVariable", "[LocPoolVarTest]") { CHECK(maxSize == 1); size_t serSize = 0; CHECK(testVariable.serialize(&varPtr, &serSize, maxSize, SerializeIF::Endianness::MACHINE) == - retval::CATCH_OK); + returnvalue::OK); CHECK(variableRaw == 10); const uint8_t* varConstPtr = &variableRaw; testVariable = 5; CHECK(testVariable.deSerialize(&varConstPtr, &serSize, SerializeIF::Endianness::MACHINE) == - retval::CATCH_OK); + returnvalue::OK); CHECK(testVariable == 10); CHECK(testVariable != testVariable2); CHECK(testVariable2 < testVariable); @@ -106,6 +107,4 @@ TEST_CASE("LocalPoolVariable", "[LocPoolVarTest]") { lp_var_t invalidObjectVar2 = lp_var_t(globPoolId); lp_var_t invalidObjectVar3 = lp_var_t(nullptr, lpool::uint8VarId); } - - CHECK(poolOwner->reset() == retval::CATCH_OK); } diff --git a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVectorTest.cpp b/unittests/datapoollocal/testLocalPoolVector.cpp similarity index 84% rename from tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVectorTest.cpp rename to unittests/datapoollocal/testLocalPoolVector.cpp index 5932db44..69014e58 100644 --- a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVectorTest.cpp +++ b/unittests/datapoollocal/testLocalPoolVector.cpp @@ -3,34 +3,35 @@ #include -#include "LocalPoolOwnerBase.h" -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" +#include "mocks/LocalPoolOwnerBase.h" #include "tests/TestsConfig.h" +using namespace returnvalue; + TEST_CASE("LocalPoolVector", "[LocPoolVecTest]") { - LocalPoolOwnerBase* poolOwner = - ObjectManager::instance()->get(objects::TEST_LOCAL_POOL_OWNER_BASE); - REQUIRE(poolOwner != nullptr); - REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); - REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() == retval::CATCH_OK); + auto queue = MessageQueueMock(1); + LocalPoolOwnerBase poolOwner(queue, objects::TEST_LOCAL_POOL_OWNER_BASE); + REQUIRE(poolOwner.initializeHkManager() == OK); + REQUIRE(poolOwner.initializeHkManagerAfterTaskCreation() == OK); SECTION("BasicTest") { // very basic test. lp_vec_t testVector = lp_vec_t(objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id); - REQUIRE(testVector.read() == retval::CATCH_OK); + REQUIRE(testVector.read() == returnvalue::OK); testVector.value[0] = 5; testVector.value[1] = 232; testVector.value[2] = 32023; - REQUIRE(testVector.commit(true) == retval::CATCH_OK); + REQUIRE(testVector.commit(true) == returnvalue::OK); CHECK(testVector.isValid()); testVector.value[0] = 0; testVector.value[1] = 0; testVector.value[2] = 0; - CHECK(testVector.read() == retval::CATCH_OK); + CHECK(testVector.read() == returnvalue::OK); CHECK(testVector.value[0] == 5); CHECK(testVector.value[1] == 232); CHECK(testVector.value[2] == 32023); @@ -41,7 +42,7 @@ TEST_CASE("LocalPoolVector", "[LocPoolVecTest]") { (we can't throw exceptions) */ testVector[4] = 12; CHECK(testVector[2] == 12); - CHECK(testVector.commit() == retval::CATCH_OK); + CHECK(testVector.commit() == returnvalue::OK); /* Use read-only reference. */ const lp_vec_t& roTestVec = testVector; @@ -58,7 +59,7 @@ TEST_CASE("LocalPoolVector", "[LocPoolVecTest]") { uint8_t* vecPtr = reinterpret_cast(serializedVector); size_t serSize = 0; REQUIRE(testVector.serialize(&vecPtr, &serSize, maxSize, SerializeIF::Endianness::MACHINE) == - retval::CATCH_OK); + returnvalue::OK); CHECK(serSize == 6); CHECK(serializedVector[0] == 5); @@ -75,7 +76,7 @@ TEST_CASE("LocalPoolVector", "[LocPoolVecTest]") { const uint8_t* constVecPtr = reinterpret_cast(serializedVector); REQUIRE(testVector.deSerialize(&constVecPtr, &serSize, SerializeIF::Endianness::MACHINE) == - retval::CATCH_OK); + returnvalue::OK); CHECK(testVector[0] == 16); CHECK(testVector[1] == 7832); CHECK(testVector[2] == 39232); @@ -106,5 +107,4 @@ TEST_CASE("LocalPoolVector", "[LocPoolVecTest]") { objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id, nullptr, pool_rwm_t::VAR_READ); REQUIRE(readOnlyVec.commit() == static_cast(PoolVariableIF::INVALID_READ_WRITE_MODE)); } - poolOwner->reset(); } diff --git a/unittests/devicehandler/CMakeLists.txt b/unittests/devicehandler/CMakeLists.txt new file mode 100644 index 00000000..068e0dd4 --- /dev/null +++ b/unittests/devicehandler/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE DeviceHandlerCommander.cpp + TestDeviceHandlerBase.cpp) diff --git a/unittests/devicehandler/DeviceHandlerCommander.cpp b/unittests/devicehandler/DeviceHandlerCommander.cpp new file mode 100644 index 00000000..835faf2b --- /dev/null +++ b/unittests/devicehandler/DeviceHandlerCommander.cpp @@ -0,0 +1,66 @@ +#include "DeviceHandlerCommander.h" + +#include + +DeviceHandlerCommander::DeviceHandlerCommander(object_id_t objectId) + : SystemObject(objectId), commandActionHelper(this) { + auto mqArgs = MqArgs(this->getObjectId()); + commandQueue = QueueFactory::instance()->createMessageQueue( + QUEUE_SIZE, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs); +} + +DeviceHandlerCommander::~DeviceHandlerCommander() { + QueueFactory::instance()->deleteMessageQueue(commandQueue); +} + +ReturnValue_t DeviceHandlerCommander::performOperation(uint8_t operationCode) { + readCommandQueue(); + return returnvalue::OK; +} + +ReturnValue_t DeviceHandlerCommander::initialize() { + ReturnValue_t result = commandActionHelper.initialize(); + if (result != returnvalue::OK) { + return result; + } + return returnvalue::OK; +} + +MessageQueueIF* DeviceHandlerCommander::getCommandQueuePtr() { return commandQueue; } + +void DeviceHandlerCommander::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) {} + +void DeviceHandlerCommander::stepFailedReceived(ActionId_t actionId, uint8_t step, + ReturnValue_t returnCode) {} + +void DeviceHandlerCommander::dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) { +} + +void DeviceHandlerCommander::completionSuccessfulReceived(ActionId_t actionId) { + lastReplyReturnCode = returnvalue::OK; +} + +void DeviceHandlerCommander::completionFailedReceived(ActionId_t actionId, + ReturnValue_t returnCode) { + lastReplyReturnCode = returnCode; +} + +void DeviceHandlerCommander::readCommandQueue() { + CommandMessage message; + ReturnValue_t result = returnvalue::OK; + for (result = commandQueue->receiveMessage(&message); result == returnvalue::OK; + result = commandQueue->receiveMessage(&message)) { + result = commandActionHelper.handleReply(&message); + if (result == returnvalue::OK) { + continue; + } + } +} + +ReturnValue_t DeviceHandlerCommander::sendCommand(object_id_t target, ActionId_t actionId) { + return commandActionHelper.commandAction(target, actionId, nullptr, 0); +} + +ReturnValue_t DeviceHandlerCommander::getReplyReturnCode() { return lastReplyReturnCode; } + +void DeviceHandlerCommander::resetReplyReturnCode() { lastReplyReturnCode = returnvalue::FAILED; } diff --git a/unittests/devicehandler/DeviceHandlerCommander.h b/unittests/devicehandler/DeviceHandlerCommander.h new file mode 100644 index 00000000..62713d54 --- /dev/null +++ b/unittests/devicehandler/DeviceHandlerCommander.h @@ -0,0 +1,49 @@ +#ifndef TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEHANDLERCOMMANDER_H_ +#define TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEHANDLERCOMMANDER_H_ + +#include "fsfw/action/CommandActionHelper.h" +#include "fsfw/action/CommandsActionsIF.h" +#include "fsfw/objectmanager/SystemObject.h" +#include "fsfw/returnvalues/returnvalue.h" +#include "fsfw/tasks/ExecutableObjectIF.h" + +class DeviceHandlerCommander : public ExecutableObjectIF, + public SystemObject, + public CommandsActionsIF { + public: + DeviceHandlerCommander(object_id_t objectId); + virtual ~DeviceHandlerCommander(); + + ReturnValue_t performOperation(uint8_t operationCode = 0); + ReturnValue_t initialize() override; + MessageQueueIF* getCommandQueuePtr() override; + void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) override; + void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) override; + void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) override; + void completionSuccessfulReceived(ActionId_t actionId) override; + void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) override; + + /** + * @brief Calling this function will send the command to the device handler object. + * + * @param target Object ID of the device handler + * @param actionId Action ID of the command to send + */ + ReturnValue_t sendCommand(object_id_t target, ActionId_t actionId); + + ReturnValue_t getReplyReturnCode(); + void resetReplyReturnCode(); + + private: + static const uint32_t QUEUE_SIZE = 20; + + MessageQueueIF* commandQueue = nullptr; + + CommandActionHelper commandActionHelper; + + ReturnValue_t lastReplyReturnCode = returnvalue::FAILED; + + void readCommandQueue(); +}; + +#endif /* TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEHANDLERCOMMANDER_H_ */ diff --git a/unittests/devicehandler/TestDeviceHandlerBase.cpp b/unittests/devicehandler/TestDeviceHandlerBase.cpp new file mode 100644 index 00000000..67c3cdaf --- /dev/null +++ b/unittests/devicehandler/TestDeviceHandlerBase.cpp @@ -0,0 +1,95 @@ +#include + +#include "DeviceHandlerCommander.h" +#include "mocks/ComIFMock.h" +#include "mocks/CookieIFMock.h" +#include "mocks/DeviceFdirMock.h" +#include "mocks/DeviceHandlerMock.h" +#include "objects/systemObjectList.h" + +TEST_CASE("Device Handler Base", "[DeviceHandlerBase]") { + // Will be deleted with DHB destructor + auto* cookieIFMock = new CookieIFMock; + ComIFMock comIF(objects::COM_IF_MOCK); + DeviceFdirMock deviceFdirMock(objects::DEVICE_HANDLER_MOCK, objects::NO_OBJECT); + DeviceHandlerMock deviceHandlerMock(objects::DEVICE_HANDLER_MOCK, objects::COM_IF_MOCK, + cookieIFMock, &deviceFdirMock); + ReturnValue_t result = deviceHandlerMock.initialize(); + REQUIRE(result == returnvalue::OK); + DeviceHandlerCommander deviceHandlerCommander(objects::DEVICE_HANDLER_COMMANDER); + result = deviceHandlerCommander.initialize(); + REQUIRE(result == returnvalue::OK); + + SECTION("Commanding nominal") { + comIF.setTestCase(ComIFMock::TestCase::SIMPLE_COMMAND_NOMINAL); + result = deviceHandlerCommander.sendCommand(objects::DEVICE_HANDLER_MOCK, + DeviceHandlerMock::SIMPLE_COMMAND); + REQUIRE(result == returnvalue::OK); + deviceHandlerMock.performOperation(DeviceHandlerIF::PERFORM_OPERATION); + deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_WRITE); + deviceHandlerMock.performOperation(DeviceHandlerIF::GET_WRITE); + deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_READ); + deviceHandlerMock.performOperation(DeviceHandlerIF::GET_READ); + deviceHandlerCommander.performOperation(); + result = deviceHandlerCommander.getReplyReturnCode(); + uint32_t missedReplies = deviceFdirMock.getMissedReplyCount(); + REQUIRE(missedReplies == 0); + REQUIRE(result == returnvalue::OK); + } + + SECTION("Commanding missed reply") { + comIF.setTestCase(ComIFMock::TestCase::MISSED_REPLY); + deviceHandlerCommander.resetReplyReturnCode(); + // Set the timeout to 0 to immediately timeout the reply + deviceHandlerMock.changeSimpleCommandReplyCountdown(0); + result = deviceHandlerCommander.sendCommand(objects::DEVICE_HANDLER_MOCK, + DeviceHandlerMock::SIMPLE_COMMAND); + REQUIRE(result == returnvalue::OK); + deviceHandlerMock.performOperation(DeviceHandlerIF::PERFORM_OPERATION); + deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_WRITE); + deviceHandlerMock.performOperation(DeviceHandlerIF::GET_WRITE); + deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_READ); + deviceHandlerMock.performOperation(DeviceHandlerIF::GET_READ); + deviceHandlerMock.performOperation(DeviceHandlerIF::PERFORM_OPERATION); + deviceHandlerCommander.performOperation(); + result = deviceHandlerCommander.getReplyReturnCode(); + REQUIRE(result == DeviceHandlerIF::TIMEOUT); + uint32_t missedReplies = deviceFdirMock.getMissedReplyCount(); + REQUIRE(missedReplies == 1); + } + + SECTION("Periodic reply nominal") { + comIF.setTestCase(ComIFMock::TestCase::PERIODIC_REPLY_NOMINAL); + deviceHandlerMock.enablePeriodicReply(DeviceHandlerMock::PERIODIC_REPLY); + deviceHandlerMock.performOperation(DeviceHandlerIF::PERFORM_OPERATION); + deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_WRITE); + deviceHandlerMock.performOperation(DeviceHandlerIF::GET_WRITE); + deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_READ); + deviceHandlerMock.performOperation(DeviceHandlerIF::GET_READ); + REQUIRE(deviceHandlerMock.getPeriodicReplyReceived() == true); + } + + SECTION("Missed periodic reply") { + comIF.setTestCase(ComIFMock::TestCase::MISSED_REPLY); + // Set the timeout to 0 to immediately timeout the reply + deviceHandlerMock.changePeriodicReplyCountdown(0); + deviceHandlerMock.enablePeriodicReply(DeviceHandlerMock::PERIODIC_REPLY); + deviceHandlerMock.performOperation(DeviceHandlerIF::PERFORM_OPERATION); + deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_WRITE); + deviceHandlerMock.performOperation(DeviceHandlerIF::GET_WRITE); + deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_READ); + deviceHandlerMock.performOperation(DeviceHandlerIF::GET_READ); + uint32_t missedReplies = deviceFdirMock.getMissedReplyCount(); + REQUIRE(missedReplies == 1); + // Test if disabling of periodic reply + deviceHandlerMock.disablePeriodicReply(DeviceHandlerMock::PERIODIC_REPLY); + deviceHandlerMock.performOperation(DeviceHandlerIF::PERFORM_OPERATION); + deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_WRITE); + deviceHandlerMock.performOperation(DeviceHandlerIF::GET_WRITE); + deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_READ); + deviceHandlerMock.performOperation(DeviceHandlerIF::GET_READ); + missedReplies = deviceFdirMock.getMissedReplyCount(); + // Should still be 1 because periodic reply is now disabled + REQUIRE(missedReplies == 1); + } +} diff --git a/unittests/globalfunctions/CMakeLists.txt b/unittests/globalfunctions/CMakeLists.txt new file mode 100644 index 00000000..ee94ca77 --- /dev/null +++ b/unittests/globalfunctions/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources( + ${FSFW_TEST_TGT} PRIVATE testDleEncoder.cpp testOpDivider.cpp testBitutil.cpp + testCRC.cpp testTimevalOperations.cpp) diff --git a/tests/src/fsfw_tests/unit/globalfunctions/testBitutil.cpp b/unittests/globalfunctions/testBitutil.cpp similarity index 100% rename from tests/src/fsfw_tests/unit/globalfunctions/testBitutil.cpp rename to unittests/globalfunctions/testBitutil.cpp diff --git a/tests/src/fsfw_tests/unit/globalfunctions/testCRC.cpp b/unittests/globalfunctions/testCRC.cpp similarity index 88% rename from tests/src/fsfw_tests/unit/globalfunctions/testCRC.cpp rename to unittests/globalfunctions/testCRC.cpp index b163ea1f..2b6de4db 100644 --- a/tests/src/fsfw_tests/unit/globalfunctions/testCRC.cpp +++ b/unittests/globalfunctions/testCRC.cpp @@ -1,8 +1,8 @@ #include +#include "CatchDefinitions.h" #include "catch2/catch_test_macros.hpp" #include "fsfw/globalfunctions/CRC.h" -#include "fsfw_tests/unit/CatchDefinitions.h" TEST_CASE("CRC", "[CRC]") { std::array testData = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; diff --git a/tests/src/fsfw_tests/unit/globalfunctions/testDleEncoder.cpp b/unittests/globalfunctions/testDleEncoder.cpp similarity index 98% rename from tests/src/fsfw_tests/unit/globalfunctions/testDleEncoder.cpp rename to unittests/globalfunctions/testDleEncoder.cpp index 034cb3a0..55e27ba4 100644 --- a/tests/src/fsfw_tests/unit/globalfunctions/testDleEncoder.cpp +++ b/unittests/globalfunctions/testDleEncoder.cpp @@ -1,8 +1,8 @@ #include +#include "CatchDefinitions.h" #include "catch2/catch_test_macros.hpp" #include "fsfw/globalfunctions/DleEncoder.h" -#include "fsfw_tests/unit/CatchDefinitions.h" const std::vector TEST_ARRAY_0 = {0, 0, 0, 0, 0}; const std::vector TEST_ARRAY_1 = {0, DleEncoder::DLE_CHAR, 5}; @@ -49,7 +49,7 @@ const std::vector TEST_ARRAY_4_ENCODED_NON_ESCAPED = { TEST_CASE("DleEncoder", "[DleEncoder]") { DleEncoder dleEncoder; - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = returnvalue::OK; std::array buffer; size_t encodedLen = 0; @@ -60,7 +60,7 @@ TEST_CASE("DleEncoder", "[DleEncoder]") { const std::vector& expectedVec) { result = encoder.encode(vecToEncode.data(), vecToEncode.size(), buffer.data(), buffer.size(), &encodedLen); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); for (size_t idx = 0; idx < expectedVec.size(); idx++) { REQUIRE(buffer[idx] == expectedVec[idx]); } @@ -71,7 +71,7 @@ TEST_CASE("DleEncoder", "[DleEncoder]") { const std::vector& expectedVec) { result = encoder.decode(testVecEncoded.data(), testVecEncoded.size(), &readLen, buffer.data(), buffer.size(), &decodedLen); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(readLen == testVecEncoded.size()); REQUIRE(decodedLen == expectedVec.size()); for (size_t idx = 0; idx < decodedLen; idx++) { diff --git a/tests/src/fsfw_tests/unit/globalfunctions/testOpDivider.cpp b/unittests/globalfunctions/testOpDivider.cpp similarity index 100% rename from tests/src/fsfw_tests/unit/globalfunctions/testOpDivider.cpp rename to unittests/globalfunctions/testOpDivider.cpp diff --git a/unittests/globalfunctions/testTimevalOperations.cpp b/unittests/globalfunctions/testTimevalOperations.cpp new file mode 100644 index 00000000..0f89338b --- /dev/null +++ b/unittests/globalfunctions/testTimevalOperations.cpp @@ -0,0 +1,128 @@ +#include + +#include +#include + +#include "CatchDefinitions.h" + +TEST_CASE("TimevalTest", "[timevalOperations]") { + SECTION("Comparison") { + timeval t1; + t1.tv_sec = 1648227422; + t1.tv_usec = 123456; + timeval t2; + t2.tv_sec = 1648227422; + t2.tv_usec = 123456; + REQUIRE(t1 == t2); + REQUIRE(t2 == t1); + REQUIRE_FALSE(t1 != t2); + REQUIRE_FALSE(t2 != t1); + REQUIRE(t1 <= t2); + REQUIRE(t2 <= t1); + REQUIRE(t1 >= t2); + REQUIRE(t2 >= t1); + REQUIRE_FALSE(t1 < t2); + REQUIRE_FALSE(t2 < t1); + REQUIRE_FALSE(t1 > t2); + REQUIRE_FALSE(t2 > t1); + + timeval t3; + t3.tv_sec = 1648227422; + t3.tv_usec = 123457; + REQUIRE_FALSE(t1 == t3); + REQUIRE(t1 != t3); + REQUIRE(t1 <= t3); + REQUIRE_FALSE(t3 <= t1); + REQUIRE_FALSE(t1 >= t3); + REQUIRE(t3 >= t1); + REQUIRE(t1 < t3); + REQUIRE_FALSE(t3 < t1); + REQUIRE_FALSE(t1 > t3); + REQUIRE(t3 > t1); + + timeval t4; + t4.tv_sec = 1648227423; + t4.tv_usec = 123456; + REQUIRE_FALSE(t1 == t4); + REQUIRE(t1 != t4); + REQUIRE(t1 <= t4); + REQUIRE_FALSE(t4 <= t1); + REQUIRE_FALSE(t1 >= t4); + REQUIRE(t4 >= t1); + REQUIRE(t1 < t4); + REQUIRE_FALSE(t4 < t1); + REQUIRE_FALSE(t1 > t4); + REQUIRE(t4 > t1); + } + SECTION("Operators") { + timeval t1; + if (sizeof(t1.tv_sec) == 8) { + t1.tv_sec = 1648227422; + t1.tv_usec = 123456; + timeval t2; + t2.tv_sec = 1648227422; + t2.tv_usec = 123456; + timeval t3 = t1 - t2; + REQUIRE(t3.tv_sec == 0); + REQUIRE(t3.tv_usec == 0); + timeval t4 = t1 - t3; + REQUIRE(t4.tv_sec == 1648227422); + REQUIRE(t4.tv_usec == 123456); + timeval t5 = t3 - t1; + REQUIRE(t5.tv_sec == -1648227422); + REQUIRE(t5.tv_usec == -123456); + + timeval t6; + t6.tv_sec = 1648227400; + t6.tv_usec = 999999; + + timeval t7 = t6 + t1; + // Overflow test + REQUIRE(t7.tv_sec == (1648227422ull + 1648227400ull + 1ull)); + + REQUIRE(t7.tv_usec == 123455); + + timeval t8 = t1 - t6; + REQUIRE(t8.tv_sec == 1648227422 - 1648227400 - 1); + REQUIRE(t8.tv_usec == 123457); + + double scalar = 2; + timeval t9 = t1 * scalar; + REQUIRE(t9.tv_sec == 3296454844); + REQUIRE(t9.tv_usec == 246912); + timeval t10 = scalar * t1; + REQUIRE(t10.tv_sec == 3296454844); + REQUIRE(t10.tv_usec == 246912); + timeval t11 = t6 * scalar; + REQUIRE(t11.tv_sec == (3296454800 + 1)); + REQUIRE(t11.tv_usec == 999998); + + timeval t12 = t1 / scalar; + REQUIRE(t12.tv_sec == 824113711); + REQUIRE(t12.tv_usec == 61728); + + timeval t13 = t6 / scalar; + REQUIRE(t13.tv_sec == 824113700); + // Rounding issue + REQUIRE(t13.tv_usec == 499999); + + double scalar2 = t9 / t1; + REQUIRE(scalar2 == Catch::Approx(2.0)); + double scalar3 = t1 / t6; + REQUIRE(scalar3 == Catch::Approx(1.000000013)); + double scalar4 = t3 / t1; + REQUIRE(scalar4 == Catch::Approx(0)); + double scalar5 = t12 / t1; + REQUIRE(scalar5 == Catch::Approx(0.5)); + } + } + + SECTION("timevalOperations::toTimeval") { + double seconds = 1648227422.123456; + timeval t1 = timevalOperations::toTimeval(seconds); + REQUIRE(t1.tv_sec == 1648227422); + // Allow 1 usec rounding tolerance + REQUIRE(t1.tv_usec >= 123455); + REQUIRE(t1.tv_usec <= 123457); + } +} \ No newline at end of file diff --git a/unittests/hal/CMakeLists.txt b/unittests/hal/CMakeLists.txt new file mode 100644 index 00000000..76aabd51 --- /dev/null +++ b/unittests/hal/CMakeLists.txt @@ -0,0 +1,5 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE testHostFilesystem.cpp testFsMock.cpp) + +if(UNIX) + target_sources(${FSFW_TEST_TGT} PRIVATE testCommandExecutor.cpp) +endif() diff --git a/tests/src/fsfw_tests/unit/hal/testCommandExecutor.cpp b/unittests/hal/testCommandExecutor.cpp similarity index 76% rename from tests/src/fsfw_tests/unit/hal/testCommandExecutor.cpp rename to unittests/hal/testCommandExecutor.cpp index 3ad26876..89011922 100644 --- a/tests/src/fsfw_tests/unit/hal/testCommandExecutor.cpp +++ b/unittests/hal/testCommandExecutor.cpp @@ -2,26 +2,28 @@ #include #include +#include #include "fsfw/container/DynamicFIFO.h" #include "fsfw/container/SimpleRingBuffer.h" #include "fsfw/platform.h" #include "fsfw/serviceinterface.h" #include "fsfw_hal/linux/CommandExecutor.h" +#include "tests/TestsConfig.h" #ifdef PLATFORM_UNIX static const char TEST_FILE_NAME[] = "/tmp/fsfw-unittest-test.txt"; -TEST_CASE("Command Executor", "[cmd-exec]") { +TEST_CASE("Command Executor", "[hal][linux]") { // Check blocking mode first CommandExecutor cmdExecutor(1024); std::string cmd = "echo \"test\" >> " + std::string(TEST_FILE_NAME); REQUIRE(cmdExecutor.getCurrentState() == CommandExecutor::States::IDLE); ReturnValue_t result = cmdExecutor.load(cmd, true, true); REQUIRE(cmdExecutor.getCurrentState() == CommandExecutor::States::COMMAND_LOADED); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - REQUIRE(cmdExecutor.execute() == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); + REQUIRE(cmdExecutor.execute() == returnvalue::OK); // Check that file exists with contents std::ifstream file(TEST_FILE_NAME); std::string line; @@ -36,7 +38,7 @@ TEST_CASE("Command Executor", "[cmd-exec]") { cmdExecutor.setRingBuffer(&outputBuffer, &sizesFifo); result = cmdExecutor.load("echo \"Hello World\"", false, false); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); cmdExecutor.execute(); bool bytesHaveBeenRead = false; size_t limitIdx = 0; @@ -56,15 +58,18 @@ TEST_CASE("Command Executor", "[cmd-exec]") { REQUIRE(readBytes == 12); REQUIRE(outputBuffer.getAvailableReadData() == 12); uint8_t readBuffer[32] = {}; - REQUIRE(outputBuffer.readData(readBuffer, 12) == HasReturnvaluesIF::RETURN_OK); + REQUIRE(outputBuffer.readData(readBuffer, 12) == returnvalue::OK); std::string readString(reinterpret_cast(readBuffer)); std::string cmpString = "Hello World\n"; CHECK(readString == cmpString); outputBuffer.deleteData(12, true); + + // Issues with CI/CD +#if FSFW_CICD_BUILD == 0 // Test more complex command result = cmdExecutor.load("ping -c 1 localhost", false, false); REQUIRE(cmdExecutor.getCurrentState() == CommandExecutor::States::COMMAND_LOADED); - REQUIRE(cmdExecutor.execute() == HasReturnvaluesIF::RETURN_OK); + REQUIRE(cmdExecutor.execute() == returnvalue::OK); REQUIRE(cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING); limitIdx = 0; while (result != CommandExecutor::EXECUTION_FINISHED) { @@ -81,24 +86,34 @@ TEST_CASE("Command Executor", "[cmd-exec]") { REQUIRE(cmdExecutor.getCurrentState() == CommandExecutor::States::IDLE); readBytes = 0; sizesFifo.retrieve(&readBytes); - // That's about the size of the reply - bool beTrue = (readBytes > 200) and (readBytes < 300); - REQUIRE(beTrue); uint8_t largerReadBuffer[1024] = {}; + // That's about the size of the reply + bool beTrue = (readBytes > 100) and (readBytes < 400); + if (not beTrue) { + size_t readLen = outputBuffer.getAvailableReadData(); + if (readLen > sizeof(largerReadBuffer) - 1) { + readLen = sizeof(largerReadBuffer) - 1; + } + outputBuffer.readData(largerReadBuffer, readLen); + std::string readString(reinterpret_cast(largerReadBuffer)); + std::cerr << "Catch2 tag cmd-exec: Read " << readBytes << ": " << std::endl; + std::cerr << readString << std::endl; + } + REQUIRE(beTrue); outputBuffer.readData(largerReadBuffer, readBytes); // You can also check this output in the debugger 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("PING localhost") != std::string::npos); +#endif // Now check failing command result = cmdExecutor.load("false", false, false); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); result = cmdExecutor.execute(); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); - while (result != CommandExecutor::EXECUTION_FINISHED and - result != HasReturnvaluesIF::RETURN_FAILED) { + REQUIRE(result == returnvalue::OK); + while (result != CommandExecutor::EXECUTION_FINISHED and result != returnvalue::FAILED) { limitIdx++; result = cmdExecutor.check(bytesHaveBeenRead); REQUIRE(result != CommandExecutor::COMMAND_ERROR); @@ -106,7 +121,7 @@ TEST_CASE("Command Executor", "[cmd-exec]") { usleep(500); REQUIRE(limitIdx < 500); } - REQUIRE(result == HasReturnvaluesIF::RETURN_FAILED); + REQUIRE(result == returnvalue::FAILED); REQUIRE(cmdExecutor.getLastError() == 1); } diff --git a/unittests/hal/testFsMock.cpp b/unittests/hal/testFsMock.cpp new file mode 100644 index 00000000..2ebcd231 --- /dev/null +++ b/unittests/hal/testFsMock.cpp @@ -0,0 +1,49 @@ +#include + +#include "fsfw/serialize/SerializeIF.h" +#include "mocks/FilesystemMock.h" + +using namespace std; + +TEST_CASE("Filesystem Mock", "[mocks]") { + auto fsMock = FilesystemMock(); + + SECTION("Create File") { + FilesystemParams params("hello.txt"); + CHECK(fsMock.createFile(params) == returnvalue::OK); + auto iter = fsMock.fileMap.find("hello.txt"); + REQUIRE(iter != fsMock.fileMap.end()); + FilesystemMock::FileInfo &stats = iter->second; + CHECK(stats.fileSegQueue.empty()); + CHECK(stats.fileRaw.empty()); + } + + SECTION("Write to File") { + std::string testData = "test data"; + FileOpParams params("hello.txt", testData.size()); + CHECK(fsMock.writeToFile(params, reinterpret_cast(testData.data())) == + returnvalue::OK); + auto iter = fsMock.fileMap.find("hello.txt"); + REQUIRE(iter != fsMock.fileMap.end()); + FilesystemMock::FileInfo &stats = iter->second; + CHECK(not stats.fileSegQueue.empty()); + CHECK(not stats.fileRaw.empty()); + auto &segment = stats.fileSegQueue.back(); + CHECK(segment.offset == 0); + CHECK(std::string(reinterpret_cast(segment.data.data()), segment.data.size()) == + testData); + CHECK(std::string(reinterpret_cast(stats.fileRaw.data()), segment.data.size()) == + testData); + } + + SECTION("Create Directory") { + FilesystemParams params("hello"); + CHECK(fsMock.createDirectory(params) == returnvalue::OK); + REQUIRE(not fsMock.dirMap.empty()); + auto iter = fsMock.dirMap.find("hello"); + REQUIRE(iter != fsMock.dirMap.end()); + auto &dirInfo = iter->second; + CHECK(dirInfo.createCallCount == 1); + CHECK(dirInfo.delCallCount == 0); + } +} \ No newline at end of file diff --git a/unittests/hal/testHostFilesystem.cpp b/unittests/hal/testHostFilesystem.cpp new file mode 100644 index 00000000..e33b30cc --- /dev/null +++ b/unittests/hal/testHostFilesystem.cpp @@ -0,0 +1,228 @@ +#include + +#include +#include +#include +#include + +#include "fsfw/serialize/SerializeIF.h" +#include "fsfw_hal/host/HostFilesystem.h" + +using namespace std; + +TEST_CASE("Host Filesystem", "[hal][host]") { + namespace fs = filesystem; + auto hostFs = HostFilesystem(); + auto tmpDir = fs::temp_directory_path(); + fs::path file0 = tmpDir / "hello.txt"; + fs::path file1 = tmpDir / "hello2.txt"; + fs::path dir0 = tmpDir / "test_dir"; + fs::path fileInDir0 = dir0 / "hello.txt"; + fs::path dirWithParent = dir0 / "test_dir"; + + REQUIRE_NOTHROW(fs::remove(file0)); + REQUIRE_NOTHROW(fs::remove(file1)); + REQUIRE_NOTHROW(fs::remove_all(dir0)); + + SECTION("Create file") { + FilesystemParams params(file0.c_str()); + REQUIRE(hostFs.createFile(params) == returnvalue::OK); + CHECK(fs::is_regular_file(file0)); + REQUIRE(fs::exists(file0)); + } + + SECTION("Remove File") { + FilesystemParams params(file0.c_str()); + REQUIRE(hostFs.createFile(params) == returnvalue::OK); + CHECK(fs::is_regular_file(file0)); + REQUIRE(fs::exists(file0)); + REQUIRE(hostFs.removeFile(file0.c_str()) == returnvalue::OK); + REQUIRE(not fs::exists(file0)); + } + + SECTION("Create Directory") { + FilesystemParams params(dir0.c_str()); + REQUIRE(hostFs.createDirectory(params) == returnvalue::OK); + CHECK(fs::is_directory(dir0)); + REQUIRE(fs::exists(dir0)); + } + + SECTION("Remove Directory") { + FilesystemParams params(dir0.c_str()); + REQUIRE(hostFs.createDirectory(params) == returnvalue::OK); + REQUIRE(fs::exists(dir0)); + REQUIRE(hostFs.removeDirectory(params) == returnvalue::OK); + REQUIRE(not fs::exists(dir0)); + } + + SECTION("Rename File") { + FilesystemParams params(file0.c_str()); + REQUIRE(hostFs.createFile(params) == returnvalue::OK); + CHECK(fs::is_regular_file(file0)); + REQUIRE(fs::exists(file0)); + REQUIRE(hostFs.rename(file0.c_str(), file1.c_str()) == returnvalue::OK); + } + + SECTION("Write To File") { + std::string data = "hello world!"; + FileOpParams params(file0.c_str(), data.size()); + REQUIRE(hostFs.createFile(params.fsParams) == returnvalue::OK); + CHECK(fs::is_regular_file(file0)); + REQUIRE(fs::exists(file0)); + CHECK(hostFs.writeToFile(params, reinterpret_cast(data.c_str())) == + returnvalue::OK); + CHECK(fs::file_size(file0) == data.size()); + ifstream ifile(file0); + std::array readBuf{}; + ifile.read(readBuf.data(), sizeof(readBuf)); + std::string readBackString(readBuf.data()); + CHECK(data == readBackString); + } + + SECTION("Write To File, Check Not Truncated") { + std::random_device dev; + std::mt19937 rng(dev()); + std::uniform_int_distribution distU8(1, 255); + std::array randData{}; + for (uint8_t& byte : randData) { + byte = distU8(rng); + } + FileOpParams params(file0.c_str(), randData.size() - 256); + REQUIRE(hostFs.createFile(params.fsParams) == returnvalue::OK); + CHECK(fs::is_regular_file(file0)); + REQUIRE(fs::exists(file0)); + // Write first file chunk + CHECK(hostFs.writeToFile(params, randData.cbegin()) == returnvalue::OK); + params.offset = 256; + CHECK(hostFs.writeToFile(params, randData.cbegin() + 256) == returnvalue::OK); + std::ifstream rf(file0, ios::binary); + std::array readBack{}; + REQUIRE(std::filesystem::file_size(file0) == 512); + rf.read(reinterpret_cast(readBack.data()), readBack.size()); + for (size_t i = 0; i < 512; i++) { + CHECK(randData[i] == readBack[i]); + } + } + + SECTION("Read From File") { + std::string data = "hello world!"; + FileOpParams params(file0.c_str(), data.size()); + REQUIRE(hostFs.createFile(params.fsParams) == returnvalue::OK); + CHECK(fs::is_regular_file(file0)); + ofstream of(file0); + of.write(data.c_str(), static_cast(data.size())); + of.close(); + CHECK(fs::file_size(file0) == data.size()); + REQUIRE(fs::exists(file0)); + std::array readBuf{}; + uint8_t* readPtr = readBuf.data(); + size_t readSize = 0; + CHECK(hostFs.readFromFile(params, &readPtr, readSize, readBuf.size()) == returnvalue::OK); + std::string readBackString(reinterpret_cast(readBuf.data())); + CHECK(readSize == data.size()); + CHECK(data == readBackString); + } + + SECTION("Invalid Input does not crash") { + FileOpParams params(nullptr, 10); + REQUIRE(hostFs.createFile(params.fsParams) != returnvalue::OK); + REQUIRE(hostFs.createDirectory(params.fsParams) != returnvalue::OK); + REQUIRE(hostFs.createFile(params.fsParams) != returnvalue::OK); + REQUIRE(hostFs.removeDirectory(params.fsParams) != returnvalue::OK); + REQUIRE(hostFs.removeFile(nullptr) != returnvalue::OK); + REQUIRE(hostFs.rename(nullptr, nullptr) != returnvalue::OK); + REQUIRE(hostFs.writeToFile(params, nullptr) != returnvalue::OK); + size_t readLen = 0; + REQUIRE(hostFs.readFromFile(params, nullptr, readLen, 20) != returnvalue::OK); + } + + SECTION("Create File but already exists") { + FilesystemParams params(file0.c_str()); + REQUIRE(hostFs.createFile(params) == returnvalue::OK); + REQUIRE(hostFs.createFile(params) == HasFileSystemIF::FILE_ALREADY_EXISTS); + } + + SECTION("Remove File but does not exist") { + REQUIRE(hostFs.removeFile(file0.c_str()) == HasFileSystemIF::FILE_DOES_NOT_EXIST); + } + + SECTION("Create Directory but already exists") { + FileOpParams params(file0.c_str(), 12); + REQUIRE(hostFs.createDirectory(params.fsParams) == returnvalue::OK); + REQUIRE(hostFs.createDirectory(params.fsParams) == HasFileSystemIF::DIRECTORY_ALREADY_EXISTS); + } + + SECTION("Remove Directory but does not exist") { + FilesystemParams params(dir0.c_str()); + REQUIRE(hostFs.removeDirectory(params) == HasFileSystemIF::DIRECTORY_DOES_NOT_EXIST); + } + + SECTION("Remove Directory but is file") { + ofstream of(file0); + FilesystemParams params(file0.c_str()); + REQUIRE(hostFs.removeDirectory(params) == HasFileSystemIF::NOT_A_DIRECTORY); + } + + SECTION("Read from file but does not exist") { + std::string data = "hello world!"; + FileOpParams params(file0.c_str(), data.size()); + std::array readBuf{}; + uint8_t* readPtr = readBuf.data(); + size_t readSize = 0; + CHECK(hostFs.readFromFile(params, &readPtr, readSize, readBuf.size()) == + HasFileSystemIF::FILE_DOES_NOT_EXIST); + } + + SECTION("Write to file but does not exist") { + std::string data = "hello world!"; + FileOpParams params(file0.c_str(), data.size()); + CHECK(hostFs.writeToFile(params, reinterpret_cast(data.c_str())) == + HasFileSystemIF::FILE_DOES_NOT_EXIST); + } + + SECTION("Remove recursively") { + fs::create_directory(dir0.c_str()); + ofstream of(fileInDir0); + CHECK(fs::is_directory(dir0)); + CHECK(fs::is_regular_file(fileInDir0)); + REQUIRE(hostFs.removeDirectory(FilesystemParams(dir0.c_str()), true) == returnvalue::OK); + CHECK(not fs::is_directory(dir0)); + CHECK(not fs::is_regular_file(fileInDir0)); + } + + SECTION("Non-Recursive Removal Fails") { + fs::create_directory(dir0.c_str()); + ofstream of(fileInDir0); + CHECK(fs::is_directory(dir0)); + CHECK(fs::is_regular_file(fileInDir0)); + REQUIRE(hostFs.removeDirectory(FilesystemParams(dir0.c_str())) == + HasFileSystemIF::DIRECTORY_NOT_EMPTY); + } + + SECTION("Create directory with parent directory") { + CHECK(hostFs.createDirectory(FilesystemParams(dirWithParent.c_str()), true) == returnvalue::OK); + CHECK(fs::is_directory(dir0)); + CHECK(fs::is_directory(dirWithParent)); + } + + SECTION("Read but provided buffer too small") { + std::string data = "hello world!"; + FileOpParams params(file0.c_str(), data.size()); + ofstream of(file0); + of.write(data.c_str(), static_cast(data.size())); + of.close(); + CHECK(fs::file_size(file0) == data.size()); + REQUIRE(fs::exists(file0)); + std::array readBuf{}; + uint8_t* readPtr = readBuf.data(); + size_t readSize = 0; + CHECK(hostFs.readFromFile(params, &readPtr, readSize, 5) == SerializeIF::BUFFER_TOO_SHORT); + readSize = 10; + CHECK(hostFs.readFromFile(params, &readPtr, readSize, readBuf.size()) == + SerializeIF::BUFFER_TOO_SHORT); + } + + REQUIRE_NOTHROW(fs::remove(file0)); + REQUIRE_NOTHROW(fs::remove(file1)); + REQUIRE_NOTHROW(fs::remove_all(dir0)); +} \ No newline at end of file diff --git a/unittests/internalerror/CMakeLists.txt b/unittests/internalerror/CMakeLists.txt new file mode 100644 index 00000000..c02cbafc --- /dev/null +++ b/unittests/internalerror/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE TestInternalErrorReporter.cpp) diff --git a/tests/src/fsfw_tests/unit/internalerror/TestInternalErrorReporter.cpp b/unittests/internalerror/TestInternalErrorReporter.cpp similarity index 82% rename from tests/src/fsfw_tests/unit/internalerror/TestInternalErrorReporter.cpp rename to unittests/internalerror/TestInternalErrorReporter.cpp index 92c3ff22..4562bab4 100644 --- a/tests/src/fsfw_tests/unit/internalerror/TestInternalErrorReporter.cpp +++ b/unittests/internalerror/TestInternalErrorReporter.cpp @@ -8,35 +8,37 @@ #include #include +#include "CatchDefinitions.h" #include "fsfw/action/ActionMessage.h" #include "fsfw/ipc/CommandMessage.h" #include "fsfw/ipc/MessageQueueMessage.h" #include "fsfw/objectmanager/frameworkObjects.h" -#include "fsfw_tests/unit/CatchDefinitions.h" -#include "fsfw_tests/unit/mocks/PeriodicTaskIFMock.h" +#include "mocks/PeriodicTaskIFMock.h" TEST_CASE("Internal Error Reporter", "[TestInternalError]") { - PeriodicTaskMock task(10); + PeriodicTaskMock task(10, nullptr); ObjectManagerIF* manager = ObjectManager::instance(); if (manager == nullptr) { FAIL(); } - InternalErrorReporter* internalErrorReporter = dynamic_cast( + auto* internalErrorReporter = dynamic_cast( ObjectManager::instance()->get(objects::INTERNAL_ERROR_REPORTER)); if (internalErrorReporter == nullptr) { FAIL(); } task.addComponent(objects::INTERNAL_ERROR_REPORTER); + // This calls the initializeAfterTaskCreation function + task.startTask(); MessageQueueIF* testQueue = QueueFactory::instance()->createMessageQueue(1); MessageQueueIF* hkQueue = QueueFactory::instance()->createMessageQueue(1); internalErrorReporter->getSubscriptionInterface()->subscribeForSetUpdateMessage( InternalErrorDataset::ERROR_SET_ID, objects::NO_OBJECT, hkQueue->getId(), true); - StorageManagerIF* ipcStore = ObjectManager::instance()->get(objects::IPC_STORE); + auto* ipcStore = ObjectManager::instance()->get(objects::IPC_STORE); SECTION("MessageQueueFull") { CommandMessage message; ActionMessage::setCompletionReply(&message, 10, true); auto result = hkQueue->sendMessage(testQueue->getId(), &message); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); uint32_t queueHits = 0; uint32_t lostTm = 0; uint32_t storeHits = 0; @@ -47,7 +49,7 @@ TEST_CASE("Internal Error Reporter", "[TestInternalError]") { { CommandMessage hkMessage; result = hkQueue->receiveMessage(&hkMessage); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(hkMessage.getCommand() == HousekeepingMessage::UPDATE_SNAPSHOT_SET); store_address_t storeAddress; gp_id_t gpid = @@ -55,14 +57,14 @@ TEST_CASE("Internal Error Reporter", "[TestInternalError]") { REQUIRE(gpid.objectId == objects::INTERNAL_ERROR_REPORTER); // We need the object ID of the reporter here (NO_OBJECT) InternalErrorDataset dataset(objects::INTERNAL_ERROR_REPORTER); - CCSDSTime::CDS_short time; + CCSDSTime::CDS_short time{}; ConstAccessorPair data = ipcStore->getData(storeAddress); - REQUIRE(data.first == HasReturnvaluesIF::RETURN_OK); + REQUIRE(data.first == returnvalue::OK); HousekeepingSnapshot hkSnapshot(&time, &dataset); const uint8_t* buffer = data.second.data(); size_t size = data.second.size(); result = hkSnapshot.deSerialize(&buffer, &size, SerializeIF::Endianness::MACHINE); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); // Remember the amount of queueHits before to see the increase queueHits = dataset.queueHits.value; lostTm = dataset.tmHits.value; @@ -76,7 +78,7 @@ TEST_CASE("Internal Error Reporter", "[TestInternalError]") { internalErrorReporter->performOperation(0); CommandMessage hkMessage; result = hkQueue->receiveMessage(&hkMessage); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(hkMessage.getCommand() == HousekeepingMessage::UPDATE_SNAPSHOT_SET); store_address_t storeAddress; gp_id_t gpid = @@ -84,7 +86,7 @@ TEST_CASE("Internal Error Reporter", "[TestInternalError]") { REQUIRE(gpid.objectId == objects::INTERNAL_ERROR_REPORTER); ConstAccessorPair data = ipcStore->getData(storeAddress); - REQUIRE(data.first == HasReturnvaluesIF::RETURN_OK); + REQUIRE(data.first == returnvalue::OK); CCSDSTime::CDS_short time; // We need the object ID of the reporter here (NO_OBJECT) InternalErrorDataset dataset(objects::INTERNAL_ERROR_REPORTER); @@ -92,7 +94,7 @@ TEST_CASE("Internal Error Reporter", "[TestInternalError]") { const uint8_t* buffer = data.second.data(); size_t size = data.second.size(); result = hkSnapshot.deSerialize(&buffer, &size, SerializeIF::Endianness::MACHINE); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); // Test that we had one more queueHit REQUIRE(dataset.queueHits.value == (queueHits + 1)); REQUIRE(dataset.tmHits.value == (lostTm + 1)); @@ -105,14 +107,14 @@ TEST_CASE("Internal Error Reporter", "[TestInternalError]") { // Message Queue Id MessageQueueId_t id = internalErrorReporter->getCommandQueue(); REQUIRE(id != MessageQueueIF::NO_QUEUE); - CommandMessage message; + CommandMessage message2; sid_t sid(objects::INTERNAL_ERROR_REPORTER, InternalErrorDataset::ERROR_SET_ID); - HousekeepingMessage::setToggleReportingCommand(&message, sid, true, false); - result = hkQueue->sendMessage(id, &message); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + HousekeepingMessage::setToggleReportingCommand(&message2, sid, true, false); + result = hkQueue->sendMessage(id, &message2); + REQUIRE(result == returnvalue::OK); internalErrorReporter->performOperation(0); } } QueueFactory::instance()->deleteMessageQueue(testQueue); QueueFactory::instance()->deleteMessageQueue(hkQueue); -} \ No newline at end of file +} diff --git a/unittests/lcov_epilog.html b/unittests/lcov_epilog.html new file mode 100644 index 00000000..6ed9a1b2 --- /dev/null +++ b/unittests/lcov_epilog.html @@ -0,0 +1,2 @@ +
Impressum Datenschutz
+ diff --git a/unittests/mocks/AcceptsTcMock.cpp b/unittests/mocks/AcceptsTcMock.cpp new file mode 100644 index 00000000..a9afafd9 --- /dev/null +++ b/unittests/mocks/AcceptsTcMock.cpp @@ -0,0 +1,8 @@ +#include "AcceptsTcMock.h" + +AcceptsTcMock::AcceptsTcMock(const char* name, uint32_t id, MessageQueueId_t queueId) + : name(name), id(id), queueId(queueId) {} + +const char* AcceptsTcMock::getName() const { return name; } +uint32_t AcceptsTcMock::getIdentifier() const { return id; } +MessageQueueId_t AcceptsTcMock::getRequestQueue() const { return queueId; } diff --git a/unittests/mocks/AcceptsTcMock.h b/unittests/mocks/AcceptsTcMock.h new file mode 100644 index 00000000..028b68cd --- /dev/null +++ b/unittests/mocks/AcceptsTcMock.h @@ -0,0 +1,20 @@ +#ifndef FSFW_TESTS_ACCEPTSTCMOCK_H +#define FSFW_TESTS_ACCEPTSTCMOCK_H + +#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h" + +class AcceptsTcMock : public AcceptsTelecommandsIF { + public: + AcceptsTcMock(const char* name, uint32_t id, MessageQueueId_t queueId); + [[nodiscard]] const char* getName() const override; + [[nodiscard]] uint32_t getIdentifier() const override; + [[nodiscard]] MessageQueueId_t getRequestQueue() const override; + + const char* name; + uint32_t id; + MessageQueueId_t queueId; + + private: +}; + +#endif // FSFW_TESTS_ACCEPTSTCMOCK_H diff --git a/unittests/mocks/AcceptsTmMock.cpp b/unittests/mocks/AcceptsTmMock.cpp new file mode 100644 index 00000000..2f718e61 --- /dev/null +++ b/unittests/mocks/AcceptsTmMock.cpp @@ -0,0 +1,13 @@ +#include "AcceptsTmMock.h" + +AcceptsTmMock::AcceptsTmMock(object_id_t registeredId, MessageQueueId_t queueToReturn) + : SystemObject(registeredId), returnedQueue(queueToReturn) {} + +AcceptsTmMock::AcceptsTmMock(MessageQueueId_t queueToReturn) + : SystemObject(objects::NO_OBJECT, false), returnedQueue(queueToReturn) {} + +MessageQueueId_t AcceptsTmMock::getReportReceptionQueue(uint8_t virtualChannel) const { + return returnedQueue; +} + +const char* AcceptsTmMock::getName() const { return "TM Acceptor Mock"; } diff --git a/unittests/mocks/AcceptsTmMock.h b/unittests/mocks/AcceptsTmMock.h new file mode 100644 index 00000000..b12e1094 --- /dev/null +++ b/unittests/mocks/AcceptsTmMock.h @@ -0,0 +1,17 @@ +#ifndef FSFW_TESTS_ACCEPTSTMMOCK_H +#define FSFW_TESTS_ACCEPTSTMMOCK_H + +#include "fsfw/objectmanager/SystemObject.h" +#include "fsfw/tmtcservices/AcceptsTelemetryIF.h" + +class AcceptsTmMock : public SystemObject, public AcceptsTelemetryIF { + public: + AcceptsTmMock(object_id_t registeredId, MessageQueueId_t queueToReturn); + explicit AcceptsTmMock(MessageQueueId_t queueToReturn); + + MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override; + const char* getName() const override; + + MessageQueueId_t returnedQueue; +}; +#endif // FSFW_TESTS_ACCEPTSTMMOCK_H diff --git a/unittests/mocks/CMakeLists.txt b/unittests/mocks/CMakeLists.txt new file mode 100644 index 00000000..bd093da8 --- /dev/null +++ b/unittests/mocks/CMakeLists.txt @@ -0,0 +1,21 @@ +target_sources( + ${FSFW_TEST_TGT} + PRIVATE PowerSwitcherMock.cpp + DeviceHandlerMock.cpp + DeviceFdirMock.cpp + CookieIFMock.cpp + ComIFMock.cpp + MessageQueueMock.cpp + InternalErrorReporterMock.cpp + LocalPoolOwnerBase.cpp + PusVerificationReporterMock.cpp + PusServiceBaseMock.cpp + AcceptsTmMock.cpp + PusDistributorMock.cpp + CcsdsCheckerMock.cpp + AcceptsTcMock.cpp + StorageManagerMock.cpp + FilesystemMock.cpp + EventReportingProxyMock.cpp) + +add_subdirectory(cfdp) diff --git a/unittests/mocks/CcsdsCheckerMock.cpp b/unittests/mocks/CcsdsCheckerMock.cpp new file mode 100644 index 00000000..18c5fb4e --- /dev/null +++ b/unittests/mocks/CcsdsCheckerMock.cpp @@ -0,0 +1,10 @@ +#include "CcsdsCheckerMock.h" + +CcsdsCheckerMock::CcsdsCheckerMock() = default; + +ReturnValue_t CcsdsCheckerMock::checkPacket(const SpacePacketReader& currentPacket, + size_t packetLen) { + checkCallCount++; + checkedPacketLen = packetLen; + return nextResult; +} diff --git a/unittests/mocks/CcsdsCheckerMock.h b/unittests/mocks/CcsdsCheckerMock.h new file mode 100644 index 00000000..bdcd491a --- /dev/null +++ b/unittests/mocks/CcsdsCheckerMock.h @@ -0,0 +1,16 @@ +#ifndef FSFW_TESTS_CCSDSCHECKERMOCK_H +#define FSFW_TESTS_CCSDSCHECKERMOCK_H + +#include "fsfw/tcdistribution/CcsdsPacketCheckIF.h" +class CcsdsCheckerMock : public CcsdsPacketCheckIF { + public: + CcsdsCheckerMock(); + unsigned int checkCallCount = 0; + size_t checkedPacketLen = 0; + ReturnValue_t nextResult = returnvalue::OK; + ReturnValue_t checkPacket(const SpacePacketReader& currentPacket, size_t packetLen) override; + + private: +}; + +#endif // FSFW_TESTS_CCSDSCHECKERMOCK_H diff --git a/unittests/mocks/CdsShortTimestamperMock.h b/unittests/mocks/CdsShortTimestamperMock.h new file mode 100644 index 00000000..1ce13581 --- /dev/null +++ b/unittests/mocks/CdsShortTimestamperMock.h @@ -0,0 +1,82 @@ +#ifndef FSFW_TESTS_CDSSHORTTIMESTAMPERMOCK_H +#define FSFW_TESTS_CDSSHORTTIMESTAMPERMOCK_H + +#include + +#include "fsfw/timemanager/TimeReaderIF.h" +#include "fsfw/timemanager/TimeWriterIF.h" + +class CdsShortTimestamperMock : public TimeWriterIF, public TimeReaderIF { + public: + unsigned int serializeCallCount = 0; + unsigned int deserializeCallCount = 0; + ReturnValue_t lastDeserializeResult = returnvalue::OK; + ReturnValue_t lastSerializeResult = returnvalue::OK; + unsigned int getSizeCallCount = 0; + bool nextSerFails = false; + ReturnValue_t serFailRetval = returnvalue::FAILED; + bool nextDeserFails = false; + ReturnValue_t deserFailRetval = returnvalue::FAILED; + std::array valueToStamp{}; + + CdsShortTimestamperMock() = default; + + explicit CdsShortTimestamperMock(std::array valueToStamp) + : valueToStamp(valueToStamp) {} + + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override { + auto &thisNonConst = const_cast(*this); + thisNonConst.serializeCallCount += 1; + if (nextSerFails) { + return serFailRetval; + } + if (*size + getSerializedSize() > maxSize) { + thisNonConst.lastSerializeResult = SerializeIF::BUFFER_TOO_SHORT; + return lastSerializeResult; + } + std::copy(valueToStamp.begin(), valueToStamp.end(), *buffer); + thisNonConst.lastSerializeResult = returnvalue::OK; + *buffer += getSerializedSize(); + *size += getSerializedSize(); + return lastSerializeResult; + } + [[nodiscard]] size_t getSerializedSize() const override { + auto &thisNonConst = const_cast(*this); + thisNonConst.getSizeCallCount += 1; + return valueToStamp.size(); + } + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override { + deserializeCallCount += 1; + if (nextDeserFails) { + return deserFailRetval; + } + if (*size < 7) { + lastDeserializeResult = SerializeIF::STREAM_TOO_SHORT; + return lastDeserializeResult; + } + std::copy(*buffer, *buffer + getSerializedSize(), valueToStamp.begin()); + return lastDeserializeResult; + } + + [[nodiscard]] size_t getTimestampSize() const override { return getSerializedSize(); } + + void reset() { + serializeCallCount = 0; + getSizeCallCount = 0; + deserializeCallCount = 0; + nextSerFails = false; + nextDeserFails = false; + lastSerializeResult = returnvalue::OK; + lastDeserializeResult = returnvalue::OK; + deserFailRetval = returnvalue::FAILED; + serFailRetval = returnvalue::FAILED; + } + + timeval &getTime() override { return dummyTime; } + + private: + timeval dummyTime{}; +}; +#endif // FSFW_TESTS_CDSSHORTTIMESTAMPERMOCK_H diff --git a/unittests/mocks/ComIFMock.cpp b/unittests/mocks/ComIFMock.cpp new file mode 100644 index 00000000..d51339dc --- /dev/null +++ b/unittests/mocks/ComIFMock.cpp @@ -0,0 +1,46 @@ +#include "ComIFMock.h" + +#include "DeviceHandlerMock.h" + +ComIFMock::ComIFMock(object_id_t objectId) : SystemObject(objectId) {} + +ComIFMock::~ComIFMock() {} + +ReturnValue_t ComIFMock::initializeInterface(CookieIF *cookie) { return returnvalue::OK; } + +ReturnValue_t ComIFMock::sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen) { + data = *sendData; + return returnvalue::OK; +} + +ReturnValue_t ComIFMock::getSendSuccess(CookieIF *cookie) { return returnvalue::OK; } + +ReturnValue_t ComIFMock::requestReceiveMessage(CookieIF *cookie, size_t requestLen) { + return returnvalue::OK; +} + +ReturnValue_t ComIFMock::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) { + switch (testCase) { + case TestCase::MISSED_REPLY: { + *size = 0; + return returnvalue::OK; + } + case TestCase::SIMPLE_COMMAND_NOMINAL: { + *size = 1; + data = DeviceHandlerMock::SIMPLE_COMMAND_DATA; + *buffer = &data; + break; + } + case TestCase::PERIODIC_REPLY_NOMINAL: { + *size = 1; + data = DeviceHandlerMock::PERIODIC_REPLY_DATA; + *buffer = &data; + break; + } + default: + break; + } + return returnvalue::OK; +} + +void ComIFMock::setTestCase(TestCase testCase_) { testCase = testCase_; } diff --git a/unittests/mocks/ComIFMock.h b/unittests/mocks/ComIFMock.h new file mode 100644 index 00000000..d16cc0a6 --- /dev/null +++ b/unittests/mocks/ComIFMock.h @@ -0,0 +1,37 @@ +#ifndef TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_COMIFMOCK_H_ +#define TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_COMIFMOCK_H_ + +#include +#include + +/** + * @brief The ComIFMock supports the simulation of various device communication error cases + * like incomplete or wrong replies and can be used to test the + * DeviceHandlerBase. + */ +class ComIFMock : public DeviceCommunicationIF, public SystemObject { + public: + enum class TestCase { SIMPLE_COMMAND_NOMINAL, PERIODIC_REPLY_NOMINAL, MISSED_REPLY }; + + ComIFMock(object_id_t objectId); + virtual ~ComIFMock(); + + virtual ReturnValue_t initializeInterface(CookieIF *cookie) override; + virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t *sendData, + size_t sendLen) override; + virtual ReturnValue_t getSendSuccess(CookieIF *cookie) override; + virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) override; + virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, + size_t *size) override; + void setTestCase(TestCase testCase_); + + private: + TestCase testCase = TestCase::SIMPLE_COMMAND_NOMINAL; + + static const uint8_t SIMPLE_COMMAND_DATA = 1; + static const uint8_t PERIODIC_REPLY_DATA = 2; + + uint8_t data = 0; +}; + +#endif /* TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_COMIFMOCK_H_ */ diff --git a/unittests/mocks/CookieIFMock.cpp b/unittests/mocks/CookieIFMock.cpp new file mode 100644 index 00000000..1ae2eb6e --- /dev/null +++ b/unittests/mocks/CookieIFMock.cpp @@ -0,0 +1,5 @@ +#include "CookieIFMock.h" + +CookieIFMock::CookieIFMock() {} + +CookieIFMock::~CookieIFMock() {} diff --git a/unittests/mocks/CookieIFMock.h b/unittests/mocks/CookieIFMock.h new file mode 100644 index 00000000..1243b0a7 --- /dev/null +++ b/unittests/mocks/CookieIFMock.h @@ -0,0 +1,12 @@ +#ifndef TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_COOKIEIFMOCK_H_ +#define TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_COOKIEIFMOCK_H_ + +#include "fsfw/devicehandlers/CookieIF.h" + +class CookieIFMock : public CookieIF { + public: + CookieIFMock(); + virtual ~CookieIFMock(); +}; + +#endif /* TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_COOKIEIFMOCK_H_ */ diff --git a/unittests/mocks/DeviceFdirMock.cpp b/unittests/mocks/DeviceFdirMock.cpp new file mode 100644 index 00000000..5dcd985d --- /dev/null +++ b/unittests/mocks/DeviceFdirMock.cpp @@ -0,0 +1,16 @@ +#include "DeviceFdirMock.h" + +DeviceFdirMock::DeviceFdirMock(object_id_t owner, object_id_t parent) + : DeviceHandlerFailureIsolation(owner, parent) {} + +DeviceFdirMock::~DeviceFdirMock() = default; + +uint32_t DeviceFdirMock::getMissedReplyCount() { + ParameterWrapper parameterWrapper; + this->getParameter(MISSED_REPLY_DOMAIN_ID, + static_cast(FaultCounter::ParameterIds::FAULT_COUNT), + ¶meterWrapper, nullptr, 0); + uint32_t missedReplyCount = 0; + parameterWrapper.getElement(&missedReplyCount); + return missedReplyCount; +} diff --git a/unittests/mocks/DeviceFdirMock.h b/unittests/mocks/DeviceFdirMock.h new file mode 100644 index 00000000..b314fc98 --- /dev/null +++ b/unittests/mocks/DeviceFdirMock.h @@ -0,0 +1,18 @@ +#ifndef TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEFDIRMOCK_H_ +#define TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEFDIRMOCK_H_ + +#include "fsfw/devicehandlers/DeviceHandlerFailureIsolation.h" + +class DeviceFdirMock : public DeviceHandlerFailureIsolation { + public: + DeviceFdirMock(object_id_t owner, object_id_t parent); + virtual ~DeviceFdirMock(); + + uint32_t getMissedReplyCount(); + + private: + static const uint8_t STRANGE_REPLY_DOMAIN_ID = 0xF0; + static const uint8_t MISSED_REPLY_DOMAIN_ID = 0xF1; +}; + +#endif /* TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEFDIRMOCK_H_ */ diff --git a/unittests/mocks/DeviceHandlerMock.cpp b/unittests/mocks/DeviceHandlerMock.cpp new file mode 100644 index 00000000..ef0a23d8 --- /dev/null +++ b/unittests/mocks/DeviceHandlerMock.cpp @@ -0,0 +1,103 @@ +#include "DeviceHandlerMock.h" + +#include + +DeviceHandlerMock::DeviceHandlerMock(object_id_t objectId, object_id_t deviceCommunication, + CookieIF *comCookie, FailureIsolationBase *fdirInstance) + : DeviceHandlerBase(objectId, deviceCommunication, comCookie, fdirInstance) { + mode = MODE_ON; +} + +DeviceHandlerMock::~DeviceHandlerMock() = default; + +void DeviceHandlerMock::doStartUp() { setMode(_MODE_TO_ON); } + +void DeviceHandlerMock::doShutDown() { setMode(_MODE_POWER_DOWN); } + +ReturnValue_t DeviceHandlerMock::buildNormalDeviceCommand(DeviceCommandId_t *id) { + return NOTHING_TO_SEND; +} + +ReturnValue_t DeviceHandlerMock::buildTransitionDeviceCommand(DeviceCommandId_t *id) { + return NOTHING_TO_SEND; +} + +ReturnValue_t DeviceHandlerMock::buildCommandFromCommand(DeviceCommandId_t deviceCommand, + const uint8_t *commandData, + size_t commandDataLen) { + switch (deviceCommand) { + case SIMPLE_COMMAND: { + commandBuffer[0] = SIMPLE_COMMAND_DATA; + rawPacket = commandBuffer; + rawPacketLen = sizeof(SIMPLE_COMMAND_DATA); + break; + } + default: + WARN("DeviceHandlerMock::buildCommandFromCommand: Invalid device command"); + break; + } + return returnvalue::OK; +} + +ReturnValue_t DeviceHandlerMock::scanForReply(const uint8_t *start, size_t len, + DeviceCommandId_t *foundId, size_t *foundLen) { + switch (*start) { + case SIMPLE_COMMAND_DATA: { + *foundId = SIMPLE_COMMAND; + *foundLen = sizeof(SIMPLE_COMMAND_DATA); + return returnvalue::OK; + break; + } + case PERIODIC_REPLY_DATA: { + *foundId = PERIODIC_REPLY; + *foundLen = sizeof(PERIODIC_REPLY_DATA); + return returnvalue::OK; + break; + } + default: + break; + } + return returnvalue::FAILED; +} + +ReturnValue_t DeviceHandlerMock::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { + switch (id) { + case SIMPLE_COMMAND: + case PERIODIC_REPLY: { + periodicReplyReceived = true; + break; + } + default: + break; + } + return returnvalue::OK; +} + +void DeviceHandlerMock::fillCommandAndReplyMap() { + insertInCommandAndReplyMap(SIMPLE_COMMAND, 0, nullptr, 0, false, false, 0, + &simpleCommandReplyTimeout); + insertInCommandAndReplyMap(PERIODIC_REPLY, 0, nullptr, 0, true, false, 0, + &periodicReplyCountdown); +} + +uint32_t DeviceHandlerMock::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 500; } + +void DeviceHandlerMock::changePeriodicReplyCountdown(uint32_t timeout) { + periodicReplyCountdown.setTimeout(timeout); +} + +void DeviceHandlerMock::changeSimpleCommandReplyCountdown(uint32_t timeout) { + simpleCommandReplyTimeout.setTimeout(timeout); +} + +void DeviceHandlerMock::resetPeriodicReplyState() { periodicReplyReceived = false; } + +bool DeviceHandlerMock::getPeriodicReplyReceived() { return periodicReplyReceived; } + +ReturnValue_t DeviceHandlerMock::enablePeriodicReply(DeviceCommandId_t replyId) { + return updatePeriodicReply(true, replyId); +} + +ReturnValue_t DeviceHandlerMock::disablePeriodicReply(DeviceCommandId_t replyId) { + return updatePeriodicReply(false, replyId); +} diff --git a/unittests/mocks/DeviceHandlerMock.h b/unittests/mocks/DeviceHandlerMock.h new file mode 100644 index 00000000..ef1649c3 --- /dev/null +++ b/unittests/mocks/DeviceHandlerMock.h @@ -0,0 +1,46 @@ +#ifndef TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEHANDLERMOCK_H_ +#define TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEHANDLERMOCK_H_ + +#include + +class DeviceHandlerMock : public DeviceHandlerBase { + public: + static const DeviceCommandId_t SIMPLE_COMMAND = 1; + static const DeviceCommandId_t PERIODIC_REPLY = 2; + + static const uint8_t SIMPLE_COMMAND_DATA = 1; + static const uint8_t PERIODIC_REPLY_DATA = 2; + + DeviceHandlerMock(object_id_t objectId, object_id_t deviceCommunication, CookieIF *comCookie, + FailureIsolationBase *fdirInstance); + virtual ~DeviceHandlerMock(); + void changePeriodicReplyCountdown(uint32_t timeout); + void changeSimpleCommandReplyCountdown(uint32_t timeout); + void resetPeriodicReplyState(); + bool getPeriodicReplyReceived(); + ReturnValue_t enablePeriodicReply(DeviceCommandId_t replyId); + ReturnValue_t disablePeriodicReply(DeviceCommandId_t replyId); + + protected: + void doStartUp() override; + void doShutDown() override; + ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override; + ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) override; + ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData, + size_t commandDataLen) override; + ReturnValue_t scanForReply(const uint8_t *start, size_t len, DeviceCommandId_t *foundId, + size_t *foundLen) override; + ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override; + void fillCommandAndReplyMap() override; + uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; + + private: + Countdown simpleCommandReplyTimeout = Countdown(1000); + Countdown periodicReplyCountdown = Countdown(1000); + + uint8_t commandBuffer[1]; + + bool periodicReplyReceived = false; +}; + +#endif /* TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEHANDLERMOCK_H_ */ diff --git a/unittests/mocks/EventReportingProxyMock.cpp b/unittests/mocks/EventReportingProxyMock.cpp new file mode 100644 index 00000000..cb4f6d93 --- /dev/null +++ b/unittests/mocks/EventReportingProxyMock.cpp @@ -0,0 +1,6 @@ +#include "EventReportingProxyMock.h" + +void EventReportingProxyMock::forwardEvent(Event event, uint32_t parameter1, + uint32_t parameter2) const { + eventQueue.emplace(event, parameter1, parameter2); +} diff --git a/unittests/mocks/EventReportingProxyMock.h b/unittests/mocks/EventReportingProxyMock.h new file mode 100644 index 00000000..c04942c3 --- /dev/null +++ b/unittests/mocks/EventReportingProxyMock.h @@ -0,0 +1,21 @@ +#ifndef FSFW_TESTS_EVENTREPORTPROXYMOCK_H +#define FSFW_TESTS_EVENTREPORTPROXYMOCK_H + +#include + +#include "fsfw/events/EventReportingProxyIF.h" + +class EventReportingProxyMock : public EventReportingProxyIF { + public: + void forwardEvent(Event event, uint32_t parameter1, uint32_t parameter2) const override; + + struct EventInfo { + EventInfo(Event event, uint32_t p1, uint32_t p2) : event(event), p1(p1), p2(p2) {} + + Event event; + uint32_t p1; + uint32_t p2; + }; + mutable std::queue eventQueue; +}; +#endif // FSFW_TESTS_EVENTREPORTPROXYMOCK_H diff --git a/unittests/mocks/FilesystemMock.cpp b/unittests/mocks/FilesystemMock.cpp new file mode 100644 index 00000000..bf0c3bf6 --- /dev/null +++ b/unittests/mocks/FilesystemMock.cpp @@ -0,0 +1,140 @@ +#include "FilesystemMock.h" + +#include + +#include "fsfw/serialize/SerializeIF.h" + +ReturnValue_t FilesystemMock::feedFile(const std::string &filename, std::ifstream &file) { + if (not std::filesystem::exists(filename)) { + return returnvalue::FAILED; + } + size_t fileSize = std::filesystem::file_size(filename); + FileOpParams params(filename.c_str(), fileSize); + std::vector rawData(fileSize); + file.read(reinterpret_cast(rawData.data()), static_cast(rawData.size())); + createOrAddToFile(params, rawData.data()); + return returnvalue::OK; +} + +ReturnValue_t FilesystemMock::writeToFile(FileOpParams params, const uint8_t *data) { + createOrAddToFile(params, data); + return returnvalue::OK; +} + +ReturnValue_t FilesystemMock::readFromFile(FileOpParams params, uint8_t **buffer, size_t &readSize, + size_t maxSize) { + std::string filename(params.path()); + auto iter = fileMap.find(filename); + if (iter == fileMap.end()) { + return HasFileSystemIF::FILE_DOES_NOT_EXIST; + } else { + FileInfo &info = iter->second; + size_t readLen = params.size; + if (params.offset + params.size > info.fileRaw.size()) { + if (params.offset > info.fileRaw.size()) { + return returnvalue::OK; + } + readLen = info.fileRaw.size() - params.offset; + } + if (readSize + readLen > maxSize) { + return SerializeIF::STREAM_TOO_SHORT; + } + std::copy(info.fileRaw.data() + params.offset, info.fileRaw.data() + readLen, *buffer); + *buffer += readLen; + readSize += readLen; + } + return returnvalue::OK; +} + +ReturnValue_t FilesystemMock::createFile(FilesystemParams params, const uint8_t *data, + size_t size) { + FileOpParams params2(params.path, size); + createOrAddToFile(params2, data); + return returnvalue::OK; +} + +ReturnValue_t FilesystemMock::removeFile(const char *path, FileSystemArgsIF *args) { + std::string filename(path); + auto iter = fileMap.find(filename); + if (iter == fileMap.end()) { + return HasFileSystemIF::FILE_DOES_NOT_EXIST; + } else { + fileMap.erase(iter); + return returnvalue::OK; + } +} + +ReturnValue_t FilesystemMock::createDirectory(FilesystemParams params, bool createParentDirs) { + std::string dirPath = params.path; + dirMap[dirPath].createCallCount++; + dirMap[dirPath].wihParentDir.push(createParentDirs); + return returnvalue::OK; +} + +ReturnValue_t FilesystemMock::removeDirectory(FilesystemParams params, bool deleteRecurively) { + std::string dirPath = params.path; + dirMap[dirPath].delCallCount++; + dirMap[dirPath].recursiveDeletion.push(deleteRecurively); + return returnvalue::OK; +} + +ReturnValue_t FilesystemMock::rename(const char *oldPath, const char *newPath, + FileSystemArgsIF *args) { + renameQueue.push(RenameInfo(oldPath, newPath)); + return returnvalue::OK; +} + +void FilesystemMock::createOrAddToFile(FileOpParams params, const uint8_t *data) { + std::string filename(params.path()); + auto iter = fileMap.find(filename); + if (iter == fileMap.end()) { + FileSegmentQueue queue; + if (params.size > 0) { + queue.push(FileWriteInfo(filename, params.offset, data, params.size)); + } + FileInfo info; + info.fileSegQueue = queue; + if (data != nullptr) { + info.fileRaw.insert(info.fileRaw.end(), data, data + params.size); + } + fileMap.emplace(filename, info); + } else { + FileInfo &info = iter->second; + info.fileSegQueue.push(FileWriteInfo(filename, params.offset, data, params.size)); + if (data == nullptr) { + return; + } + // Easiest case: append data to the end + if (params.offset == info.fileRaw.size()) { + info.fileRaw.insert(info.fileRaw.end(), data, data + params.size); + } else { + size_t totalNewLen = params.offset + params.size; + if (totalNewLen > info.fileRaw.size()) { + info.fileRaw.resize(params.offset + params.size); + } + std::copy(data, data + params.size, + info.fileRaw.begin() + static_cast(params.offset)); + } + } +} + +void FilesystemMock::reset() { + fileMap.clear(); + dirMap.clear(); + std::queue empty; + std::swap(renameQueue, empty); +} + +bool FilesystemMock::fileExists(FilesystemParams params) { + std::string filename(params.path); + auto iter = fileMap.find(filename); + if (iter == fileMap.end()) { + return false; + } + return true; +} + +ReturnValue_t FilesystemMock::truncateFile(FilesystemParams params) { + truncateCalledOnFile = params.path; + return returnvalue::OK; +} diff --git a/unittests/mocks/FilesystemMock.h b/unittests/mocks/FilesystemMock.h new file mode 100644 index 00000000..74221d70 --- /dev/null +++ b/unittests/mocks/FilesystemMock.h @@ -0,0 +1,81 @@ +#ifndef FSFW_MOCKS_FILESYSTEMMOCK_H +#define FSFW_MOCKS_FILESYSTEMMOCK_H + +#include +#include +#include +#include +#include + +#include "fsfw/filesystem.h" + +/** + * This mock models a filesystem in the RAM. It can be used to verify correct behaviour of + * a component using a filesystem without relying on an actual OS filesystem implementation. + * + * Please note that this object does not actually check paths for validity. The file API was + * built in a way to allow reading a file back after it was written while also remembering + * the specific file segments which were inserted in write calls. + */ +class FilesystemMock : public HasFileSystemIF { + public: + struct FileWriteInfo { + FileWriteInfo(std::string filename, size_t offset, const uint8_t *data, size_t len) + : filename(std::move(filename)), offset(offset) { + this->data.insert(this->data.end(), data, data + len); + } + std::string filename; + size_t offset; + std::vector data; + }; + using FileSegmentQueue = std::queue; + + struct FileInfo { + FileSegmentQueue fileSegQueue; + std::vector fileRaw; + }; + + std::map fileMap; + + struct DirInfo { + size_t createCallCount = 0; + size_t delCallCount = 0; + std::queue wihParentDir; + std::queue recursiveDeletion; + }; + std::map dirMap; + + struct RenameInfo { + RenameInfo(std::string oldName, std::string newName) + : oldName(std::move(oldName)), newName(std::move(newName)) {} + + std::string oldName; + std::string newName; + }; + std::queue renameQueue; + std::string truncateCalledOnFile; + ReturnValue_t feedFile(const std::string &filename, std::ifstream &file); + + bool fileExists(FilesystemParams params) override; + ReturnValue_t truncateFile(FilesystemParams params) override; + + ReturnValue_t writeToFile(FileOpParams params, const uint8_t *data) override; + ReturnValue_t readFromFile(FileOpParams params, uint8_t **buffer, size_t &readSize, + size_t maxSize) override; + ReturnValue_t createFile(FilesystemParams params, const uint8_t *data, size_t size) override; + ReturnValue_t removeFile(const char *path, FileSystemArgsIF *args) override; + ReturnValue_t createDirectory(FilesystemParams params, bool createParentDirs) override; + ReturnValue_t removeDirectory(FilesystemParams params, bool deleteRecurively) override; + ReturnValue_t rename(const char *oldPath, const char *newPath, FileSystemArgsIF *args) override; + + void reset(); + + using HasFileSystemIF::createDirectory; + using HasFileSystemIF::createFile; + using HasFileSystemIF::readFromFile; + + private: + void createOrAddToFile(FileOpParams params, const uint8_t *data); +}; + +#endif // FSFW_MOCKS_FILESYSTEMMOCK_H diff --git a/unittests/mocks/HkReceiverMock.h b/unittests/mocks/HkReceiverMock.h new file mode 100644 index 00000000..33a43a81 --- /dev/null +++ b/unittests/mocks/HkReceiverMock.h @@ -0,0 +1,16 @@ +#ifndef FSFW_UNITTEST_TESTS_MOCKS_HKRECEIVERMOCK_H_ +#define FSFW_UNITTEST_TESTS_MOCKS_HKRECEIVERMOCK_H_ + +#include + +class HkReceiverMock : public AcceptsHkPacketsIF { + public: + explicit HkReceiverMock(MessageQueueId_t queueId) : queueId(queueId) {} + + [[nodiscard]] MessageQueueId_t getHkQueue() const override { return queueId; } + + private: + MessageQueueId_t queueId; +}; + +#endif /* FSFW_UNITTEST_TESTS_MOCKS_HKRECEIVERMOCK_H_ */ diff --git a/unittests/mocks/InternalErrorReporterMock.cpp b/unittests/mocks/InternalErrorReporterMock.cpp new file mode 100644 index 00000000..f53a1ed4 --- /dev/null +++ b/unittests/mocks/InternalErrorReporterMock.cpp @@ -0,0 +1,13 @@ +#include "InternalErrorReporterMock.h" + +InternalErrorReporterMock::InternalErrorReporterMock() = default; + +void InternalErrorReporterMock::queueMessageNotSent() { queueMsgNotSentCallCnt++; } +void InternalErrorReporterMock::lostTm() { lostTmCallCnt++; } +void InternalErrorReporterMock::storeFull() { storeFullCallCnt++; } + +void InternalErrorReporterMock::reset() { + queueMsgNotSentCallCnt = 0; + lostTmCallCnt = 0; + storeFullCallCnt = 0; +} diff --git a/unittests/mocks/InternalErrorReporterMock.h b/unittests/mocks/InternalErrorReporterMock.h new file mode 100644 index 00000000..e1ad35ae --- /dev/null +++ b/unittests/mocks/InternalErrorReporterMock.h @@ -0,0 +1,19 @@ +#ifndef FSFW_TESTS_INTERNALERRORREPORTERMOCK_H +#define FSFW_TESTS_INTERNALERRORREPORTERMOCK_H + +#include "fsfw/internalerror/InternalErrorReporterIF.h" + +class InternalErrorReporterMock : public InternalErrorReporterIF { + public: + unsigned int queueMsgNotSentCallCnt = 0; + unsigned int lostTmCallCnt = 0; + unsigned int storeFullCallCnt = 0; + InternalErrorReporterMock(); + void reset(); + + private: + void queueMessageNotSent() override; + void lostTm() override; + void storeFull() override; +}; +#endif // FSFW_TESTS_INTERNALERRORREPORTERMOCK_H diff --git a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolOwnerBase.cpp b/unittests/mocks/LocalPoolOwnerBase.cpp similarity index 70% rename from tests/src/fsfw_tests/unit/datapoollocal/LocalPoolOwnerBase.cpp rename to unittests/mocks/LocalPoolOwnerBase.cpp index 6f054893..e1f2f0c5 100644 --- a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolOwnerBase.cpp +++ b/unittests/mocks/LocalPoolOwnerBase.cpp @@ -1,32 +1,31 @@ #include "LocalPoolOwnerBase.h" -LocalPoolOwnerBase::LocalPoolOwnerBase(object_id_t objectId) - : SystemObject(objectId), poolManager(this, messageQueue), dataset(this, lpool::testSetId) { - messageQueue = new MessageQueueMockBase(); -} +LocalPoolOwnerBase::LocalPoolOwnerBase(MessageQueueIF &queue, object_id_t objectId) + : SystemObject(objectId), + queue(queue), + poolManager(this, &queue), + dataset(this, lpool::testSetId) {} -LocalPoolOwnerBase::~LocalPoolOwnerBase() { - QueueFactory::instance()->deleteMessageQueue(messageQueue); -} +LocalPoolOwnerBase::~LocalPoolOwnerBase() = default; ReturnValue_t LocalPoolOwnerBase::initializeHkManager() { if (not initialized) { initialized = true; - return poolManager.initialize(messageQueue); + return poolManager.initialize(&queue); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } ReturnValue_t LocalPoolOwnerBase::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { // Default initialization empty for now. - localDataPoolMap.emplace(lpool::uint8VarId, new PoolEntry({0})); - localDataPoolMap.emplace(lpool::floatVarId, new PoolEntry({0})); - localDataPoolMap.emplace(lpool::uint32VarId, new PoolEntry({0})); + localDataPoolMap.emplace(lpool::uint8VarId, &u8PoolEntry); + localDataPoolMap.emplace(lpool::floatVarId, &floatPoolEntry); + localDataPoolMap.emplace(lpool::uint32VarId, &u32PoolEntry); - localDataPoolMap.emplace(lpool::uint16Vec3Id, new PoolEntry({0, 0, 0})); - localDataPoolMap.emplace(lpool::int64Vec2Id, new PoolEntry({0, 0})); - return HasReturnvaluesIF::RETURN_OK; + localDataPoolMap.emplace(lpool::uint16Vec3Id, &u16VecPoolEntry); + localDataPoolMap.emplace(lpool::int64Vec2Id, &i64VecPoolEntry); + return returnvalue::OK; } LocalPoolObjectBase *LocalPoolOwnerBase::getPoolObjectHandle(lp_id_t localPoolId) { @@ -47,10 +46,10 @@ LocalPoolObjectBase *LocalPoolOwnerBase::getPoolObjectHandle(lp_id_t localPoolId ReturnValue_t LocalPoolOwnerBase::reset() { resetSubscriptionList(); - ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t status = returnvalue::OK; { PoolReadGuard readHelper(&dataset); - if (readHelper.getReadResult() != HasReturnvaluesIF::RETURN_OK) { + if (readHelper.getReadResult() != returnvalue::OK) { status = readHelper.getReadResult(); } dataset.localPoolVarUint8.value = 0; @@ -63,7 +62,7 @@ ReturnValue_t LocalPoolOwnerBase::reset() { { PoolReadGuard readHelper(&testUint32); - if (readHelper.getReadResult() != HasReturnvaluesIF::RETURN_OK) { + if (readHelper.getReadResult() != returnvalue::OK) { status = readHelper.getReadResult(); } testUint32.value = 0; @@ -72,7 +71,7 @@ ReturnValue_t LocalPoolOwnerBase::reset() { { PoolReadGuard readHelper(&testInt64Vec); - if (readHelper.getReadResult() != HasReturnvaluesIF::RETURN_OK) { + if (readHelper.getReadResult() != returnvalue::OK) { status = readHelper.getReadResult(); } testInt64Vec.value[0] = 0; @@ -90,7 +89,7 @@ bool LocalPoolOwnerBase::changedDataSetCallbackWasCalled(sid_t &sid, store_addre sid = changedDatasetSid; storeId = storeIdForChangedSet; this->changedDatasetSid.raw = sid_t::INVALID_SID; - this->storeIdForChangedSet = storeId::INVALID_STORE_ADDRESS; + this->storeIdForChangedSet = store_address_t::invalid(); return condition; } @@ -108,7 +107,7 @@ bool LocalPoolOwnerBase::changedVariableCallbackWasCalled(gp_id_t &gpid, store_a gpid = changedPoolVariableGpid; storeId = storeIdForChangedVariable; this->changedPoolVariableGpid.raw = gp_id_t::INVALID_GPID; - this->storeIdForChangedVariable = storeId::INVALID_STORE_ADDRESS; + this->storeIdForChangedVariable = store_address_t::invalid(); return condition; } @@ -117,7 +116,7 @@ ReturnValue_t LocalPoolOwnerBase::initializeHkManagerAfterTaskCreation() { initializedAfterTaskCreation = true; return poolManager.initializeAfterTaskCreation(); } - return HasReturnvaluesIF::RETURN_OK; + return returnvalue::OK; } void LocalPoolOwnerBase::handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId, @@ -125,3 +124,5 @@ void LocalPoolOwnerBase::handleChangedPoolVariable(gp_id_t globPoolId, store_add this->changedPoolVariableGpid = globPoolId; this->storeIdForChangedVariable = storeId; } + +void LocalPoolOwnerBase::setHkDestId(MessageQueueId_t id) { poolManager.setHkDestinationId(id); } diff --git a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolOwnerBase.h b/unittests/mocks/LocalPoolOwnerBase.h similarity index 64% rename from tests/src/fsfw_tests/unit/datapoollocal/LocalPoolOwnerBase.h rename to unittests/mocks/LocalPoolOwnerBase.h index 0bcebc00..f1d1225f 100644 --- a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolOwnerBase.h +++ b/unittests/mocks/LocalPoolOwnerBase.h @@ -10,7 +10,8 @@ #include #include -#include "../mocks/MessageQueueMockBase.h" +#include "fsfw/datapool/PoolEntry.h" +#include "mocks/MessageQueueMock.h" #include "tests/TestsConfig.h" namespace lpool { @@ -64,26 +65,29 @@ class LocalPoolTestDataSet : public LocalDataSet { class LocalPoolOwnerBase : public SystemObject, public HasLocalDataPoolIF { public: - LocalPoolOwnerBase(object_id_t objectId = objects::TEST_LOCAL_POOL_OWNER_BASE); + explicit LocalPoolOwnerBase(MessageQueueIF& queue, + object_id_t objectId = objects::TEST_LOCAL_POOL_OWNER_BASE); - ~LocalPoolOwnerBase(); + ~LocalPoolOwnerBase() override; - object_id_t getObjectId() const override { return SystemObject::getObjectId(); } + [[nodiscard]] object_id_t getObjectId() const override { return SystemObject::getObjectId(); } ReturnValue_t initializeHkManager(); + void setHkDestId(MessageQueueId_t id); + ReturnValue_t initializeHkManagerAfterTaskCreation(); /** Command queue for housekeeping messages. */ - MessageQueueId_t getCommandQueue() const override { return messageQueue->getId(); } + [[nodiscard]] MessageQueueId_t getCommandQueue() const override { return queue.getId(); } // This is called by initializeAfterTaskCreation of the HK manager. - virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, - LocalDataPoolManager& poolManager) override; + ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; LocalDataPoolManager* getHkManagerHandle() override { return &poolManager; } - dur_millis_t getPeriodicOperationFrequency() const override { return 200; } + [[nodiscard]] dur_millis_t getPeriodicOperationFrequency() const override { return 200; } /** * This function is used by the pool manager to get a valid dataset @@ -91,41 +95,54 @@ class LocalPoolOwnerBase : public SystemObject, public HasLocalDataPoolIF { * @param sid Corresponding structure ID * @return */ - virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override { return &dataset; } + LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override { return &dataset; } - virtual LocalPoolObjectBase* getPoolObjectHandle(lp_id_t localPoolId) override; + LocalPoolObjectBase* getPoolObjectHandle(lp_id_t localPoolId) override; - MessageQueueMockBase* getMockQueueHandle() const { - return dynamic_cast(messageQueue); + [[nodiscard]] MessageQueueMock& getMockQueueHandle() const { + return dynamic_cast(queue); } ReturnValue_t subscribePeriodicHk(bool enableReporting) { - return poolManager.subscribeForPeriodicPacket(lpool::testSid, enableReporting, 0.2, false); + return poolManager.subscribeForRegularPeriodicPacket( + subdp::RegularHkPeriodicParams(lpool::testSid, enableReporting, 0.2)); } - ReturnValue_t subscribeWrapperSetUpdate() { + ReturnValue_t subscribeWrapperSetUpdate(MessageQueueId_t receiverId) { return poolManager.subscribeForSetUpdateMessage(lpool::testSetId, objects::NO_OBJECT, - objects::HK_RECEIVER_MOCK, false); + receiverId, false); } - ReturnValue_t subscribeWrapperSetUpdateSnapshot() { + ReturnValue_t subscribeWrapperSetUpdateSnapshot(MessageQueueId_t receiverId) { return poolManager.subscribeForSetUpdateMessage(lpool::testSetId, objects::NO_OBJECT, - objects::HK_RECEIVER_MOCK, true); + receiverId, true); } - ReturnValue_t subscribeWrapperSetUpdateHk(bool diagnostics = false) { - return poolManager.subscribeForUpdatePacket(lpool::testSid, diagnostics, false, - objects::HK_RECEIVER_MOCK); + ReturnValue_t subscribeWrapperSetUpdateHk(bool diagnostics = false, + AcceptsHkPacketsIF* receiver = nullptr) { + if (diagnostics) { + auto params = subdp::DiagnosticsHkUpdateParams(lpool::testSid, true); + if (receiver != nullptr) { + params.receiver = receiver->getHkQueue(); + } + return poolManager.subscribeForDiagUpdatePacket(params); + } else { + auto params = subdp::RegularHkUpdateParams(lpool::testSid, true); + if (receiver != nullptr) { + params.receiver = receiver->getHkQueue(); + } + return poolManager.subscribeForRegularUpdatePacket(params); + } } - ReturnValue_t subscribeWrapperVariableUpdate(lp_id_t localPoolId) { + ReturnValue_t subscribeWrapperVariableUpdate(MessageQueueId_t receiverId, lp_id_t localPoolId) { return poolManager.subscribeForVariableUpdateMessage(localPoolId, MessageQueueIF::NO_QUEUE, - objects::HK_RECEIVER_MOCK, false); + receiverId, false); } - ReturnValue_t subscribeWrapperVariableSnapshot(lp_id_t localPoolId) { + ReturnValue_t subscribeWrapperVariableSnapshot(MessageQueueId_t receiverId, lp_id_t localPoolId) { return poolManager.subscribeForVariableUpdateMessage(localPoolId, MessageQueueIF::NO_QUEUE, - objects::HK_RECEIVER_MOCK, true); + receiverId, true); } ReturnValue_t reset(); @@ -148,14 +165,19 @@ class LocalPoolOwnerBase : public SystemObject, public HasLocalDataPoolIF { gp_id_t changedPoolVariableGpid; store_address_t storeIdForChangedVariable; + PoolEntry u8PoolEntry = PoolEntry({0}); + PoolEntry floatPoolEntry = PoolEntry({0}); + PoolEntry u32PoolEntry = PoolEntry({0}); + PoolEntry u16VecPoolEntry = PoolEntry({0, 0, 0}); + PoolEntry i64VecPoolEntry = PoolEntry({0, 0}); + lp_var_t testUint8 = lp_var_t(this, lpool::uint8VarId); lp_var_t testFloat = lp_var_t(this, lpool::floatVarId); lp_var_t testUint32 = lp_var_t(this, lpool::uint32VarId); - lp_vec_t testUint16Vec = lp_vec_t(this, lpool::uint16Vec3Id); lp_vec_t testInt64Vec = lp_vec_t(this, lpool::int64Vec2Id); - MessageQueueIF* messageQueue = nullptr; + MessageQueueIF& queue; bool initialized = false; bool initializedAfterTaskCreation = false; diff --git a/unittests/mocks/MessageQueueMock.cpp b/unittests/mocks/MessageQueueMock.cpp new file mode 100644 index 00000000..cac5a0d9 --- /dev/null +++ b/unittests/mocks/MessageQueueMock.cpp @@ -0,0 +1,173 @@ +#include "MessageQueueMock.h" + +#include +#include + +MessageQueueMock::MessageQueueMock(MessageQueueId_t queueId) + : MessageQueueBase(queueId, MessageQueueIF::NO_QUEUE, nullptr) {} + +bool MessageQueueMock::wasMessageSent() const { + return std::any_of( + sendMap.begin(), sendMap.end(), + [](const std::pair& pair) { return pair.second.callCount > 0; }); +} + +size_t MessageQueueMock::numberOfSentMessages() const { + size_t callCount = 0; + for (auto& destInfo : sendMap) { + callCount += destInfo.second.callCount; + } + return callCount; +} + +size_t MessageQueueMock::numberOfSentMessagesToDest(MessageQueueId_t id) const { + auto iter = sendMap.find(id); + if (iter == sendMap.end()) { + return 0; + } + return iter->second.callCount; +} + +size_t MessageQueueMock::numberOfSentMessagesToDefault() const { + return numberOfSentMessagesToDest(MessageQueueBase::getDefaultDestination()); +} + +ReturnValue_t MessageQueueMock::clearLastReceivedMessage(bool clearCmdMsg) { + if (receivedMsgs.empty()) { + return MessageQueueIF::EMPTY; + } + if (clearCmdMsg) { + CommandMessage message; + std::memcpy(message.getBuffer(), receivedMsgs.front().getBuffer(), message.getMessageSize()); + message.clearCommandMessage(); + } + receivedMsgs.pop(); + return returnvalue::OK; +} + +ReturnValue_t MessageQueueMock::receiveMessage(MessageQueueMessageIF* message) { + if (receivedMsgs.empty()) { + return MessageQueueIF::EMPTY; + } + std::memcpy(message->getBuffer(), receivedMsgs.front().getBuffer(), message->getMessageSize()); + receivedMsgs.pop(); + return returnvalue::OK; +} + +ReturnValue_t MessageQueueMock::flush(uint32_t* count) { return returnvalue::FAILED; } + +ReturnValue_t MessageQueueMock::sendMessageFrom(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, + MessageQueueId_t sentFrom, bool ignoreFault) { + if (message == nullptr) { + return returnvalue::FAILED; + } + if (nextSendFailsPair.first) { + nextSendFailsPair.first = false; + return nextSendFailsPair.second; + } + auto iter = sendMap.find(sendTo); + MessageQueueMessage messageCopy; + if (iter == sendMap.end()) { + createMsgCopy(messageCopy, *message); + sendMap.emplace(sendTo, SendInfo(messageCopy, 1)); + } else { + iter->second.callCount += 1; + createMsgCopy(messageCopy, *message); + iter->second.msgs.push(messageCopy); + } + return returnvalue::OK; +} + +ReturnValue_t MessageQueueMock::reply(MessageQueueMessageIF* message) { + return sendMessageFrom(MessageQueueIF::NO_QUEUE, message, this->getId(), false); +} + +void MessageQueueMock::clearMessages(bool clearCommandMessages) { + if (not clearCommandMessages) { + sendMap.clear(); + return; + } + for (auto& destInfo : sendMap) { + while (!destInfo.second.msgs.empty()) { + CommandMessage message; + std::memcpy(message.getBuffer(), destInfo.second.msgs.front().getBuffer(), + message.getMessageSize()); + message.clear(); + destInfo.second.msgs.pop(); + destInfo.second.callCount--; + } + } + sendMap.clear(); +} + +void MessageQueueMock::addReceivedMessage(MessageQueueMessageIF& msg) { + MessageQueueMessage messageCopy; + createMsgCopy(messageCopy, msg); + receivedMsgs.push(messageCopy); +} + +void MessageQueueMock::createMsgCopy(MessageQueueMessageIF& into, MessageQueueMessageIF& from) { + if (from.getMessageSize() > into.getMaximumDataSize()) { + throw std::invalid_argument("Passed message does not fit into message copy"); + } + std::memcpy(into.getBuffer(), from.getBuffer(), from.getMaximumDataSize()); +} + +ReturnValue_t MessageQueueMock::getNextSentMessage(MessageQueueId_t id, + MessageQueueMessageIF& message) { + auto iter = sendMap.find(id); + if (iter == sendMap.end() or iter->second.callCount == 0) { + return MessageQueueIF::EMPTY; + } + createMsgCopy(message, iter->second.msgs.front()); + return returnvalue::OK; +} + +ReturnValue_t MessageQueueMock::getNextSentMessage(MessageQueueMessageIF& message) { + return getNextSentMessage(MessageQueueBase::getDefaultDestination(), message); +} + +ReturnValue_t MessageQueueMock::clearLastSentMessage(MessageQueueId_t destId, bool clearCmdMsg) { + auto iter = sendMap.find(destId); + if (iter == sendMap.end()) { + return MessageQueueIF::EMPTY; + } + return clearLastSentMessage(iter, clearCmdMsg); +} + +ReturnValue_t MessageQueueMock::clearLastSentMessage(bool clearCmdMsg) { + auto iter = sendMap.find(getDefaultDestination()); + if (iter == sendMap.end()) { + return MessageQueueIF::EMPTY; + } + ReturnValue_t result = clearLastSentMessage(iter, clearCmdMsg); + clearEmptyEntries(); + return result; +} + +ReturnValue_t MessageQueueMock::clearLastSentMessage( + std::map::iterator& iter, bool clearCmdMsg) { + if (clearCmdMsg) { + CommandMessage message; + std::memcpy(message.getBuffer(), iter->second.msgs.front().getBuffer(), + message.getMessageSize()); + message.clear(); + } + iter->second.msgs.pop(); + iter->second.callCount--; + return returnvalue::OK; +} +void MessageQueueMock::clearEmptyEntries() { + for (auto it = sendMap.cbegin(); it != sendMap.cend();) { + if (it->second.callCount == 0) { + sendMap.erase(it++); + } else { + ++it; + } + } +} +void MessageQueueMock::makeNextSendFail(ReturnValue_t retval) { + nextSendFailsPair.first = true; + nextSendFailsPair.second = retval; +} diff --git a/unittests/mocks/MessageQueueMock.h b/unittests/mocks/MessageQueueMock.h new file mode 100644 index 00000000..52ba5dfe --- /dev/null +++ b/unittests/mocks/MessageQueueMock.h @@ -0,0 +1,64 @@ +#ifndef FSFW_UNITTEST_TESTS_MOCKS_MESSAGEQUEUEMOCKBASE_H_ +#define FSFW_UNITTEST_TESTS_MOCKS_MESSAGEQUEUEMOCKBASE_H_ + +#include +#include +#include + +#include "CatchDefinitions.h" +#include "fsfw/ipc/CommandMessage.h" +#include "fsfw/ipc/MessageQueueBase.h" +#include "fsfw/ipc/MessageQueueIF.h" +#include "fsfw/ipc/MessageQueueMessage.h" + +struct SendInfo { + explicit SendInfo(MessageQueueMessage& initMsg, unsigned int initCallCnt = 1) + : callCount(initCallCnt) { + msgs.push(initMsg); + } + unsigned int callCount = 0; + std::queue msgs; +}; + +class MessageQueueMock : public MessageQueueBase { + public: + void addReceivedMessage(MessageQueueMessageIF& msg); + explicit MessageQueueMock(MessageQueueId_t queueId); + + //! Get next message which was sent to the default destination + ReturnValue_t getNextSentMessage(MessageQueueMessageIF& message); + //! Get message which was sent to a specific ID + ReturnValue_t getNextSentMessage(MessageQueueId_t id, MessageQueueMessageIF& message); + [[nodiscard]] bool wasMessageSent() const; + void makeNextSendFail(ReturnValue_t retval); + [[nodiscard]] size_t numberOfSentMessages() const; + [[nodiscard]] size_t numberOfSentMessagesToDefault() const; + [[nodiscard]] size_t numberOfSentMessagesToDest(MessageQueueId_t id) const; + /** + * Pop a message, clearing it in the process. + * @return + */ + ReturnValue_t clearLastReceivedMessage(bool clearCmdMsg = true); + + ReturnValue_t flush(uint32_t* count) override; + ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, + MessageQueueId_t sentFrom, bool ignoreFault = false) override; + ReturnValue_t reply(MessageQueueMessageIF* message) override; + + ReturnValue_t clearLastSentMessage(MessageQueueId_t destId, bool clearCmdMsg = true); + ReturnValue_t clearLastSentMessage(bool clearCmdMsg = true); + void clearMessages(bool clearCmdMsg = true); + + private: + using SendMap = std::map; + SendMap sendMap; + std::queue receivedMsgs; + std::pair nextSendFailsPair; + + void clearEmptyEntries(); + ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override; + static ReturnValue_t clearLastSentMessage(SendMap::iterator& iter, bool clearCmdMsg = true); + static void createMsgCopy(MessageQueueMessageIF& into, MessageQueueMessageIF& from); +}; + +#endif /* FSFW_UNITTEST_TESTS_MOCKS_MESSAGEQUEUEMOCKBASE_H_ */ diff --git a/unittests/mocks/PeriodicTaskIFMock.h b/unittests/mocks/PeriodicTaskIFMock.h new file mode 100644 index 00000000..7fbcfee1 --- /dev/null +++ b/unittests/mocks/PeriodicTaskIFMock.h @@ -0,0 +1,25 @@ +#ifndef FSFW_UNITTEST_TESTS_MOCKS_PERIODICTASKMOCK_H_ +#define FSFW_UNITTEST_TESTS_MOCKS_PERIODICTASKMOCK_H_ + +#include +#include + +class PeriodicTaskMock : public PeriodicTaskBase { + public: + PeriodicTaskMock(TaskPeriod period, TaskDeadlineMissedFunction dlmFunc) + : PeriodicTaskBase(period, dlmFunc) {} + + virtual ~PeriodicTaskMock() {} + /** + * @brief With the startTask method, a created task can be started + * for the first time. + */ + virtual ReturnValue_t startTask() override { + initObjsAfterTaskCreation(); + return returnvalue::OK; + }; + + virtual ReturnValue_t sleepFor(uint32_t ms) override { return returnvalue::OK; }; +}; + +#endif // FSFW_UNITTEST_TESTS_MOCKS_PERIODICTASKMOCK_H_ diff --git a/unittests/mocks/PowerSwitcherMock.cpp b/unittests/mocks/PowerSwitcherMock.cpp new file mode 100644 index 00000000..b1506f6e --- /dev/null +++ b/unittests/mocks/PowerSwitcherMock.cpp @@ -0,0 +1,77 @@ +#include "PowerSwitcherMock.h" + +static uint32_t SWITCH_REQUEST_UPDATE_VALUE = 0; + +PowerSwitcherMock::PowerSwitcherMock() {} + +ReturnValue_t PowerSwitcherMock::sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) { + if (switchMap.count(switchNr) == 0) { + switchMap.emplace(switchNr, SwitchInfo(switchNr, onOff)); + } else { + SwitchInfo& info = switchMap.at(switchNr); + info.currentState = onOff; + if (onOff == PowerSwitchIF::SWITCH_ON) { + info.timesCalledOn++; + } else { + info.timesCalledOff++; + } + } + return returnvalue::OK; +} + +ReturnValue_t PowerSwitcherMock::sendFuseOnCommand(uint8_t fuseNr) { + if (fuseMap.count(fuseNr) == 0) { + fuseMap.emplace(fuseNr, FuseInfo(fuseNr)); + } else { + FuseInfo& info = fuseMap.at(fuseNr); + info.timesCalled++; + } + return returnvalue::OK; +} + +ReturnValue_t PowerSwitcherMock::getSwitchState(power::Switch_t switchNr) const { + if (switchMap.count(switchNr) == 1) { + auto& info = switchMap.at(switchNr); + SWITCH_REQUEST_UPDATE_VALUE++; + return info.currentState; + } + return returnvalue::FAILED; +} + +ReturnValue_t PowerSwitcherMock::getFuseState(uint8_t fuseNr) const { + if (fuseMap.count(fuseNr) == 1) { + return FUSE_ON; + } else { + return FUSE_OFF; + } + return returnvalue::FAILED; +} + +uint32_t PowerSwitcherMock::getSwitchDelayMs(void) const { return 5000; } + +SwitchInfo::SwitchInfo() : switcher(0) {} + +SwitchInfo::SwitchInfo(power::Switch_t switcher, ReturnValue_t initState) + : switcher(switcher), currentState(initState) {} + +FuseInfo::FuseInfo(uint8_t fuse) : fuse(fuse) {} + +void PowerSwitcherMock::getSwitchInfo(power::Switch_t switcher, SwitchInfo& info) { + if (switchMap.count(switcher) == 1) { + info = switchMap.at(switcher); + } +} + +void PowerSwitcherMock::getFuseInfo(uint8_t fuse, FuseInfo& info) { + if (fuseMap.count(fuse) == 1) { + info = fuseMap.at(fuse); + } +} + +uint32_t PowerSwitcherMock::getAmountSwitchStatWasRequested() { + return SWITCH_REQUEST_UPDATE_VALUE; +} + +void PowerSwitcherMock::initSwitch(power::Switch_t switchNr) { + switchMap.emplace(switchNr, SwitchInfo(switchNr, PowerSwitchIF::SWITCH_OFF)); +} diff --git a/unittests/mocks/PowerSwitcherMock.h b/unittests/mocks/PowerSwitcherMock.h new file mode 100644 index 00000000..3a740e66 --- /dev/null +++ b/unittests/mocks/PowerSwitcherMock.h @@ -0,0 +1,52 @@ +#ifndef FSFW_TESTS_SRC_FSFW_TESTS_UNIT_MOCKS_POWERSWITCHERMOCK_H_ +#define FSFW_TESTS_SRC_FSFW_TESTS_UNIT_MOCKS_POWERSWITCHERMOCK_H_ + +#include + +#include +#include + +struct SwitchInfo { + public: + SwitchInfo(); + SwitchInfo(power::Switch_t switcher, ReturnValue_t initState); + + power::Switch_t switcher; + ReturnValue_t currentState = PowerSwitchIF::SWITCH_OFF; + uint32_t timesCalledOn = 0; + uint32_t timesCalledOff = 0; + uint32_t timesStatusRequested = 0; +}; + +struct FuseInfo { + public: + FuseInfo(uint8_t fuse); + uint8_t fuse; + uint32_t timesCalled = 0; +}; + +class PowerSwitcherMock : public PowerSwitchIF { + public: + PowerSwitcherMock(); + + ReturnValue_t sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) override; + ReturnValue_t sendFuseOnCommand(uint8_t fuseNr) override; + ReturnValue_t getSwitchState(power::Switch_t switchNr) const override; + ReturnValue_t getFuseState(uint8_t fuseNr) const override; + uint32_t getSwitchDelayMs(void) const override; + + void getSwitchInfo(power::Switch_t switcher, SwitchInfo& info); + void getFuseInfo(uint8_t fuse, FuseInfo& info); + + uint32_t getAmountSwitchStatWasRequested(); + + void initSwitch(power::Switch_t switchNr); + + private: + using SwitchOnOffPair = std::pair; + using FuseOnOffPair = std::pair; + std::map switchMap; + std::map fuseMap; +}; + +#endif /* FSFW_TESTS_SRC_FSFW_TESTS_UNIT_MOCKS_POWERSWITCHERMOCK_H_ */ diff --git a/unittests/mocks/PusDistributorMock.cpp b/unittests/mocks/PusDistributorMock.cpp new file mode 100644 index 00000000..aed45ce4 --- /dev/null +++ b/unittests/mocks/PusDistributorMock.cpp @@ -0,0 +1,12 @@ +#include "PusDistributorMock.h" + +PusDistributorMock::PusDistributorMock() : SystemObject(objects::NO_OBJECT, false) {} + +PusDistributorMock::PusDistributorMock(object_id_t registeredId) + : SystemObject(registeredId, true) {} + +ReturnValue_t PusDistributorMock::registerService(const AcceptsTelecommandsIF& service) { + registerCallCount++; + registeredServies.push_back(&service); + return returnvalue::OK; +} diff --git a/unittests/mocks/PusDistributorMock.h b/unittests/mocks/PusDistributorMock.h new file mode 100644 index 00000000..417ae448 --- /dev/null +++ b/unittests/mocks/PusDistributorMock.h @@ -0,0 +1,18 @@ +#ifndef FSFW_TESTS_PUSDISTRIBUTORMOCK_H +#define FSFW_TESTS_PUSDISTRIBUTORMOCK_H + +#include + +#include "fsfw/objectmanager/SystemObject.h" +#include "fsfw/tcdistribution/PusDistributorIF.h" + +class PusDistributorMock : public SystemObject, public PusDistributorIF { + public: + PusDistributorMock(); + explicit PusDistributorMock(object_id_t registeredId); + unsigned int registerCallCount = 0; + std::vector registeredServies; + ReturnValue_t registerService(const AcceptsTelecommandsIF& service) override; +}; + +#endif // FSFW_TESTS_PUSDISTRIBUTORMOCK_H diff --git a/unittests/mocks/PusServiceBaseMock.cpp b/unittests/mocks/PusServiceBaseMock.cpp new file mode 100644 index 00000000..91e745e9 --- /dev/null +++ b/unittests/mocks/PusServiceBaseMock.cpp @@ -0,0 +1,53 @@ +#include "PusServiceBaseMock.h" + +PsbMock::PsbMock(PsbParams params) : PusServiceBase(params) {} + +ReturnValue_t PsbMock::handleRequest(uint8_t subservice) { + handleRequestCallCnt++; + subserviceQueue.push(subservice); + if (handleReqFailPair.first) { + handleReqFailPair.first = false; + return handleReqFailPair.second; + } + return returnvalue::OK; +} + +ReturnValue_t PsbMock::performService() { + performServiceCallCnt++; + if (performServiceFailPair.first) { + performServiceFailPair.first = false; + return performServiceFailPair.second; + } + return returnvalue::OK; +} + +void PsbMock::reset() { + handleRequestCallCnt = 0; + performServiceCallCnt = 0; + std::queue().swap(subserviceQueue); +} + +void PsbMock::makeNextHandleReqCallFail(ReturnValue_t retval) { + handleReqFailPair.first = true; + handleReqFailPair.second = retval; +} +bool PsbMock::getAndPopNextSubservice(uint8_t& subservice) { + if (subserviceQueue.empty()) { + return false; + } + subservice = subserviceQueue.front(); + subserviceQueue.pop(); + return true; +} + +PsbParams& PsbMock::getParams() { return psbParams; } + +void PsbMock::setStaticPusDistributor(object_id_t pusDistributor) { + PUS_DISTRIBUTOR = pusDistributor; +} + +object_id_t PsbMock::getStaticPusDistributor() { return PUS_DISTRIBUTOR; } + +void PsbMock::setStaticTmDest(object_id_t tmDest) { PACKET_DESTINATION = tmDest; } + +object_id_t PsbMock::getStaticTmDest() { return PACKET_DESTINATION; } diff --git a/unittests/mocks/PusServiceBaseMock.h b/unittests/mocks/PusServiceBaseMock.h new file mode 100644 index 00000000..0aa6b406 --- /dev/null +++ b/unittests/mocks/PusServiceBaseMock.h @@ -0,0 +1,32 @@ +#ifndef FSFW_TESTS_PUSSERVICEBASEMOCK_H +#define FSFW_TESTS_PUSSERVICEBASEMOCK_H + +#include + +#include "fsfw/tmtcservices/PusServiceBase.h" + +class PsbMock : public PusServiceBase { + public: + explicit PsbMock(PsbParams params); + unsigned int handleRequestCallCnt = 0; + std::queue subserviceQueue; + unsigned int performServiceCallCnt = 0; + + static void setStaticPusDistributor(object_id_t pusDistributor); + static object_id_t getStaticPusDistributor(); + static void setStaticTmDest(object_id_t tmDest); + static object_id_t getStaticTmDest(); + + PsbParams& getParams(); + + std::pair handleReqFailPair; + std::pair performServiceFailPair; + ReturnValue_t handleRequest(uint8_t subservice) override; + ReturnValue_t performService() override; + + void makeNextHandleReqCallFail(ReturnValue_t retval); + bool getAndPopNextSubservice(uint8_t& subservice); + void reset(); +}; + +#endif // FSFW_TESTS_PUSSERVICEBASEMOCK_H diff --git a/unittests/mocks/PusVerificationReporterMock.cpp b/unittests/mocks/PusVerificationReporterMock.cpp new file mode 100644 index 00000000..07afd319 --- /dev/null +++ b/unittests/mocks/PusVerificationReporterMock.cpp @@ -0,0 +1,42 @@ +#include "PusVerificationReporterMock.h" + +#include "fsfw/objectmanager/frameworkObjects.h" + +PusVerificationReporterMock::PusVerificationReporterMock() + : SystemObject(objects::NO_OBJECT, false) {} + +PusVerificationReporterMock::PusVerificationReporterMock(object_id_t registeredId) + : SystemObject(registeredId) {} + +size_t PusVerificationReporterMock::successCallCount() const { return successParams.size(); } +size_t PusVerificationReporterMock::failCallCount() const { return failParams.size(); } + +VerifSuccessParams& PusVerificationReporterMock::getNextSuccessCallParams() { + return successParams.front(); +} + +void PusVerificationReporterMock::popNextFailParams() { + if (not failParams.empty()) { + failParams.pop(); + } +} + +VerifFailureParams& PusVerificationReporterMock::getNextFailCallParams() { + return failParams.front(); +} + +void PusVerificationReporterMock::popNextSuccessParams() { + if (not successParams.empty()) { + successParams.pop(); + } +} + +ReturnValue_t PusVerificationReporterMock::sendSuccessReport(VerifSuccessParams params) { + successParams.push(params); + return returnvalue::OK; +} + +ReturnValue_t PusVerificationReporterMock::sendFailureReport(VerifFailureParams params) { + failParams.push(params); + return returnvalue::OK; +} diff --git a/unittests/mocks/PusVerificationReporterMock.h b/unittests/mocks/PusVerificationReporterMock.h new file mode 100644 index 00000000..dedfd30e --- /dev/null +++ b/unittests/mocks/PusVerificationReporterMock.h @@ -0,0 +1,25 @@ +#ifndef FSFW_TESTS_PUSVERIFICATIONREPORTERMOCK_H +#define FSFW_TESTS_PUSVERIFICATIONREPORTERMOCK_H + +#include + +#include "fsfw/objectmanager/SystemObject.h" +#include "fsfw/tmtcservices/VerificationReporterIF.h" + +class PusVerificationReporterMock : public SystemObject, public VerificationReporterIF { + public: + std::queue successParams; + std::queue failParams; + PusVerificationReporterMock(); + explicit PusVerificationReporterMock(object_id_t registeredId); + [[nodiscard]] size_t successCallCount() const; + VerifSuccessParams& getNextSuccessCallParams(); + void popNextSuccessParams(); + [[nodiscard]] size_t failCallCount() const; + VerifFailureParams& getNextFailCallParams(); + void popNextFailParams(); + + ReturnValue_t sendSuccessReport(VerifSuccessParams params) override; + ReturnValue_t sendFailureReport(VerifFailureParams params) override; +}; +#endif // FSFW_TESTS_PUSVERIFICATIONREPORTERMOCK_H diff --git a/unittests/mocks/SimpleSerializable.h b/unittests/mocks/SimpleSerializable.h new file mode 100644 index 00000000..222f1729 --- /dev/null +++ b/unittests/mocks/SimpleSerializable.h @@ -0,0 +1,40 @@ +#ifndef FSFW_TESTS_SIMPLESERIALIZABLE_H +#define FSFW_TESTS_SIMPLESERIALIZABLE_H + +#include "fsfw/osal/Endiness.h" +#include "fsfw/serialize.h" + +class SimpleSerializable : public SerializeIF { + public: + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override { + if (*size + getSerializedSize() > maxSize) { + return SerializeIF::BUFFER_TOO_SHORT; + } + **buffer = someU8; + *buffer += 1; + *size += 1; + return SerializeAdapter::serialize(&someU16, buffer, size, maxSize, streamEndianness); + } + + [[nodiscard]] size_t getSerializedSize() const override { return 3; } + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override { + if (*size < getSerializedSize()) { + return SerializeIF::STREAM_TOO_SHORT; + } + someU8 = **buffer; + *size -= 1; + *buffer += 1; + return SerializeAdapter::deSerialize(&someU16, buffer, size, streamEndianness); + } + + [[nodiscard]] uint8_t getU8() const { return someU8; } + [[nodiscard]] uint16_t getU16() const { return someU16; } + + private: + uint8_t someU8 = 1; + uint16_t someU16 = 0x0203; +}; + +#endif // FSFW_TESTS_SIMPLESERIALIZABLE_H diff --git a/unittests/mocks/StorageManagerMock.cpp b/unittests/mocks/StorageManagerMock.cpp new file mode 100644 index 00000000..8a287cd1 --- /dev/null +++ b/unittests/mocks/StorageManagerMock.cpp @@ -0,0 +1,81 @@ +#include "StorageManagerMock.h" + +ReturnValue_t StorageManagerMock::addData(store_address_t *storageId, const uint8_t *data, + size_t size) { + if (nextAddDataCallFails.first) { + return nextAddDataCallFails.second; + } + return LocalPool::addData(storageId, data, size); +} +ReturnValue_t StorageManagerMock::deleteData(store_address_t packet_id) { + if (nextDeleteDataCallFails.first) { + return nextDeleteDataCallFails.second; + } + return LocalPool::deleteData(packet_id); +} + +ReturnValue_t StorageManagerMock::deleteData(uint8_t *buffer, size_t size, + store_address_t *storeId) { + if (nextDeleteDataCallFails.first) { + return nextDeleteDataCallFails.second; + } + return LocalPool::deleteData(buffer, size, storeId); +} + +ReturnValue_t StorageManagerMock::getData(store_address_t packet_id, const uint8_t **packet_ptr, + size_t *size) { + return LocalPool::getData(packet_id, packet_ptr, size); +} + +ReturnValue_t StorageManagerMock::modifyData(store_address_t packet_id, uint8_t **packet_ptr, + size_t *size) { + if (nextModifyDataCallFails.first) { + return nextModifyDataCallFails.second; + } + return LocalPool::modifyData(packet_id, packet_ptr, size); +} + +ReturnValue_t StorageManagerMock::getFreeElement(store_address_t *storageId, size_t size, + uint8_t **p_data) { + if (nextFreeElementCallFails.first) { + return nextFreeElementCallFails.second; + } + return LocalPool::getFreeElement(storageId, size, p_data); +} + +bool StorageManagerMock::hasDataAtId(store_address_t storeId) const { + return LocalPool::hasDataAtId(storeId); +} +void StorageManagerMock::clearStore() { return LocalPool::clearStore(); } + +void StorageManagerMock::clearSubPool(uint8_t poolIndex) { + return LocalPool::clearSubPool(poolIndex); +} + +void StorageManagerMock::getFillCount(uint8_t *buffer, uint8_t *bytesWritten) { + return LocalPool::getFillCount(buffer, bytesWritten); +} + +size_t StorageManagerMock::getTotalSize(size_t *additionalSize) { + return LocalPool::getTotalSize(additionalSize); +} + +StorageManagerIF::max_subpools_t StorageManagerMock::getNumberOfSubPools() const { + return LocalPool::getNumberOfSubPools(); +} + +void StorageManagerMock::reset() { + clearStore(); + nextAddDataCallFails.first = false; + nextAddDataCallFails.second = returnvalue::OK; + nextModifyDataCallFails.first = false; + nextModifyDataCallFails.second = returnvalue::OK; + nextDeleteDataCallFails.first = false; + nextDeleteDataCallFails.second = returnvalue::OK; + nextFreeElementCallFails.first = false; + nextFreeElementCallFails.second = returnvalue::OK; +} + +StorageManagerMock::StorageManagerMock(object_id_t setObjectId, + const LocalPool::LocalPoolConfig &poolConfig) + : LocalPool(setObjectId, poolConfig) {} diff --git a/unittests/mocks/StorageManagerMock.h b/unittests/mocks/StorageManagerMock.h new file mode 100644 index 00000000..a0a59a47 --- /dev/null +++ b/unittests/mocks/StorageManagerMock.h @@ -0,0 +1,38 @@ +#ifndef FSFW_TESTS_STORAGEMANAGERMOCK_H +#define FSFW_TESTS_STORAGEMANAGERMOCK_H + +#include "fsfw/storagemanager/LocalPool.h" +#include "fsfw/storagemanager/StorageManagerIF.h" + +class StorageManagerMock : public LocalPool { + public: + StorageManagerMock(object_id_t setObjectId, const LocalPoolConfig &poolConfig); + + ReturnValue_t addData(store_address_t *storageId, const uint8_t *data, size_t size) override; + ReturnValue_t deleteData(store_address_t packet_id) override; + ReturnValue_t deleteData(uint8_t *buffer, size_t size, store_address_t *storeId) override; + ReturnValue_t getData(store_address_t packet_id, const uint8_t **packet_ptr, + size_t *size) override; + ReturnValue_t modifyData(store_address_t packet_id, uint8_t **packet_ptr, size_t *size) override; + ReturnValue_t getFreeElement(store_address_t *storageId, size_t size, uint8_t **p_data) override; + [[nodiscard]] bool hasDataAtId(store_address_t storeId) const override; + void clearStore() override; + void clearSubPool(uint8_t poolIndex) override; + void getFillCount(uint8_t *buffer, uint8_t *bytesWritten) override; + size_t getTotalSize(size_t *additionalSize) override; + [[nodiscard]] max_subpools_t getNumberOfSubPools() const override; + + std::pair nextAddDataCallFails; + /** + * This can be used to make both the modify and get API call fail. This is because generally, + * the pool implementation get functions will use the modify API internally. + */ + std::pair nextModifyDataCallFails; + std::pair nextDeleteDataCallFails; + std::pair nextFreeElementCallFails; + + using LocalPool::getFreeElement; + + void reset(); +}; +#endif // FSFW_TESTS_STORAGEMANAGERMOCK_H diff --git a/unittests/mocks/cfdp/CMakeLists.txt b/unittests/mocks/cfdp/CMakeLists.txt new file mode 100644 index 00000000..769e06ae --- /dev/null +++ b/unittests/mocks/cfdp/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE FaultHandlerMock.cpp UserMock.cpp + RemoteConfigTableMock.cpp) diff --git a/unittests/mocks/cfdp/FaultHandlerMock.cpp b/unittests/mocks/cfdp/FaultHandlerMock.cpp new file mode 100644 index 00000000..03736f71 --- /dev/null +++ b/unittests/mocks/cfdp/FaultHandlerMock.cpp @@ -0,0 +1,42 @@ +#include "FaultHandlerMock.h" + +namespace cfdp { + +void FaultHandlerMock::noticeOfSuspensionCb(TransactionId& id, cfdp::ConditionCode code) { + auto& info = fhInfoMap.at(cfdp::FaultHandlerCode::NOTICE_OF_SUSPENSION); + info.callCount++; + info.condCodes.push(code); +} + +void FaultHandlerMock::noticeOfCancellationCb(TransactionId& id, cfdp::ConditionCode code) { + auto& info = fhInfoMap.at(cfdp::FaultHandlerCode::NOTICE_OF_CANCELLATION); + info.callCount++; + info.condCodes.push(code); +} + +void FaultHandlerMock::abandonCb(TransactionId& id, cfdp::ConditionCode code) { + auto& info = fhInfoMap.at(cfdp::FaultHandlerCode::ABANDON_TRANSACTION); + info.callCount++; + info.condCodes.push(code); +} + +void FaultHandlerMock::ignoreCb(TransactionId& id, cfdp::ConditionCode code) { + auto& info = fhInfoMap.at(cfdp::FaultHandlerCode::IGNORE_ERROR); + info.callCount++; + info.condCodes.push(code); +} + +FaultHandlerMock::FaultInfo& FaultHandlerMock::getFhInfo(cfdp::FaultHandlerCode fhCode) { + return fhInfoMap.at(fhCode); +} + +void FaultHandlerMock::reset() { fhInfoMap.clear(); } + +bool FaultHandlerMock::faultCbWasCalled() const { + return std::any_of(fhInfoMap.begin(), fhInfoMap.end(), + [](const std::pair& pair) { + return pair.second.callCount > 0; + }); +} + +} // namespace cfdp diff --git a/unittests/mocks/cfdp/FaultHandlerMock.h b/unittests/mocks/cfdp/FaultHandlerMock.h new file mode 100644 index 00000000..5e094509 --- /dev/null +++ b/unittests/mocks/cfdp/FaultHandlerMock.h @@ -0,0 +1,37 @@ +#ifndef FSFW_TESTS_FAULTHANDLERMOCK_H +#define FSFW_TESTS_FAULTHANDLERMOCK_H + +#include +#include + +#include "fsfw/cfdp/handler/FaultHandlerBase.h" + +namespace cfdp { + +class FaultHandlerMock : public FaultHandlerBase { + public: + struct FaultInfo { + size_t callCount = 0; + std::queue condCodes; + }; + + void noticeOfSuspensionCb(TransactionId& id, ConditionCode code) override; + void noticeOfCancellationCb(TransactionId& id, ConditionCode code) override; + void abandonCb(TransactionId& id, ConditionCode code) override; + void ignoreCb(TransactionId& id, ConditionCode code) override; + + FaultInfo& getFhInfo(FaultHandlerCode fhCode); + [[nodiscard]] bool faultCbWasCalled() const; + void reset(); + + private: + std::map fhInfoMap = { + std::pair{cfdp::FaultHandlerCode::IGNORE_ERROR, FaultInfo()}, + std::pair{cfdp::FaultHandlerCode::NOTICE_OF_CANCELLATION, FaultInfo()}, + std::pair{cfdp::FaultHandlerCode::NOTICE_OF_SUSPENSION, FaultInfo()}, + std::pair{cfdp::FaultHandlerCode::ABANDON_TRANSACTION, FaultInfo()}}; +}; + +} // namespace cfdp + +#endif // FSFW_TESTS_FAULTHANDLERMOCK_H diff --git a/unittests/mocks/cfdp/RemoteConfigTableMock.cpp b/unittests/mocks/cfdp/RemoteConfigTableMock.cpp new file mode 100644 index 00000000..9cb0b77c --- /dev/null +++ b/unittests/mocks/cfdp/RemoteConfigTableMock.cpp @@ -0,0 +1,15 @@ +#include "RemoteConfigTableMock.h" + +void cfdp::RemoteConfigTableMock::addRemoteConfig(const cfdp::RemoteEntityCfg& cfg) { + remoteCfgTable.emplace(cfg.remoteId, cfg); +} + +bool cfdp::RemoteConfigTableMock::getRemoteCfg(const cfdp::EntityId& remoteId, + cfdp::RemoteEntityCfg** cfg) { + auto iter = remoteCfgTable.find(remoteId); + if (iter == remoteCfgTable.end()) { + return false; + } + *cfg = &iter->second; + return true; +} diff --git a/unittests/mocks/cfdp/RemoteConfigTableMock.h b/unittests/mocks/cfdp/RemoteConfigTableMock.h new file mode 100644 index 00000000..70891836 --- /dev/null +++ b/unittests/mocks/cfdp/RemoteConfigTableMock.h @@ -0,0 +1,20 @@ +#ifndef FSFW_TESTS_CFDP_REMOTCONFIGTABLEMOCK_H +#define FSFW_TESTS_CFDP_REMOTCONFIGTABLEMOCK_H + +#include + +#include "fsfw/cfdp/handler/RemoteConfigTableIF.h" + +namespace cfdp { + +class RemoteConfigTableMock : public RemoteConfigTableIF { + public: + void addRemoteConfig(const RemoteEntityCfg& cfg); + bool getRemoteCfg(const cfdp::EntityId& remoteId, cfdp::RemoteEntityCfg** cfg) override; + + std::map remoteCfgTable; +}; + +} // namespace cfdp + +#endif // FSFW_TESTS_CFDP_REMOTCONFIGTABLEMOCK_H diff --git a/unittests/mocks/cfdp/UserMock.cpp b/unittests/mocks/cfdp/UserMock.cpp new file mode 100644 index 00000000..ca15a5e6 --- /dev/null +++ b/unittests/mocks/cfdp/UserMock.cpp @@ -0,0 +1,35 @@ +#include "UserMock.h" + +namespace cfdp { + +cfdp::UserMock::UserMock(HasFileSystemIF& vfs) : UserBase(vfs) {} + +void UserMock::transactionIndication(const TransactionId& id) {} +void UserMock::eofSentIndication(const TransactionId& id) {} +void UserMock::abandonedIndication(const TransactionId& id, cfdp::ConditionCode code, + uint64_t progress) {} + +void UserMock::eofRecvIndication(const TransactionId& id) { eofsRevd.push(id); } + +void UserMock::transactionFinishedIndication(const TransactionFinishedParams& finishedParams) { + finishedRecvd.push({finishedParams.id, finishedParams}); +} + +void UserMock::metadataRecvdIndication(const MetadataRecvdParams& params) { + metadataRecvd.push({params.id, params}); +} + +void UserMock::fileSegmentRecvdIndication(const FileSegmentRecvdParams& params) {} +void UserMock::reportIndication(const TransactionId& id, StatusReportIF& report) {} +void UserMock::suspendedIndication(const TransactionId& id, ConditionCode code) {} +void UserMock::resumedIndication(const TransactionId& id, size_t progress) {} +void UserMock::faultIndication(const TransactionId& id, cfdp::ConditionCode code, size_t progress) { +} + +void UserMock::reset() { + std::queue().swap(eofsRevd); + std::queue>().swap(metadataRecvd); + std::queue>().swap(finishedRecvd); +} + +} // namespace cfdp diff --git a/unittests/mocks/cfdp/UserMock.h b/unittests/mocks/cfdp/UserMock.h new file mode 100644 index 00000000..e2a4a483 --- /dev/null +++ b/unittests/mocks/cfdp/UserMock.h @@ -0,0 +1,34 @@ +#ifndef FSFW_TESTS_CFDP_USERMOCK_H +#define FSFW_TESTS_CFDP_USERMOCK_H + +#include + +#include "fsfw/cfdp/handler/UserBase.h" + +namespace cfdp { + +class UserMock : public UserBase { + public: + explicit UserMock(HasFileSystemIF& vfs); + + void transactionIndication(const TransactionId& id) override; + void eofSentIndication(const TransactionId& id) override; + void abandonedIndication(const TransactionId& id, ConditionCode code, size_t progress) override; + void eofRecvIndication(const TransactionId& id) override; + void transactionFinishedIndication(const TransactionFinishedParams& params) override; + void metadataRecvdIndication(const MetadataRecvdParams& params) override; + void fileSegmentRecvdIndication(const FileSegmentRecvdParams& params) override; + void reportIndication(const TransactionId& id, StatusReportIF& report) override; + void suspendedIndication(const TransactionId& id, ConditionCode code) override; + void resumedIndication(const TransactionId& id, size_t progress) override; + void faultIndication(const TransactionId& id, ConditionCode code, size_t progress) override; + + std::queue> metadataRecvd; + std::queue eofsRevd; + std::queue> finishedRecvd; + void reset(); +}; + +} // namespace cfdp + +#endif // FSFW_TESTS_CFDP_USERMOCK_H diff --git a/unittests/osal/CMakeLists.txt b/unittests/osal/CMakeLists.txt new file mode 100644 index 00000000..90eea2c7 --- /dev/null +++ b/unittests/osal/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE testMq.cpp TestSemaphore.cpp + TestClock.cpp) diff --git a/tests/src/fsfw_tests/unit/osal/TestClock.cpp b/unittests/osal/TestClock.cpp similarity index 80% rename from tests/src/fsfw_tests/unit/osal/TestClock.cpp rename to unittests/osal/TestClock.cpp index 38ec3915..5d198db1 100644 --- a/tests/src/fsfw_tests/unit/osal/TestClock.cpp +++ b/unittests/osal/TestClock.cpp @@ -5,19 +5,19 @@ #include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" TEST_CASE("OSAL::Clock Test", "[OSAL::Clock Test]") { SECTION("Test getClock") { timeval time; ReturnValue_t result = Clock::getClock_timeval(&time); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); Clock::TimeOfDay_t timeOfDay; result = Clock::getDateAndTime(&timeOfDay); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); timeval timeOfDayAsTimeval; result = Clock::convertTimeOfDayToTimeval(&timeOfDay, &timeOfDayAsTimeval); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); // We require timeOfDayAsTimeval to be larger than time as it // was request a few ns later double difference = timevalOperations::toDouble(timeOfDayAsTimeval - time); @@ -27,28 +27,28 @@ TEST_CASE("OSAL::Clock Test", "[OSAL::Clock Test]") { // Conversion in the other direction Clock::TimeOfDay_t timevalAsTimeOfDay; result = Clock::convertTimevalToTimeOfDay(&time, &timevalAsTimeOfDay); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); CHECK(timevalAsTimeOfDay.year <= timeOfDay.year); // TODO We should write TimeOfDay operators! } SECTION("Leap seconds") { uint16_t leapSeconds = 0; ReturnValue_t result = Clock::getLeapSeconds(&leapSeconds); - REQUIRE(result == HasReturnvaluesIF::RETURN_FAILED); + REQUIRE(result == returnvalue::FAILED); REQUIRE(leapSeconds == 0); result = Clock::setLeapSeconds(18); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); result = Clock::getLeapSeconds(&leapSeconds); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(leapSeconds == 18); } SECTION("usec Test") { timeval timeAsTimeval; ReturnValue_t result = Clock::getClock_timeval(&timeAsTimeval); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); uint64_t timeAsUsec = 0; result = Clock::getClock_usecs(&timeAsUsec); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); double timeAsUsecDouble = static_cast(timeAsUsec) / 1000000.0; timeval timeAsUsecTimeval = timevalOperations::toTimeval(timeAsUsecDouble); double difference = timevalOperations::toDouble(timeAsUsecTimeval - timeAsTimeval); @@ -66,7 +66,7 @@ TEST_CASE("OSAL::Clock Test", "[OSAL::Clock Test]") { time.tv_sec = 1648208539; time.tv_usec = 0; ReturnValue_t result = Clock::convertTimevalToJD2000(time, &j2000); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); double correctJ2000 = 2459663.98772 - 2451545.0; CHECK(j2000 == Catch::Approx(correctJ2000).margin(1.2 * 1e-8)); } @@ -76,9 +76,9 @@ TEST_CASE("OSAL::Clock Test", "[OSAL::Clock Test]") { utcTime.tv_usec = 999000; timeval tt; ReturnValue_t result = Clock::setLeapSeconds(27); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); result = Clock::convertUTCToTT(utcTime, &tt); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); CHECK(tt.tv_usec == 183000); // The plus 1 is a own forced overflow of usecs CHECK(tt.tv_sec == (1648208539 + 27 + 10 + 32 + 1)); diff --git a/unittests/osal/TestSemaphore.cpp b/unittests/osal/TestSemaphore.cpp new file mode 100644 index 00000000..1d8758b1 --- /dev/null +++ b/unittests/osal/TestSemaphore.cpp @@ -0,0 +1,38 @@ +#include +#include +#include + +#include + +// binary semaphores currently only supported on linux +#ifdef FSFW_OSAL_LINUX + +TEST_CASE("Binary Semaphore Test", "[BinSemaphore]") { + // perform set-up here + SemaphoreIF* binSemaph = SemaphoreFactory::instance()->createBinarySemaphore(); + REQUIRE(binSemaph != nullptr); + SECTION("Simple Test") { + // set-up is run for each section + REQUIRE(binSemaph->getSemaphoreCounter() == 1); + REQUIRE(binSemaph->release() == static_cast(SemaphoreIF::SEMAPHORE_NOT_OWNED)); + REQUIRE(binSemaph->acquire(SemaphoreIF::POLLING) == returnvalue::OK); + { + // not precise enough on linux.. should use clock instead.. + // Stopwatch stopwatch(false); + // REQUIRE(binSemaph->acquire(SemaphoreIF::TimeoutType::WAITING, 5) == + // SemaphoreIF::SEMAPHORE_TIMEOUT); + // dur_millis_t time = stopwatch.stop(); + // CHECK(time == 5); + } + REQUIRE(binSemaph->getSemaphoreCounter() == 0); + REQUIRE(binSemaph->release() == returnvalue::OK); + } + SemaphoreFactory::instance()->deleteSemaphore(binSemaph); + // perform tear-down here +} + +TEST_CASE("Counting Semaphore Test", "[CountingSemaph]") { + SECTION("Simple Test") {} +} + +#endif \ No newline at end of file diff --git a/tests/src/fsfw_tests/unit/osal/TestMessageQueue.cpp b/unittests/osal/testMq.cpp similarity index 84% rename from tests/src/fsfw_tests/unit/osal/TestMessageQueue.cpp rename to unittests/osal/testMq.cpp index 11c0739b..dbab553f 100644 --- a/tests/src/fsfw_tests/unit/osal/TestMessageQueue.cpp +++ b/unittests/osal/testMq.cpp @@ -4,7 +4,7 @@ #include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" TEST_CASE("MessageQueue Basic Test", "[TestMq]") { MessageQueueIF* testSenderMq = QueueFactory::instance()->createMessageQueue(1); @@ -19,17 +19,17 @@ TEST_CASE("MessageQueue Basic Test", "[TestMq]") { SECTION("Simple Tests") { auto result = testSenderMq->sendMessage(testReceiverMqId, &testMessage); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); MessageQueueMessage recvMessage; result = testReceiverMq->receiveMessage(&recvMessage); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); CHECK(recvMessage.getData()[0] == 42); result = testSenderMq->sendMessage(testReceiverMqId, &testMessage); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); MessageQueueId_t senderId = 0; result = testReceiverMq->receiveMessage(&recvMessage, &senderId); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); CHECK(recvMessage.getData()[0] == 42); CHECK(senderId == testSenderMqId); senderId = testReceiverMq->getLastPartner(); @@ -37,7 +37,7 @@ TEST_CASE("MessageQueue Basic Test", "[TestMq]") { } SECTION("Test Full") { auto result = testSenderMq->sendMessage(testReceiverMqId, &testMessage); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); result = testSenderMq->sendMessage(testReceiverMqId, &testMessage); REQUIRE(result == MessageQueueIF::FULL); // We try another message @@ -45,12 +45,12 @@ TEST_CASE("MessageQueue Basic Test", "[TestMq]") { REQUIRE(result == MessageQueueIF::FULL); MessageQueueMessage recvMessage; result = testReceiverMq->receiveMessage(&recvMessage); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); CHECK(recvMessage.getData()[0] == 42); result = testSenderMq->sendMessage(testReceiverMqId, &testMessage); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); result = testReceiverMq->receiveMessage(&recvMessage); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); CHECK(recvMessage.getData()[0] == 42); } // We have to clear MQs ourself ATM diff --git a/unittests/power/CMakeLists.txt b/unittests/power/CMakeLists.txt new file mode 100644 index 00000000..78c33b42 --- /dev/null +++ b/unittests/power/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE testPowerSwitcher.cpp) diff --git a/unittests/power/testPowerSwitcher.cpp b/unittests/power/testPowerSwitcher.cpp new file mode 100644 index 00000000..222dccf6 --- /dev/null +++ b/unittests/power/testPowerSwitcher.cpp @@ -0,0 +1,71 @@ +#include +#include + +#include + +#include "mocks/PowerSwitcherMock.h" +#include "objects/systemObjectList.h" + +TEST_CASE("Power Switcher", "[power-switcher]") { + PowerSwitcherMock mock; + PowerSwitcher switcher(&mock, 1); + DummyPowerSwitcher dummySwitcher(objects::DUMMY_POWER_SWITCHER, 5, 5, false); + PowerSwitcher switcherUsingDummy(&dummySwitcher, 1); + SwitchInfo switchInfo; + mock.initSwitch(1); + + SECTION("Basic Tests") { + REQUIRE(switcher.getFirstSwitch() == 1); + REQUIRE(switcher.getSecondSwitch() == power::NO_SWITCH); + // Default start state + REQUIRE(switcher.getState() == PowerSwitcher::SWITCH_IS_OFF); + switcher.turnOn(true); + REQUIRE(mock.getAmountSwitchStatWasRequested() == 1); + REQUIRE(switcher.getState() == PowerSwitcher::WAIT_ON); + REQUIRE(switcher.checkSwitchState() == PowerSwitcher::IN_POWER_TRANSITION); + REQUIRE(switcher.active()); + switcher.doStateMachine(); + REQUIRE(switcher.getState() == PowerSwitcher::SWITCH_IS_ON); + mock.getSwitchInfo(1, switchInfo); + REQUIRE(switchInfo.timesCalledOn == 1); + REQUIRE(not switcher.active()); + REQUIRE(mock.getAmountSwitchStatWasRequested() == 2); + REQUIRE(switcher.checkSwitchState() == returnvalue::OK); + REQUIRE(mock.getAmountSwitchStatWasRequested() == 3); + switcher.turnOff(false); + REQUIRE(mock.getAmountSwitchStatWasRequested() == 3); + REQUIRE(switcher.getState() == PowerSwitcher::WAIT_OFF); + REQUIRE(switcher.active()); + REQUIRE(switcher.getState() == PowerSwitcher::WAIT_OFF); + switcher.doStateMachine(); + mock.getSwitchInfo(1, switchInfo); + REQUIRE(switcher.getState() == PowerSwitcher::SWITCH_IS_OFF); + REQUIRE(switchInfo.timesCalledOn == 1); + REQUIRE(switchInfo.timesCalledOff == 1); + REQUIRE(not switcher.active()); + REQUIRE(mock.getAmountSwitchStatWasRequested() == 4); + } + + SECTION("Dummy Test") { + // Same tests, but we can't really check the dummy + REQUIRE(switcherUsingDummy.getFirstSwitch() == 1); + REQUIRE(switcherUsingDummy.getSecondSwitch() == power::NO_SWITCH); + REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::SWITCH_IS_OFF); + switcherUsingDummy.turnOn(true); + REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::WAIT_ON); + REQUIRE(switcherUsingDummy.active()); + switcherUsingDummy.doStateMachine(); + REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::SWITCH_IS_ON); + REQUIRE(not switcherUsingDummy.active()); + + switcherUsingDummy.turnOff(false); + REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::WAIT_OFF); + REQUIRE(switcherUsingDummy.active()); + REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::WAIT_OFF); + switcherUsingDummy.doStateMachine(); + REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::SWITCH_IS_OFF); + REQUIRE(not switcherUsingDummy.active()); + } + + SECTION("More Dummy Tests") {} +} diff --git a/tests/src/fsfw_tests/unit/printChar.cpp b/unittests/printChar.cpp similarity index 100% rename from tests/src/fsfw_tests/unit/printChar.cpp rename to unittests/printChar.cpp diff --git a/tests/src/fsfw_tests/unit/printChar.h b/unittests/printChar.h similarity index 100% rename from tests/src/fsfw_tests/unit/printChar.h rename to unittests/printChar.h diff --git a/unittests/pus/CMakeLists.txt b/unittests/pus/CMakeLists.txt new file mode 100644 index 00000000..7f615a50 --- /dev/null +++ b/unittests/pus/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE testService11.cpp) diff --git a/unittests/pus/testService11.cpp b/unittests/pus/testService11.cpp new file mode 100644 index 00000000..bd3b22ad --- /dev/null +++ b/unittests/pus/testService11.cpp @@ -0,0 +1,14 @@ +#include + +#include + +#include "objects/systemObjectList.h" +#include "tmtc/apid.h" +#include "tmtc/pusIds.h" + +TEST_CASE("PUS Service 11", "[pus-srvc11]") { + Service11TelecommandScheduling<13> pusService11( + {objects::PUS_SERVICE_11_TC_SCHEDULER, apid::DEFAULT_APID, pus::PUS_SERVICE_11}, nullptr); + + // TODO test something... +} \ No newline at end of file diff --git a/unittests/serialize/CMakeLists.txt b/unittests/serialize/CMakeLists.txt new file mode 100644 index 00000000..b42be1d5 --- /dev/null +++ b/unittests/serialize/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources( + ${FSFW_TEST_TGT} PRIVATE testSerialBufferAdapter.cpp testSerializeAdapter.cpp + testSerialLinkedPacket.cpp testSerializeIF.cpp) diff --git a/tests/src/fsfw_tests/unit/serialize/TestSerialLinkedPacket.h b/unittests/serialize/SerialLinkedListAdapterPacket.h similarity index 80% rename from tests/src/fsfw_tests/unit/serialize/TestSerialLinkedPacket.h rename to unittests/serialize/SerialLinkedListAdapterPacket.h index 0cfdd9ff..81268d28 100644 --- a/tests/src/fsfw_tests/unit/serialize/TestSerialLinkedPacket.h +++ b/unittests/serialize/SerialLinkedListAdapterPacket.h @@ -26,13 +26,13 @@ class TestPacket : public SerialLinkedListAdapter { setLinks(); } - uint32_t getHeader() const { return header.entry; } + [[nodiscard]] uint32_t getHeader() const { return header.entry; } - const uint8_t* getBuffer() { return buffer.entry.getConstBuffer(); } + [[nodiscard]] const uint8_t* getBuffer() const { return buffer.entry.getConstBuffer(); } size_t getBufferLength() { return buffer.getSerializedSize(); } - uint16_t getTail() const { return tail.entry; } + [[nodiscard]] uint16_t getTail() const { return tail.entry; } private: void setLinks() { @@ -47,4 +47,4 @@ class TestPacket : public SerialLinkedListAdapter { SerializeElement tail = 0; }; -#endif /* UNITTEST_TESTFW_NEWTESTS_TESTTEMPLATE_H_ */ +#endif /* UNITTEST_HOSTED_TESTSERIALLINKEDPACKET_H_ */ diff --git a/tests/src/fsfw_tests/unit/serialize/TestSerialBufferAdapter.cpp b/unittests/serialize/testSerialBufferAdapter.cpp similarity index 94% rename from tests/src/fsfw_tests/unit/serialize/TestSerialBufferAdapter.cpp rename to unittests/serialize/testSerialBufferAdapter.cpp index 9b30427f..abd179e4 100644 --- a/tests/src/fsfw_tests/unit/serialize/TestSerialBufferAdapter.cpp +++ b/unittests/serialize/testSerialBufferAdapter.cpp @@ -3,7 +3,7 @@ #include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" static bool test_value_bool = true; static uint16_t tv_uint16{283}; @@ -64,7 +64,8 @@ TEST_CASE("Serial Buffer Adapter", "[single-file]") { SECTION("Test set buffer function") { SerialBufferAdapter tv_serial_buffer_adapter_loc = SerialBufferAdapter((uint8_t*)nullptr, 0, true); - tv_serial_buffer_adapter_loc.setBuffer(test_serial_buffer.data(), test_serial_buffer.size()); + tv_serial_buffer_adapter_loc.setConstBuffer(test_serial_buffer.data(), + test_serial_buffer.size()); serialized_size = 0; arrayPtr = testArray.data(); SerializeAdapter::serialize(&test_value_bool, &arrayPtr, &serialized_size, testArray.size(), @@ -92,7 +93,7 @@ TEST_CASE("Serial Buffer Adapter", "[single-file]") { testArray[3] = 1; testArray[4] = 1; testArray[5] = 0; - std::array test_recv_array; + std::array test_recv_array{}; arrayPtr = testArray.data(); // copy testArray[1] to testArray[4] into receive buffer, skip // size field (testArray[0]) for deSerialization. @@ -102,7 +103,7 @@ TEST_CASE("Serial Buffer Adapter", "[single-file]") { size_t size = 6; auto result = tv_serial_buffer_adapter3.deSerialize(const_cast(&arrayPtr), &size, SerializeIF::Endianness::MACHINE); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); CHECK(test_recv_array[0] == 1); CHECK(test_recv_array[1] == 1); CHECK(test_recv_array[2] == 1); @@ -116,7 +117,7 @@ TEST_CASE("Serial Buffer Adapter", "[single-file]") { testArray[3] = 1; testArray[4] = 1; testArray[5] = 0; - std::array test_recv_array; + std::array test_recv_array{}; arrayPtr = testArray.data() + 2; // copy testArray[1] to testArray[4] into receive buffer, skip // size field (testArray[0]) diff --git a/tests/src/fsfw_tests/unit/serialize/TestSerialLinkedPacket.cpp b/unittests/serialize/testSerialLinkedPacket.cpp similarity index 93% rename from tests/src/fsfw_tests/unit/serialize/TestSerialLinkedPacket.cpp rename to unittests/serialize/testSerialLinkedPacket.cpp index e3bdf882..30024248 100644 --- a/tests/src/fsfw_tests/unit/serialize/TestSerialLinkedPacket.cpp +++ b/unittests/serialize/testSerialLinkedPacket.cpp @@ -1,11 +1,10 @@ -#include "TestSerialLinkedPacket.h" - #include #include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" +#include "SerialLinkedListAdapterPacket.h" TEST_CASE("Serial Linked Packet", "[SerLinkPacket]") { // perform set-up here @@ -41,7 +40,7 @@ TEST_CASE("Serial Linked Packet", "[SerLinkPacket]") { // Deserialize big endian packet by setting bigEndian to true. ReturnValue_t result = testClass.deSerialize(&readOnlyPointer, &packetLen, SerializeIF::Endianness::BIG); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); CHECK(testClass.getHeader() == 42); // Equivalent check. // CHECK(testClass.getBuffer()[0] == 1); @@ -60,7 +59,7 @@ TEST_CASE("Serial Linked Packet", "[SerLinkPacket]") { // serialize for ground: bigEndian = true. ReturnValue_t result = testClass.serialize(&packetPointer, &serializedSize, packetMaxSize, SerializeIF::Endianness::BIG); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); // Result should be big endian now. CHECK(packet[3] == 42); CHECK(packet[4] == 1); diff --git a/tests/src/fsfw_tests/unit/serialize/TestSerialization.cpp b/unittests/serialize/testSerializeAdapter.cpp similarity index 99% rename from tests/src/fsfw_tests/unit/serialize/TestSerialization.cpp rename to unittests/serialize/testSerializeAdapter.cpp index 52cb70f6..a3340a7d 100644 --- a/tests/src/fsfw_tests/unit/serialize/TestSerialization.cpp +++ b/unittests/serialize/testSerializeAdapter.cpp @@ -5,7 +5,7 @@ #include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" static bool testBool = true; static uint8_t tvUint8{5}; diff --git a/unittests/serialize/testSerializeIF.cpp b/unittests/serialize/testSerializeIF.cpp new file mode 100644 index 00000000..30ad58e5 --- /dev/null +++ b/unittests/serialize/testSerializeIF.cpp @@ -0,0 +1,138 @@ + +#include +#include + +#include "mocks/SimpleSerializable.h" + +using namespace std; + +TEST_CASE("Serialize IF Serialize", "[serialize-if-ser]") { + auto simpleSer = SimpleSerializable(); + array buf{}; + uint8_t* ptr = buf.data(); + size_t len = 0; + + SECTION("Little Endian Normal") { + REQUIRE(simpleSer.serialize(&ptr, &len, buf.size(), SerializeIF::Endianness::LITTLE) == + returnvalue::OK); + CHECK(buf[0] == 1); + CHECK(buf[1] == 3); + CHECK(buf[2] == 2); + // Verify pointer arithmetic and size increment + CHECK(ptr == buf.data() + 3); + CHECK(len == 3); + } + + SECTION("Little Endian Simple") { + size_t serLen = 0xff; + REQUIRE(simpleSer.SerializeIF::serialize(buf.data(), serLen, buf.size(), + SerializeIF::Endianness::LITTLE) == returnvalue::OK); + CHECK(buf[0] == 1); + CHECK(buf[1] == 3); + CHECK(buf[2] == 2); + CHECK(serLen == 3); + } + + SECTION("Big Endian Normal") { + SECTION("Explicit") { + REQUIRE(simpleSer.serialize(&ptr, &len, buf.size(), SerializeIF::Endianness::BIG) == + returnvalue::OK); + } + SECTION("Network 0") { + REQUIRE(simpleSer.serialize(&ptr, &len, buf.size(), SerializeIF::Endianness::NETWORK) == + returnvalue::OK); + } + SECTION("Network 1") { + REQUIRE(simpleSer.serializeBe(&ptr, &len, buf.size()) == returnvalue::OK); + } + + CHECK(buf[0] == 1); + CHECK(buf[1] == 2); + CHECK(buf[2] == 3); + // Verify pointer arithmetic and size increment + CHECK(ptr == buf.data() + 3); + CHECK(len == 3); + } + + SECTION("Big Endian Simple") { + size_t serLen = 0xff; + SECTION("Explicit") { + REQUIRE(simpleSer.SerializeIF::serialize(buf.data(), serLen, buf.size(), + SerializeIF::Endianness::BIG) == returnvalue::OK); + } + SECTION("Network 0") { + REQUIRE(simpleSer.SerializeIF::serialize(buf.data(), serLen, buf.size(), + SerializeIF::Endianness::NETWORK) == + returnvalue::OK); + } + SECTION("Network 1") { + REQUIRE(simpleSer.SerializeIF::serializeBe(buf.data(), serLen, buf.size()) == + returnvalue::OK); + } + CHECK(buf[0] == 1); + CHECK(buf[1] == 2); + CHECK(buf[2] == 3); + CHECK(serLen == 3); + } +} + +TEST_CASE("SerializeIF Deserialize", "[serialize-if-de]") { + auto simpleSer = SimpleSerializable(); + array buf = {5, 0, 1}; + const uint8_t* ptr = buf.data(); + size_t len = buf.size(); + + SECTION("Little Endian Normal") { + REQUIRE(simpleSer.deSerialize(&ptr, &len, SerializeIF::Endianness::LITTLE) == returnvalue::OK); + CHECK(simpleSer.getU8() == 5); + CHECK(simpleSer.getU16() == 0x0100); + CHECK(ptr == buf.data() + 3); + CHECK(len == 0); + } + + SECTION("Little Endian Simple") { + size_t deserLen = 0xff; + REQUIRE(simpleSer.SerializeIF::deSerialize(ptr, deserLen, len, + SerializeIF::Endianness::LITTLE) == returnvalue::OK); + CHECK(simpleSer.getU8() == 5); + CHECK(simpleSer.getU16() == 0x0100); + CHECK(deserLen == 3); + } + + SECTION("Big Endian Normal") { + SECTION("Explicit") { + REQUIRE(simpleSer.deSerialize(&ptr, &len, SerializeIF::Endianness::BIG) == returnvalue::OK); + } + SECTION("Network 0") { + REQUIRE(simpleSer.deSerialize(&ptr, &len, SerializeIF::Endianness::NETWORK) == + returnvalue::OK); + } + SECTION("Network 1") { + REQUIRE(simpleSer.SerializeIF::deSerializeBe(&ptr, &len) == returnvalue::OK); + } + CHECK(simpleSer.getU8() == 5); + CHECK(simpleSer.getU16() == 1); + CHECK(ptr == buf.data() + 3); + CHECK(len == 0); + } + + SECTION("Big Endian Simple") { + size_t deserLen = 0xff; + SECTION("Explicit") { + REQUIRE(simpleSer.SerializeIF::deSerialize(buf.data(), deserLen, buf.size(), + SerializeIF::Endianness::BIG) == returnvalue::OK); + } + SECTION("Network 0") { + REQUIRE(simpleSer.SerializeIF::deSerialize(buf.data(), deserLen, buf.size(), + SerializeIF::Endianness::NETWORK) == + returnvalue::OK); + } + SECTION("Network 1") { + REQUIRE(simpleSer.SerializeIF::deSerializeBe(buf.data(), deserLen, buf.size()) == + returnvalue::OK); + } + CHECK(simpleSer.getU8() == 5); + CHECK(simpleSer.getU16() == 1); + CHECK(deserLen == 3); + } +} \ No newline at end of file diff --git a/unittests/storagemanager/CMakeLists.txt b/unittests/storagemanager/CMakeLists.txt new file mode 100644 index 00000000..19e84233 --- /dev/null +++ b/unittests/storagemanager/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE testAccessor.cpp testPool.cpp) diff --git a/tests/src/fsfw_tests/unit/storagemanager/TestNewAccessor.cpp b/unittests/storagemanager/testAccessor.cpp similarity index 51% rename from tests/src/fsfw_tests/unit/storagemanager/TestNewAccessor.cpp rename to unittests/storagemanager/testAccessor.cpp index e1db9ce0..56b858db 100644 --- a/tests/src/fsfw_tests/unit/storagemanager/TestNewAccessor.cpp +++ b/unittests/storagemanager/testAccessor.cpp @@ -4,15 +4,15 @@ #include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" -TEST_CASE("New Accessor", "[NewAccessor]") { +TEST_CASE("Pool Accessor", "[pool-accessor]") { LocalPool::LocalPoolConfig poolCfg = {{1, 10}}; - LocalPool SimplePool = LocalPool(0, poolCfg); - std::array testDataArray; - std::array receptionArray; + LocalPool simplePool = LocalPool(0, poolCfg); + std::array testDataArray{}; + std::array receptionArray{}; store_address_t testStoreId; - ReturnValue_t result = retval::CATCH_FAILED; + ReturnValue_t result = returnvalue::FAILED; for (size_t i = 0; i < testDataArray.size(); i++) { testDataArray[i] = i; @@ -20,10 +20,10 @@ TEST_CASE("New Accessor", "[NewAccessor]") { size_t size = 10; SECTION("Simple tests getter functions") { - result = SimplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); - auto resultPair = SimplePool.getData(testStoreId); - REQUIRE(resultPair.first == retval::CATCH_OK); + result = simplePool.addData(&testStoreId, testDataArray.data(), size); + REQUIRE(result == returnvalue::OK); + auto resultPair = simplePool.getData(testStoreId); + REQUIRE(resultPair.first == returnvalue::OK); resultPair.second.getDataCopy(receptionArray.data(), 20); CHECK(resultPair.second.getId() == testStoreId); CHECK(resultPair.second.size() == 10); @@ -38,37 +38,37 @@ TEST_CASE("New Accessor", "[NewAccessor]") { } { - auto resultPairLoc = SimplePool.getData(testStoreId); - REQUIRE(resultPairLoc.first == retval::CATCH_OK); + auto resultPairLoc = simplePool.getData(testStoreId); + REQUIRE(resultPairLoc.first == returnvalue::OK); // data should be deleted when accessor goes out of scope. } - resultPair = SimplePool.getData(testStoreId); + resultPair = simplePool.getData(testStoreId); REQUIRE(resultPair.first == (int)StorageManagerIF::DATA_DOES_NOT_EXIST); - result = SimplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + result = simplePool.addData(&testStoreId, testDataArray.data(), size); + REQUIRE(result == returnvalue::OK); { ConstStorageAccessor constAccessor(testStoreId); - result = SimplePool.getData(testStoreId, constAccessor); - REQUIRE(result == retval::CATCH_OK); + result = simplePool.getData(testStoreId, constAccessor); + REQUIRE(result == returnvalue::OK); constAccessor.getDataCopy(receptionArray.data(), 20); for (size_t i = 0; i < size; i++) { CHECK(receptionArray[i] == i); } // likewise, data should be deleted when accessor gets out of scope. } - resultPair = SimplePool.getData(testStoreId); + resultPair = simplePool.getData(testStoreId); REQUIRE(resultPair.first == (int)StorageManagerIF::DATA_DOES_NOT_EXIST); - result = SimplePool.addData(&testStoreId, testDataArray.data(), size); + result = simplePool.addData(&testStoreId, testDataArray.data(), size); { - resultPair = SimplePool.getData(testStoreId); - REQUIRE(resultPair.first == retval::CATCH_OK); + resultPair = simplePool.getData(testStoreId); + REQUIRE(resultPair.first == returnvalue::OK); resultPair.second.release(); // now data should not be deleted anymore } - resultPair = SimplePool.getData(testStoreId); - REQUIRE(resultPair.first == retval::CATCH_OK); + resultPair = simplePool.getData(testStoreId); + REQUIRE(resultPair.first == returnvalue::OK); resultPair.second.getDataCopy(receptionArray.data(), 20); for (size_t i = 0; i < size; i++) { CHECK(receptionArray[i] == i); @@ -76,12 +76,12 @@ TEST_CASE("New Accessor", "[NewAccessor]") { } SECTION("Simple tests modify functions") { - result = SimplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + result = simplePool.addData(&testStoreId, testDataArray.data(), size); + REQUIRE(result == returnvalue::OK); { StorageAccessor accessor(testStoreId); - result = SimplePool.modifyData(testStoreId, accessor); - REQUIRE(result == retval::CATCH_OK); + result = simplePool.modifyData(testStoreId, accessor); + REQUIRE(result == returnvalue::OK); CHECK(accessor.getId() == testStoreId); CHECK(accessor.size() == 10); accessor.getDataCopy(receptionArray.data(), 20); @@ -94,14 +94,14 @@ TEST_CASE("New Accessor", "[NewAccessor]") { } // data should be deleted when accessor goes out of scope } - auto resultPair = SimplePool.getData(testStoreId); + auto resultPair = simplePool.getData(testStoreId); REQUIRE(resultPair.first == (int)StorageManagerIF::DATA_DOES_NOT_EXIST); - result = SimplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + result = simplePool.addData(&testStoreId, testDataArray.data(), size); + REQUIRE(result == returnvalue::OK); { - auto resultPairLoc = SimplePool.modifyData(testStoreId); - REQUIRE(resultPairLoc.first == retval::CATCH_OK); + auto resultPairLoc = simplePool.modifyData(testStoreId); + REQUIRE(resultPairLoc.first == returnvalue::OK); CHECK(resultPairLoc.second.getId() == testStoreId); CHECK(resultPairLoc.second.size() == 10); resultPairLoc.second.getDataCopy(receptionArray.data(), 20); @@ -116,23 +116,23 @@ TEST_CASE("New Accessor", "[NewAccessor]") { resultPairLoc.second.release(); // data should not be deleted when accessor goes out of scope } - resultPair = SimplePool.getData(testStoreId); - REQUIRE(resultPair.first == retval::CATCH_OK); + resultPair = simplePool.getData(testStoreId); + REQUIRE(resultPair.first == returnvalue::OK); } SECTION("Write tests") { - result = SimplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + result = simplePool.addData(&testStoreId, testDataArray.data(), size); + REQUIRE(result == returnvalue::OK); { - auto resultPair = SimplePool.modifyData(testStoreId); - REQUIRE(resultPair.first == retval::CATCH_OK); + auto resultPair = simplePool.modifyData(testStoreId); + REQUIRE(resultPair.first == returnvalue::OK); testDataArray[9] = 42; resultPair.second.write(testDataArray.data(), 10, 0); // now data should not be deleted resultPair.second.release(); } - auto resultConstPair = SimplePool.getData(testStoreId); - REQUIRE(resultConstPair.first == retval::CATCH_OK); + auto resultConstPair = simplePool.getData(testStoreId); + REQUIRE(resultConstPair.first == returnvalue::OK); resultConstPair.second.getDataCopy(receptionArray.data(), 10); for (size_t i = 0; i < size - 1; i++) { @@ -140,20 +140,47 @@ TEST_CASE("New Accessor", "[NewAccessor]") { } CHECK(receptionArray[9] == 42); - auto resultPair = SimplePool.modifyData(testStoreId); - REQUIRE(resultPair.first == retval::CATCH_OK); + auto resultPair = simplePool.modifyData(testStoreId); + REQUIRE(resultPair.first == returnvalue::OK); result = resultPair.second.write(testDataArray.data(), 20, 0); - REQUIRE(result == retval::CATCH_FAILED); + REQUIRE(result == returnvalue::FAILED); result = resultPair.second.write(testDataArray.data(), 10, 5); - REQUIRE(result == retval::CATCH_FAILED); + REQUIRE(result == returnvalue::FAILED); std::memset(testDataArray.data(), 42, 5); result = resultPair.second.write(testDataArray.data(), 5, 5); - REQUIRE(result == retval::CATCH_OK); - resultConstPair = SimplePool.getData(testStoreId); + REQUIRE(result == returnvalue::OK); + resultConstPair = simplePool.getData(testStoreId); resultPair.second.getDataCopy(receptionArray.data(), 20); for (size_t i = 5; i < 10; i++) { CHECK(receptionArray[i] == 42); } } + + SECTION("Operators") { + result = simplePool.addData(&testStoreId, testDataArray.data(), size); + REQUIRE(result == returnvalue::OK); + { + StorageAccessor accessor(testStoreId); + StorageAccessor accessor2(store_address_t::invalid()); + accessor2 = std::move(accessor); + REQUIRE(accessor.data() == nullptr); + std::array data; + size_t size = 6; + result = accessor.write(data.data(), data.size()); + REQUIRE(result == returnvalue::FAILED); + result = simplePool.modifyData(testStoreId, accessor2); + REQUIRE(result == returnvalue::OK); + CHECK(accessor2.getId() == testStoreId); + CHECK(accessor2.size() == 10); + + std::array newData; + // Expect data to be invalid so this must return returnvalue::FAILED + result = accessor.getDataCopy(newData.data(), newData.size()); + REQUIRE(result == returnvalue::FAILED); + // Expect data to be too small + result = accessor2.getDataCopy(data.data(), data.size()); + REQUIRE(result == returnvalue::FAILED); + } + } } diff --git a/tests/src/fsfw_tests/unit/storagemanager/TestPool.cpp b/unittests/storagemanager/testPool.cpp similarity index 85% rename from tests/src/fsfw_tests/unit/storagemanager/TestPool.cpp rename to unittests/storagemanager/testPool.cpp index 2cbf951d..49a097d0 100644 --- a/tests/src/fsfw_tests/unit/storagemanager/TestPool.cpp +++ b/unittests/storagemanager/testPool.cpp @@ -1,18 +1,19 @@ #include #include +#include #include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" TEST_CASE("Local Pool Simple Tests [1 Pool]", "[TestPool]") { LocalPool::LocalPoolConfig config = {{1, 10}}; LocalPool simplePool(0, config); - std::array testDataArray; - std::array receptionArray; + std::array testDataArray{}; + std::array receptionArray{}; store_address_t testStoreId; - ReturnValue_t result = retval::CATCH_FAILED; + ReturnValue_t result; uint8_t* pointer = nullptr; const uint8_t* constPointer = nullptr; @@ -22,10 +23,12 @@ TEST_CASE("Local Pool Simple Tests [1 Pool]", "[TestPool]") { size_t size = 10; SECTION("Basic tests") { + REQUIRE(not simplePool.hasDataAtId(testStoreId)); result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); + REQUIRE(simplePool.hasDataAtId(testStoreId)); result = simplePool.getData(testStoreId, &constPointer, &size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); memcpy(receptionArray.data(), constPointer, size); for (size_t i = 0; i < size; i++) { CHECK(receptionArray[i] == i); @@ -33,12 +36,13 @@ TEST_CASE("Local Pool Simple Tests [1 Pool]", "[TestPool]") { memset(receptionArray.data(), 0, size); result = simplePool.modifyData(testStoreId, &pointer, &size); memcpy(receptionArray.data(), pointer, size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); for (size_t i = 0; i < size; i++) { CHECK(receptionArray[i] == i); } result = simplePool.deleteData(testStoreId); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); + REQUIRE(not simplePool.hasDataAtId(testStoreId)); result = simplePool.addData(&testStoreId, testDataArray.data(), 15); CHECK(result == (int)StorageManagerIF::DATA_TOO_LARGE); } @@ -46,12 +50,12 @@ TEST_CASE("Local Pool Simple Tests [1 Pool]", "[TestPool]") { SECTION("Reservation Tests ") { pointer = nullptr; result = simplePool.getFreeElement(&testStoreId, size, &pointer); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); memcpy(pointer, testDataArray.data(), size); constPointer = nullptr; result = simplePool.getData(testStoreId, &constPointer, &size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); memcpy(receptionArray.data(), constPointer, size); for (size_t i = 0; i < size; i++) { CHECK(receptionArray[i] == i); @@ -60,21 +64,21 @@ TEST_CASE("Local Pool Simple Tests [1 Pool]", "[TestPool]") { SECTION("Add, delete, add, add when full") { result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); result = simplePool.getData(testStoreId, &constPointer, &size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); memcpy(receptionArray.data(), constPointer, size); for (size_t i = 0; i < size; i++) { CHECK(receptionArray[i] == i); } result = simplePool.deleteData(testStoreId); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); result = simplePool.getData(testStoreId, &constPointer, &size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); memcpy(receptionArray.data(), constPointer, size); for (size_t i = 0; i < size; i++) { CHECK(receptionArray[i] == i); @@ -101,20 +105,20 @@ TEST_CASE("Local Pool Simple Tests [1 Pool]", "[TestPool]") { SECTION("Initialize and clear store, delete with pointer") { result = simplePool.initialize(); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); simplePool.clearStore(); result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); result = simplePool.modifyData(testStoreId, &pointer, &size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); store_address_t newId; result = simplePool.deleteData(pointer, size, &testStoreId); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(testStoreId.raw != (uint32_t)StorageManagerIF::INVALID_ADDRESS); result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); } } @@ -137,10 +141,10 @@ TEST_CASE("Local Pool Extended Tests [3 Pools]", "[TestPool2]") { runIdx++; LocalPool simplePool(0, *config); - std::array testDataArray; - std::array receptionArray; + std::array testDataArray{}; + std::array receptionArray{}; store_address_t testStoreId; - ReturnValue_t result = retval::CATCH_FAILED; + ReturnValue_t result = returnvalue::FAILED; for (size_t i = 0; i < testDataArray.size(); i++) { testDataArray[i] = i; } @@ -149,20 +153,20 @@ TEST_CASE("Local Pool Extended Tests [3 Pools]", "[TestPool2]") { SECTION("Basic tests") { size = 8; result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); // Should be on second page of the pool now for 8 bytes CHECK(testStoreId.poolIndex == 1); CHECK(testStoreId.packetIndex == 0); size = 15; result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); // Should be on third page of the pool now for 15 bytes CHECK(testStoreId.poolIndex == 2); CHECK(testStoreId.packetIndex == 0); result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); // Should be on third page of the pool now for 15 bytes CHECK(testStoreId.poolIndex == 2); CHECK(testStoreId.packetIndex == 1); @@ -173,7 +177,7 @@ TEST_CASE("Local Pool Extended Tests [3 Pools]", "[TestPool2]") { size = 8; result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); // Should still work CHECK(testStoreId.poolIndex == 1); CHECK(testStoreId.packetIndex == 1); @@ -181,7 +185,7 @@ TEST_CASE("Local Pool Extended Tests [3 Pools]", "[TestPool2]") { // fill the rest of the pool for (uint8_t idx = 2; idx < 5; idx++) { result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); CHECK(testStoreId.poolIndex == 1); CHECK(testStoreId.packetIndex == idx); } @@ -202,21 +206,21 @@ TEST_CASE("Local Pool Extended Tests [3 Pools]", "[TestPool2]") { size = 5; for (uint8_t idx = 0; idx < 10; idx++) { result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); CHECK(testStoreId.poolIndex == 0); CHECK(testStoreId.packetIndex == idx); } size = 10; for (uint8_t idx = 0; idx < 5; idx++) { result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); CHECK(testStoreId.poolIndex == 1); CHECK(testStoreId.packetIndex == idx); } size = 20; for (uint8_t idx = 0; idx < 2; idx++) { result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); CHECK(testStoreId.poolIndex == 2); CHECK(testStoreId.packetIndex == idx); } @@ -243,7 +247,7 @@ TEST_CASE("Local Pool Extended Tests [3 Pools]", "[TestPool2]") { size = 5; for (uint8_t idx = 0; idx < 10; idx++) { result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); CHECK(testStoreId.poolIndex == 0); CHECK(testStoreId.packetIndex == idx); } @@ -260,7 +264,7 @@ TEST_CASE("Local Pool Extended Tests [3 Pools]", "[TestPool2]") { size = 10; for (uint8_t idx = 0; idx < 5; idx++) { result = simplePool.addData(&testStoreId, testDataArray.data(), size); - REQUIRE(result == retval::CATCH_OK); + REQUIRE(result == returnvalue::OK); CHECK(testStoreId.poolIndex == 1); CHECK(testStoreId.packetIndex == idx); } diff --git a/unittests/tcdistributor/CMakeLists.txt b/unittests/tcdistributor/CMakeLists.txt new file mode 100644 index 00000000..1743440a --- /dev/null +++ b/unittests/tcdistributor/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE testCcsdsDistributor.cpp) diff --git a/unittests/tcdistributor/testCcsdsDistributor.cpp b/unittests/tcdistributor/testCcsdsDistributor.cpp new file mode 100644 index 00000000..c8aa81f7 --- /dev/null +++ b/unittests/tcdistributor/testCcsdsDistributor.cpp @@ -0,0 +1,169 @@ +#include +#include + +#include "fsfw/storagemanager/LocalPool.h" +#include "fsfw/tcdistribution/CcsdsDistributor.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketCreator.h" +#include "mocks/AcceptsTcMock.h" +#include "mocks/CcsdsCheckerMock.h" +#include "mocks/MessageQueueMock.h" + +TEST_CASE("CCSDS Distributor", "[ccsds][tmtcdistrib]") { + LocalPool::LocalPoolConfig cfg = {{5, 32}, {2, 64}}; + LocalPool pool(objects::NO_OBJECT, cfg); + auto queue = MessageQueueMock(1); + auto checkerMock = CcsdsCheckerMock(); + uint16_t unregisteredApid = 0; + uint16_t defaultApid = 4; + MessageQueueId_t defaultQueueId = 5; + auto ccsdsDistrib = CcsdsDistributor(defaultApid, 1, &pool, &queue, &checkerMock); + uint32_t tcAcceptorApid = 1; + MessageQueueId_t tcAcceptorQueueId = 3; + + auto tcAcceptorMock = AcceptsTcMock("TC Receiver Dummy", tcAcceptorApid, tcAcceptorQueueId); + auto defReceiverMock = AcceptsTcMock("Default Receiver Dummy", defaultApid, defaultQueueId); + auto packetId = PacketId(ccsds::PacketType::TC, true, 0); + auto psc = PacketSeqCtrl(ccsds::SequenceFlags::FIRST_SEGMENT, 0x34); + auto spParams = SpacePacketParams(packetId, psc, 0x16); + SpacePacketCreator spCreator(spParams); + std::array buf{}; + + auto createSpacePacket = [&](uint16_t apid, TmTcMessage& msg, uint8_t* dataField = nullptr, + size_t dataFieldLen = 1) { + store_address_t storeId{}; + spCreator.setApid(tcAcceptorApid); + spCreator.setCcsdsLenFromTotalDataFieldLen(dataFieldLen); + uint8_t* dataPtr; + REQUIRE(pool.getFreeElement(&storeId, spCreator.getSerializedSize() + dataFieldLen, &dataPtr) == + returnvalue::OK); + size_t serLen = 0; + REQUIRE(spCreator.SerializeIF::serializeBe(dataPtr, serLen, ccsds::HEADER_LEN) == + returnvalue::OK); + REQUIRE(spCreator.SerializeIF::serializeBe(buf.data(), serLen, ccsds::HEADER_LEN) == + returnvalue::OK); + if (dataField == nullptr) { + dataPtr[ccsds::HEADER_LEN] = 0; + buf[ccsds::HEADER_LEN] = 0; + } else { + std::memcpy(dataPtr + ccsds::HEADER_LEN, dataField, dataFieldLen); + std::memcpy(buf.data() + ccsds::HEADER_LEN, dataField, dataFieldLen); + } + msg.setStorageId(storeId); + }; + + SECTION("State") { + CHECK(ccsdsDistrib.initialize() == returnvalue::OK); + CHECK(ccsdsDistrib.getRequestQueue() == 1); + CHECK(ccsdsDistrib.getIdentifier() == 0); + CHECK(ccsdsDistrib.getObjectId() == 1); + REQUIRE(ccsdsDistrib.getName() != nullptr); + CHECK(std::strcmp(ccsdsDistrib.getName(), "CCSDS Distributor") == 0); + } + + SECTION("Basic Forwarding") { + CcsdsDistributor::DestInfo info(tcAcceptorMock, false); + REQUIRE(ccsdsDistrib.registerApplication(info) == returnvalue::OK); + TmTcMessage message; + createSpacePacket(tcAcceptorApid, message); + store_address_t storeId = message.getStorageId(); + queue.addReceivedMessage(message); + REQUIRE(ccsdsDistrib.performOperation(0) == returnvalue::OK); + CHECK(checkerMock.checkedPacketLen == 7); + CHECK(checkerMock.checkCallCount == 1); + CHECK(queue.wasMessageSent()); + CHECK(queue.numberOfSentMessages() == 1); + // The packet is forwarded, with no need to delete the data + CHECK(pool.hasDataAtId(storeId)); + TmTcMessage sentMsg; + CHECK(queue.getNextSentMessage(tcAcceptorQueueId, sentMsg) == returnvalue::OK); + CHECK(sentMsg.getStorageId() == storeId); + auto accessor = pool.getData(storeId); + CHECK(accessor.first == returnvalue::OK); + CHECK(accessor.second.size() == ccsds::HEADER_LEN + 1); + for (size_t i = 0; i < ccsds::HEADER_LEN; i++) { + CHECK(accessor.second.data()[i] == buf[i]); + } + } + + SECTION("Forwarding to Default Destination, but not registered") { + TmTcMessage message; + createSpacePacket(unregisteredApid, message); + store_address_t storeId = message.getStorageId(); + message.setStorageId(storeId); + queue.addReceivedMessage(message); + REQUIRE(ccsdsDistrib.performOperation(0) == TcDistributorBase::DESTINATION_NOT_FOUND); + } + + SECTION("Forward to Default Handler") { + CcsdsDistributor::DestInfo info(defReceiverMock, false); + ccsdsDistrib.registerApplication(info); + TmTcMessage message; + createSpacePacket(defaultApid, message); + store_address_t storeId = message.getStorageId(); + message.setStorageId(storeId); + queue.addReceivedMessage(message); + REQUIRE(ccsdsDistrib.performOperation(0) == returnvalue::OK); + CHECK(checkerMock.checkedPacketLen == 7); + CHECK(checkerMock.checkCallCount == 1); + CHECK(queue.wasMessageSent()); + CHECK(queue.numberOfSentMessages() == 1); + // The packet is forwarded, with no need to delete the data + CHECK(pool.hasDataAtId(storeId)); + TmTcMessage sentMsg; + CHECK(queue.getNextSentMessage(defaultQueueId, sentMsg) == returnvalue::OK); + CHECK(sentMsg.getStorageId() == storeId); + auto accessor = pool.getData(storeId); + CHECK(accessor.first == returnvalue::OK); + CHECK(accessor.second.size() == ccsds::HEADER_LEN + 1); + for (size_t i = 0; i < ccsds::HEADER_LEN; i++) { + CHECK(accessor.second.data()[i] == buf[i]); + } + } + + SECTION("Remove CCSDS header") { + uint16_t tgtApid = 0; + MessageQueueId_t tgtQueueId = MessageQueueIF::NO_QUEUE; + SECTION("Default destination") { + CcsdsDistributor::DestInfo info(defReceiverMock, true); + tgtApid = defaultApid; + tgtQueueId = defaultQueueId; + REQUIRE(ccsdsDistrib.registerApplication(info) == returnvalue::OK); + } + SECTION("Specific destination") { + CcsdsDistributor::DestInfo info(tcAcceptorMock, true); + tgtApid = tcAcceptorApid; + tgtQueueId = tcAcceptorQueueId; + REQUIRE(ccsdsDistrib.registerApplication(info) == returnvalue::OK); + } + TmTcMessage message; + std::array dataField = {0, 1, 2, 3, 4}; + createSpacePacket(tgtApid, message, dataField.data(), 5); + store_address_t storeId = message.getStorageId(); + message.setStorageId(storeId); + queue.addReceivedMessage(message); + REQUIRE(ccsdsDistrib.performOperation(0) == returnvalue::OK); + CHECK(checkerMock.checkedPacketLen == 11); + CHECK(checkerMock.checkCallCount == 1); + // Data was deleted from old slot to re-store without the header + CHECK(not pool.hasDataAtId(storeId)); + TmTcMessage sentMsg; + CHECK(queue.getNextSentMessage(tgtQueueId, sentMsg) == returnvalue::OK); + CHECK(sentMsg.getStorageId() != storeId); + auto accessor = pool.getData(sentMsg.getStorageId()); + CHECK(accessor.first == returnvalue::OK); + CHECK(accessor.second.size() == 5); + // Verify correctness of data field + for (size_t i = 0; i < 5; i++) { + CHECK(accessor.second.data()[i] == i); + } + } + + SECTION("Invalid Space Packet, Too Short") { + store_address_t storeId{}; + std::array data = {1, 2, 3, 4}; + pool.addData(&storeId, data.data(), data.size()); + TmTcMessage message(storeId); + queue.addReceivedMessage(message); + REQUIRE(ccsdsDistrib.performOperation(0) == SerializeIF::STREAM_TOO_SHORT); + } +} \ No newline at end of file diff --git a/tests/src/fsfw_tests/unit/version.cpp b/unittests/testVersion.cpp similarity index 94% rename from tests/src/fsfw_tests/unit/version.cpp rename to unittests/testVersion.cpp index 2967dfa5..2f487031 100644 --- a/tests/src/fsfw_tests/unit/version.cpp +++ b/unittests/testVersion.cpp @@ -1,10 +1,9 @@ -#include "fsfw/version.h" - #include +#include "CatchDefinitions.h" #include "fsfw/serviceinterface.h" -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "fsfw/version.h" TEST_CASE("Version API Tests", "[TestVersionAPI]") { // Check that major version is non-zero @@ -14,8 +13,8 @@ TEST_CASE("Version API Tests", "[TestVersionAPI]") { REQUIRE(fsfw::Version(255, 0, 0) >= fsfw::FSFW_VERSION); REQUIRE(fsfw::Version(0, 0, 0) < fsfw::FSFW_VERSION); REQUIRE(fsfw::Version(0, 0, 0) <= fsfw::FSFW_VERSION); - fsfw::Version v1 = fsfw::Version(1, 1, 1); - fsfw::Version v2 = fsfw::Version(1, 1, 1); + auto v1 = fsfw::Version(1, 1, 1); + auto v2 = fsfw::Version(1, 1, 1); REQUIRE(v1 == v2); REQUIRE(not(v1 < v2)); REQUIRE(not(v1 > v2)); diff --git a/unittests/testcfg/CMakeLists.txt b/unittests/testcfg/CMakeLists.txt new file mode 100644 index 00000000..3edb59f6 --- /dev/null +++ b/unittests/testcfg/CMakeLists.txt @@ -0,0 +1,16 @@ +target_sources( + ${FSFW_TEST_TGT} PRIVATE ipc/MissionMessageTypes.cpp + pollingsequence/PollingSequenceFactory.cpp) + +# Add include paths for the executable +target_include_directories(${FSFW_TEST_TGT} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + +# If a special translation file for object IDs exists, compile it. +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp") + target_sources(${FSFW_TEST_TGT} PRIVATE objects/translateObjects.cpp) +endif() + +# If a special translation file for events exists, compile it. +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp") + target_sources(${FSFW_TEST_TGT} PRIVATE events/translateEvents.cpp) +endif() diff --git a/tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in b/unittests/testcfg/FSFWConfig.h.in similarity index 100% rename from tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in rename to unittests/testcfg/FSFWConfig.h.in diff --git a/tests/src/fsfw_tests/unit/testcfg/OBSWConfig.h.in b/unittests/testcfg/OBSWConfig.h.in similarity index 100% rename from tests/src/fsfw_tests/unit/testcfg/OBSWConfig.h.in rename to unittests/testcfg/OBSWConfig.h.in diff --git a/tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in b/unittests/testcfg/TestsConfig.h.in similarity index 92% rename from tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in rename to unittests/testcfg/TestsConfig.h.in index 7d950070..1865c41a 100644 --- a/tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in +++ b/unittests/testcfg/TestsConfig.h.in @@ -1,6 +1,8 @@ #ifndef FSFW_UNITTEST_CONFIG_TESTSCONFIG_H_ #define FSFW_UNITTEST_CONFIG_TESTSCONFIG_H_ +#cmakedefine01 FSFW_CICD_BUILD + #define FSFW_ADD_DEFAULT_FACTORY_FUNCTIONS 1 #ifdef __cplusplus diff --git a/tests/src/fsfw_tests/unit/testcfg/devices/logicalAddresses.cpp b/unittests/testcfg/devices/logicalAddresses.cpp similarity index 100% rename from tests/src/fsfw_tests/unit/testcfg/devices/logicalAddresses.cpp rename to unittests/testcfg/devices/logicalAddresses.cpp diff --git a/tests/src/fsfw_tests/unit/testcfg/devices/logicalAddresses.h b/unittests/testcfg/devices/logicalAddresses.h similarity index 88% rename from tests/src/fsfw_tests/unit/testcfg/devices/logicalAddresses.h rename to unittests/testcfg/devices/logicalAddresses.h index 788c124f..a7e34cce 100644 --- a/tests/src/fsfw_tests/unit/testcfg/devices/logicalAddresses.h +++ b/unittests/testcfg/devices/logicalAddresses.h @@ -7,7 +7,7 @@ namespace addresses { /* Logical addresses have uint32_t datatype */ -enum logicalAddresses : address_t {}; +enum LogicAddress : address_t {}; } // namespace addresses #endif /* CONFIG_DEVICES_LOGICALADDRESSES_H_ */ diff --git a/tests/src/fsfw_tests/unit/testcfg/devices/powerSwitcherList.cpp b/unittests/testcfg/devices/powerSwitcherList.cpp similarity index 100% rename from tests/src/fsfw_tests/unit/testcfg/devices/powerSwitcherList.cpp rename to unittests/testcfg/devices/powerSwitcherList.cpp diff --git a/tests/src/fsfw_tests/unit/testcfg/devices/powerSwitcherList.h b/unittests/testcfg/devices/powerSwitcherList.h similarity index 100% rename from tests/src/fsfw_tests/unit/testcfg/devices/powerSwitcherList.h rename to unittests/testcfg/devices/powerSwitcherList.h diff --git a/tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h b/unittests/testcfg/events/subsystemIdRanges.h similarity index 100% rename from tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h rename to unittests/testcfg/events/subsystemIdRanges.h diff --git a/tests/src/fsfw_tests/unit/testcfg/ipc/MissionMessageTypes.cpp b/unittests/testcfg/ipc/MissionMessageTypes.cpp similarity index 100% rename from tests/src/fsfw_tests/unit/testcfg/ipc/MissionMessageTypes.cpp rename to unittests/testcfg/ipc/MissionMessageTypes.cpp diff --git a/tests/src/fsfw_tests/unit/testcfg/ipc/MissionMessageTypes.h b/unittests/testcfg/ipc/MissionMessageTypes.h similarity index 100% rename from tests/src/fsfw_tests/unit/testcfg/ipc/MissionMessageTypes.h rename to unittests/testcfg/ipc/MissionMessageTypes.h diff --git a/tests/src/fsfw_tests/unit/testcfg/objects/systemObjectList.h b/unittests/testcfg/objects/systemObjectList.h similarity index 76% rename from tests/src/fsfw_tests/unit/testcfg/objects/systemObjectList.h rename to unittests/testcfg/objects/systemObjectList.h index 3eba1484..1e86d5f7 100644 --- a/tests/src/fsfw_tests/unit/testcfg/objects/systemObjectList.h +++ b/unittests/testcfg/objects/systemObjectList.h @@ -21,9 +21,14 @@ enum sourceObjects : uint32_t { HK_RECEIVER_MOCK = 22, TEST_LOCAL_POOL_OWNER_BASE = 25, - SHARED_SET_ID = 26 + SHARED_SET_ID = 26, + DUMMY_POWER_SWITCHER = 28, + + DEVICE_HANDLER_MOCK = 29, + COM_IF_MOCK = 30, + DEVICE_HANDLER_COMMANDER = 40, }; } -#endif /* BSP_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ */ +#endif /* HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ */ diff --git a/tests/src/fsfw_tests/unit/testcfg/pollingsequence/PollingSequenceFactory.cpp b/unittests/testcfg/pollingsequence/PollingSequenceFactory.cpp similarity index 84% rename from tests/src/fsfw_tests/unit/testcfg/pollingsequence/PollingSequenceFactory.cpp rename to unittests/testcfg/pollingsequence/PollingSequenceFactory.cpp index 0c44f6a2..2ee88f96 100644 --- a/tests/src/fsfw_tests/unit/testcfg/pollingsequence/PollingSequenceFactory.cpp +++ b/unittests/testcfg/pollingsequence/PollingSequenceFactory.cpp @@ -4,6 +4,7 @@ #include #include +#include "fsfw/FSFW.h" #include "tests/TestsConfig.h" ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) { @@ -17,14 +18,14 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) thisSequence->addSlot(objects::TEST_DEVICE, 0.6 * length, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::TEST_DEVICE, 0.8 * length, DeviceHandlerIF::GET_READ); - if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { - return HasReturnvaluesIF::RETURN_OK; + if (thisSequence->checkSequence() == returnvalue::OK) { + return returnvalue::OK; } else { -#if FSFW_CPP_OSTREAM_ENABLED +#if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "pst::pollingSequenceInitDefault: Sequence invalid!" << std::endl; #else sif::printError("pst::pollingSequenceInitDefault: Sequence invalid!"); #endif - return HasReturnvaluesIF::RETURN_FAILED; + return returnvalue::FAILED; } } diff --git a/tests/src/fsfw_tests/unit/testcfg/pollingsequence/PollingSequenceFactory.h b/unittests/testcfg/pollingsequence/PollingSequenceFactory.h similarity index 95% rename from tests/src/fsfw_tests/unit/testcfg/pollingsequence/PollingSequenceFactory.h rename to unittests/testcfg/pollingsequence/PollingSequenceFactory.h index fc9891b2..daba33a8 100644 --- a/tests/src/fsfw_tests/unit/testcfg/pollingsequence/PollingSequenceFactory.h +++ b/unittests/testcfg/pollingsequence/PollingSequenceFactory.h @@ -1,7 +1,7 @@ #ifndef POLLINGSEQUENCEFACTORY_H_ #define POLLINGSEQUENCEFACTORY_H_ -#include +#include class FixedTimeslotTaskIF; diff --git a/tests/src/fsfw_tests/unit/testcfg/returnvalues/classIds.h b/unittests/testcfg/returnvalues/classIds.h similarity index 100% rename from tests/src/fsfw_tests/unit/testcfg/returnvalues/classIds.h rename to unittests/testcfg/returnvalues/classIds.h diff --git a/tests/src/fsfw_tests/unit/testcfg/tmtc/apid.h b/unittests/testcfg/tmtc/apid.h similarity index 100% rename from tests/src/fsfw_tests/unit/testcfg/tmtc/apid.h rename to unittests/testcfg/tmtc/apid.h diff --git a/tests/src/fsfw_tests/unit/testcfg/tmtc/pusIds.h b/unittests/testcfg/tmtc/pusIds.h similarity index 100% rename from tests/src/fsfw_tests/unit/testcfg/tmtc/pusIds.h rename to unittests/testcfg/tmtc/pusIds.h diff --git a/tests/src/fsfw_tests/unit/testtemplate/TestTemplate.cpp b/unittests/testtemplate/TestTemplate.cpp similarity index 100% rename from tests/src/fsfw_tests/unit/testtemplate/TestTemplate.cpp rename to unittests/testtemplate/TestTemplate.cpp diff --git a/unittests/timemanager/CMakeLists.txt b/unittests/timemanager/CMakeLists.txt new file mode 100644 index 00000000..ad9cae23 --- /dev/null +++ b/unittests/timemanager/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE TestCountdown.cpp TestCCSDSTime.cpp) diff --git a/tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp b/unittests/timemanager/TestCCSDSTime.cpp similarity index 83% rename from tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp rename to unittests/timemanager/TestCCSDSTime.cpp index a43ff8ab..0b1b602c 100644 --- a/tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp +++ b/unittests/timemanager/TestCCSDSTime.cpp @@ -5,11 +5,11 @@ #include #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { INFO("CCSDSTime Tests"); - CCSDSTime::Ccs_mseconds cssMilliSecconds; + CCSDSTime::Ccs_mseconds cssMilliSecconds{}; Clock::TimeOfDay_t time; time.year = 2020; time.month = 2; @@ -20,7 +20,7 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { time.usecond = 123456; SECTION("Test CCS Time") { auto result = CCSDSTime::convertToCcsds(&cssMilliSecconds, &time); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(cssMilliSecconds.pField == 0x52); // 0b01010010 REQUIRE(cssMilliSecconds.yearMSB == 0x07); REQUIRE(cssMilliSecconds.yearLSB == 0xe4); @@ -36,7 +36,7 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { const uint8_t* dataPtr = reinterpret_cast(&cssMilliSecconds); size_t length = sizeof(CCSDSTime::Ccs_mseconds); result = CCSDSTime::convertFromCCS(&timeTo, dataPtr, &length, sizeof(CCSDSTime::Ccs_mseconds)); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(cssMilliSecconds.pField == 0x52); // 0b01010010 REQUIRE(cssMilliSecconds.yearMSB == 0x07); REQUIRE(cssMilliSecconds.yearLSB == 0xe4); @@ -59,7 +59,7 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { size_t length = ccsDayOfYear.size(); auto result = CCSDSTime::convertFromCCS(&timeTo, ccsDayOfYear.data(), &length, ccsDayOfYear.size()); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); // Check constness REQUIRE(ccsDayOfYear[0] == 0b01011000); REQUIRE(ccsDayOfYear[1] == 0x07); @@ -82,7 +82,7 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { Clock::TimeOfDay_t timeTo; const uint8_t* timeChar = reinterpret_cast(timeAscii.c_str()); auto result = CCSDSTime::convertFromASCII(&timeTo, timeChar, timeAscii.length()); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(timeTo.year == 2022); REQUIRE(timeTo.month == 12); REQUIRE(timeTo.day == 31); @@ -95,7 +95,7 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { const uint8_t* timeChar2 = reinterpret_cast(timeAscii2.c_str()); Clock::TimeOfDay_t timeTo2; result = CCSDSTime::convertFromCcsds(&timeTo2, timeChar2, timeAscii2.length()); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); REQUIRE(timeTo2.year == 2022); REQUIRE(timeTo2.month == 12); REQUIRE(timeTo2.day == 31); @@ -117,14 +117,14 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { time.usecond = 123456; timeval timeAsTimeval; auto result = Clock::convertTimeOfDayToTimeval(&time, &timeAsTimeval); - CHECK(result == HasReturnvaluesIF::RETURN_OK); + CHECK(result == returnvalue::OK); CHECK(timeAsTimeval.tv_sec == 1582982685); CHECK(timeAsTimeval.tv_usec == 123456); // Conversion to CDS Short CCSDSTime::CDS_short cdsTime; result = CCSDSTime::convertToCcsds(&cdsTime, &timeAsTimeval); - CHECK(result == HasReturnvaluesIF::RETURN_OK); + CHECK(result == returnvalue::OK); // Days in CCSDS Epoch 22704 (0x58B0) CHECK(cdsTime.dayMSB == 0x58); CHECK(cdsTime.dayLSB == 0xB0); @@ -138,7 +138,7 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { // Conversion back to timeval timeval timeReturnAsTimeval; result = CCSDSTime::convertFromCDS(&timeReturnAsTimeval, &cdsTime); - CHECK(result == HasReturnvaluesIF::RETURN_OK); + CHECK(result == returnvalue::OK); // micro seconds precision is lost timeval difference = timeAsTimeval - timeReturnAsTimeval; CHECK(difference.tv_usec == 456); @@ -146,7 +146,7 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { Clock::TimeOfDay_t timeReturnAsTimeOfDay; result = CCSDSTime::convertFromCDS(&timeReturnAsTimeOfDay, &cdsTime); - CHECK(result == HasReturnvaluesIF::RETURN_OK); + CHECK(result == returnvalue::OK); CHECK(timeReturnAsTimeOfDay.year == 2020); CHECK(timeReturnAsTimeOfDay.month == 2); CHECK(timeReturnAsTimeOfDay.day == 29); @@ -159,7 +159,7 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { Clock::TimeOfDay_t timeReturnAsTodFromBuffer; const uint8_t* buffer = reinterpret_cast(&cdsTime); result = CCSDSTime::convertFromCDS(&timeReturnAsTodFromBuffer, buffer, sizeof(cdsTime)); - REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(result == returnvalue::OK); CHECK(timeReturnAsTodFromBuffer.year == time.year); CHECK(timeReturnAsTodFromBuffer.month == time.month); CHECK(timeReturnAsTodFromBuffer.day == time.day); @@ -170,7 +170,7 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { Clock::TimeOfDay_t todFromCCSDS; result = CCSDSTime::convertFromCcsds(&todFromCCSDS, buffer, sizeof(cdsTime)); - CHECK(result == HasReturnvaluesIF::RETURN_OK); + CHECK(result == returnvalue::OK); CHECK(todFromCCSDS.year == time.year); CHECK(todFromCCSDS.month == time.month); CHECK(todFromCCSDS.day == time.day); @@ -179,6 +179,27 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { CHECK(todFromCCSDS.second == time.second); CHECK(todFromCCSDS.usecond == 123000); } + SECTION("CUC") { + timeval to; + // seconds = 0x771E960F, microseconds = 0x237 + // microseconds = 567000 + // This gives 37158.912 1/65536 seconds -> rounded to 37159 -> 0x9127 + // This results in -> 567001 us + std::array cucBuffer = { + CCSDSTime::P_FIELD_CUC_6B_CCSDS, 0x77, 0x1E, 0x96, 0x0F, 0x91, 0x27}; + size_t foundLength = 0; + auto result = CCSDSTime::convertFromCUC(&to, cucBuffer.data(), &foundLength, cucBuffer.size()); + REQUIRE(result == returnvalue::OK); + REQUIRE(foundLength == 7); + REQUIRE(to.tv_sec == 1619801999); // TAI (no leap seconds) + REQUIRE(to.tv_usec == 567001); + + Clock::TimeOfDay_t tod; + result = CCSDSTime::convertFromCUC(&tod, cucBuffer.data(), cucBuffer.size()); + // This test must be changed if this is ever going to be implemented + REQUIRE(result == CCSDSTime::UNSUPPORTED_TIME_FORMAT); + } + SECTION("CCSDS Failures") { Clock::TimeOfDay_t time; time.year = 2020; diff --git a/tests/src/fsfw_tests/unit/timemanager/TestCountdown.cpp b/unittests/timemanager/TestCountdown.cpp similarity index 73% rename from tests/src/fsfw_tests/unit/timemanager/TestCountdown.cpp rename to unittests/timemanager/TestCountdown.cpp index bc39b02e..67f4ddb2 100644 --- a/tests/src/fsfw_tests/unit/timemanager/TestCountdown.cpp +++ b/unittests/timemanager/TestCountdown.cpp @@ -2,15 +2,15 @@ #include -#include "fsfw_tests/unit/CatchDefinitions.h" +#include "CatchDefinitions.h" TEST_CASE("Countdown Tests", "[TestCountdown]") { INFO("Countdown Tests"); Countdown count(20); REQUIRE(count.timeout == 20); - REQUIRE(count.setTimeout(100) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(count.setTimeout(100) == static_cast(returnvalue::OK)); REQUIRE(count.timeout == 100); - REQUIRE(count.setTimeout(150) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(count.setTimeout(150) == static_cast(returnvalue::OK)); REQUIRE(count.isBusy()); REQUIRE(not count.hasTimedOut()); uint32_t number = count.getRemainingMillis(); diff --git a/unittests/tmtcpacket/CMakeLists.txt b/unittests/tmtcpacket/CMakeLists.txt new file mode 100644 index 00000000..4415685e --- /dev/null +++ b/unittests/tmtcpacket/CMakeLists.txt @@ -0,0 +1,10 @@ +target_sources( + ${FSFW_TEST_TGT} + PRIVATE testCcsdsCreator.cpp + testCcsdsReader.cpp + testPusTcCreator.cpp + testPusTcReader.cpp + testPusTmCreator.cpp + testPusTmReader.cpp + testCcsds.cpp + testZcTmWriter.cpp) diff --git a/unittests/tmtcpacket/testCcsds.cpp b/unittests/tmtcpacket/testCcsds.cpp new file mode 100644 index 00000000..233e4ada --- /dev/null +++ b/unittests/tmtcpacket/testCcsds.cpp @@ -0,0 +1,134 @@ +#include +#include +#include + +#include "fsfw/tmtcpacket/ccsds/PacketId.h" +#include "fsfw/tmtcpacket/ccsds/PacketSeqCtrl.h" +#include "fsfw/tmtcpacket/ccsds/header.h" + +TEST_CASE("CCSDS Low Level", "[ccsds-ll]") { + SECTION("Lowlevel Header Packet ID test") { + ccsds::PrimaryHeader header{}; + uint16_t packetIdRaw = 0x3ff; + ccsds::setPacketId(header, packetIdRaw); + REQUIRE(header.packetIdHAndVersion == 3); + REQUIRE(header.packetIdL == 0xff); + REQUIRE(ccsds::getPacketId(header) == 0x3ff); + header.packetIdHAndVersion |= 0b00100000; + REQUIRE(ccsds::getPacketId(header) == 0x3ff); + REQUIRE(ccsds::getVersion(header) == 0b001); + } + + SECTION("Lowlevel Header APID Test") { + ccsds::PrimaryHeader header{}; + uint16_t packetIdRaw = 0x3ff; + ccsds::setPacketId(header, packetIdRaw); + ccsds::setApid(header, 0x1ff); + REQUIRE(ccsds::getPacketId(header) == 0x3ff); + } + + SECTION("Lowlevel Packet Length Test") { + ccsds::PrimaryHeader header{}; + header.packetLenH = 0x02; + header.packetLenL = 0x03; + REQUIRE(ccsds::getPacketLen(header) == 0x0203); + } +} + +TEST_CASE("CCSDS Packet ID", "[ccsds-packet-id]") { + PacketId packetId; + std::array buf{}; + SECTION("Basic") { + packetId.apid = 0x1ff; + packetId.secHeaderFlag = false; + packetId.packetType = ccsds::PacketType::TM; + size_t serLen = 0; + REQUIRE(packetId.raw() == 0x1ff); + REQUIRE(packetId.SerializeIF::serializeBe(buf.data(), serLen, buf.size()) == returnvalue::OK); + CHECK(buf[0] == 0x1); + CHECK(buf[1] == 0xff); + } + + SECTION("Invalid Ser") { + size_t serLen = 0; + REQUIRE(packetId.SerializeIF::serializeBe(buf.data(), serLen, 0) == + SerializeIF::BUFFER_TOO_SHORT); + REQUIRE(packetId.SerializeIF::serializeBe(buf.data(), serLen, 1) == + SerializeIF::BUFFER_TOO_SHORT); + } + + SECTION("Invalid Deser") { + size_t deserLen = 0; + REQUIRE(packetId.deSerialize(buf.data(), deserLen, 1, SerializeIF::Endianness::NETWORK) == + SerializeIF::STREAM_TOO_SHORT); + REQUIRE(packetId.deSerialize(buf.data(), deserLen, 0, SerializeIF::Endianness::NETWORK) == + SerializeIF::STREAM_TOO_SHORT); + } + + SECTION("From Raw") { + auto newId = PacketId(ccsds::PacketType::TC, true, 0x2ff); + uint16_t rawId = newId.raw(); + CHECK(rawId == 0x1aff); + CHECK(PacketId::fromRaw(rawId) == newId); + } + + SECTION("Deserialize") { + buf[0] = 0x1a; + buf[1] = 0xff; + size_t deserLen = 0xff; + REQUIRE(packetId.deSerialize(buf.data(), deserLen, buf.size(), + SerializeIF::Endianness::NETWORK) == returnvalue::OK); + CHECK(packetId.apid == 0x2ff); + CHECK(deserLen == 2); + CHECK(packetId.packetType == ccsds::PacketType::TC); + CHECK(packetId.secHeaderFlag == true); + } +} + +TEST_CASE("CCSDS Packet Seq Ctrl", "[ccsds-packet-seq-ctrl]") { + PacketSeqCtrl psc; + std::array buf{}; + SECTION("Basic") { + size_t serLen = 0xff; + psc.seqFlags = ccsds::SequenceFlags::FIRST_SEGMENT; + psc.seqCount = static_cast(std::round(std::pow(2, 14) - 1)); + REQUIRE(psc.raw() == 0x7fff); + REQUIRE(psc.SerializeIF::serializeBe(buf.data(), serLen, buf.size()) == returnvalue::OK); + CHECK(buf[0] == 0x7f); + CHECK(buf[1] == 0xff); + CHECK(serLen == 2); + } + + SECTION("From Raw") { + auto newId = PacketSeqCtrl(ccsds::SequenceFlags::LAST_SEGMENT, + static_cast(std::round(std::pow(2, 14) - 2))); + uint16_t rawId = newId.raw(); + REQUIRE(rawId == 0xbffe); + CHECK(PacketSeqCtrl::fromRaw(rawId) == newId); + } + + SECTION("Deserialize") { + buf[0] = 0xbf; + buf[1] = 0xfe; + size_t deserLen = 0xff; + REQUIRE(psc.deSerialize(buf.data(), deserLen, buf.size(), SerializeIF::Endianness::NETWORK) == + returnvalue::OK); + CHECK(psc.seqFlags == ccsds::SequenceFlags::LAST_SEGMENT); + CHECK(deserLen == 2); + CHECK(psc.seqCount == static_cast(std::round(std::pow(2, 14) - 2))); + } + + SECTION("Invalid Ser") { + size_t deserLen = 0; + REQUIRE(psc.SerializeIF::serializeBe(buf.data(), deserLen, 0) == SerializeIF::BUFFER_TOO_SHORT); + REQUIRE(psc.SerializeIF::serializeBe(buf.data(), deserLen, 1) == SerializeIF::BUFFER_TOO_SHORT); + } + + SECTION("Invalid Deser") { + size_t deserLen = 0; + REQUIRE(psc.deSerialize(buf.data(), deserLen, 1, SerializeIF::Endianness::NETWORK) == + SerializeIF::STREAM_TOO_SHORT); + REQUIRE(psc.deSerialize(buf.data(), deserLen, 0, SerializeIF::Endianness::NETWORK) == + SerializeIF::STREAM_TOO_SHORT); + } +} diff --git a/unittests/tmtcpacket/testCcsdsCreator.cpp b/unittests/tmtcpacket/testCcsdsCreator.cpp new file mode 100644 index 00000000..cd9b3e97 --- /dev/null +++ b/unittests/tmtcpacket/testCcsdsCreator.cpp @@ -0,0 +1,123 @@ +#include +#include +#include + +#include "fsfw/tmtcpacket/ccsds/SpacePacketCreator.h" + +TEST_CASE("CCSDS Creator", "[ccsds-creator]") { + auto packetId = PacketId(ccsds::PacketType::TC, true, 0x02); + auto psc = PacketSeqCtrl(ccsds::SequenceFlags::FIRST_SEGMENT, 0x34); + auto params = SpacePacketParams(packetId, psc, 0x16); + SpacePacketCreator base = SpacePacketCreator(params); + std::array buf{}; + uint8_t* bufPtr = buf.data(); + size_t serLen = 0; + + SECTION("Constexpr Helpers") { + REQUIRE(ccsds::getTcSpacePacketIdFromApid(0x22, true) == 0x1822); + REQUIRE(ccsds::getTmSpacePacketIdFromApid(0x22, true) == 0x0822); + + REQUIRE(ccsds::getTcSpacePacketIdFromApid(0x22, false) == 0x1022); + REQUIRE(ccsds::getTmSpacePacketIdFromApid(0x22, false) == 0x0022); + + REQUIRE(ccsds::getTcSpacePacketIdFromApid(0x7ff, true) == 0x1fff); + REQUIRE(ccsds::getTmSpacePacketIdFromApid(0x7ff, true) == 0xfff); + + REQUIRE(ccsds::getTcSpacePacketIdFromApid(0x7ff, false) == 0x17ff); + REQUIRE(ccsds::getTmSpacePacketIdFromApid(0x7ff, false) == 0x7ff); + } + + SECTION("Basic Test") { + CHECK(base.isValid()); + CHECK(base); + CHECK(base.getApid() == 0x02); + CHECK(base.getSequenceFlags() == ccsds::SequenceFlags::FIRST_SEGMENT); + CHECK(base.getVersion() == 0b000); + CHECK(base.getSequenceCount() == 0x34); + CHECK(base.getPacketDataLen() == 0x16); + CHECK(base.getPacketType() == ccsds::PacketType::TC); + CHECK(base.getPacketIdRaw() == 0x1802); + CHECK(base.getSerializedSize() == 6); + CHECK(base.getPacketSeqCtrl() == psc); + CHECK(base.getPacketId() == packetId); + } + + SECTION("Deserialization Fails") { + serLen = 6; + const uint8_t* readOnlyPtr = buf.data(); + auto& ser = dynamic_cast(base); + REQUIRE(ser.deSerialize(&readOnlyPtr, &serLen, SerializeIF::Endianness::BIG) == + returnvalue::FAILED); + } + + SECTION("Raw Output") { + REQUIRE(base.serializeBe(&bufPtr, &serLen, buf.size()) == returnvalue::OK); + // TC, and secondary header flag is set -> 0b0001100 -> 0x18 + CHECK(buf[0] == 0x18); + // APID 0x02 + CHECK(buf[1] == 0x02); + // Sequence count is one byte value, so the only set bit here is the bit + // from the Sequence flag argument, which is the second bit for + // SequenceFlags.FIRST_SEGMENT + CHECK(buf[2] == 0x40); + // Sequence Count specified above + CHECK(buf[3] == 0x34); + // This byte and the next byte should be 22 big endian (packet length) + CHECK(buf[4] == 0x00); + CHECK(buf[5] == 0x16); + } + + SECTION("All Ones Output") { + base.setApid(static_cast(std::pow(2, 11)) - 1); + base.setSeqCount(static_cast(std::pow(2, 14)) - 1); + base.setSeqFlags(ccsds::SequenceFlags::UNSEGMENTED); + base.setDataLenField(static_cast(std::pow(2, 16)) - 1); + REQUIRE(base.isValid()); + REQUIRE(base.serializeBe(&bufPtr, &serLen, buf.size()) == returnvalue::OK); + CHECK(buf[0] == 0x1F); + CHECK(buf[1] == 0xFF); + CHECK(buf[2] == 0xFF); + CHECK(buf[3] == 0xFF); + CHECK(buf[4] == 0xFF); + CHECK(buf[5] == 0xFF); + } + + SECTION("Setting data length 0 is ignored") { + SpacePacketCreator creator = SpacePacketCreator( + ccsds::PacketType::TC, true, 0xFFFF, ccsds::SequenceFlags::FIRST_SEGMENT, 0x34, 0x22); + creator.setCcsdsLenFromTotalDataFieldLen(0); + REQUIRE(creator.getPacketDataLen() == 0x22); + creator.setCcsdsLenFromTotalDataFieldLen(1); + REQUIRE(creator.getPacketDataLen() == 0x00); + } + + SECTION("Invalid APID") { + SpacePacketCreator creator = SpacePacketCreator( + ccsds::PacketType::TC, true, 0xFFFF, ccsds::SequenceFlags::FIRST_SEGMENT, 0x34, 0x16); + REQUIRE(not creator.isValid()); + REQUIRE(not creator); + REQUIRE(creator.serializeBe(&bufPtr, &serLen, buf.size()) == returnvalue::FAILED); + } + + SECTION("Invalid Seq Count") { + SpacePacketCreator invalid = SpacePacketCreator( + ccsds::PacketType::TC, true, 0x02, ccsds::SequenceFlags::FIRST_SEGMENT, 0xFFFF, 0x16); + REQUIRE(not invalid.isValid()); + REQUIRE(invalid.serializeBe(&bufPtr, &serLen, buf.size()) == returnvalue::FAILED); + } + + SECTION("Invalid Buf Size 1") { + serLen = 2; + REQUIRE(base.serializeBe(&bufPtr, &serLen, buf.size()) == SerializeIF::BUFFER_TOO_SHORT); + } + + SECTION("Invalid Buf Size 2") { + serLen = 4; + REQUIRE(base.serializeBe(&bufPtr, &serLen, buf.size()) == SerializeIF::BUFFER_TOO_SHORT); + } + + SECTION("Invalid Buf Size 3") { + serLen = 6; + REQUIRE(base.serializeBe(&bufPtr, &serLen, buf.size()) == SerializeIF::BUFFER_TOO_SHORT); + } +} diff --git a/unittests/tmtcpacket/testCcsdsReader.cpp b/unittests/tmtcpacket/testCcsdsReader.cpp new file mode 100644 index 00000000..5a36d70d --- /dev/null +++ b/unittests/tmtcpacket/testCcsdsReader.cpp @@ -0,0 +1,71 @@ +#include +#include + +#include "fsfw/tmtcpacket/ccsds/SpacePacketCreator.h" +#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" + +#define FULL_PACKET_LEN 29 + +TEST_CASE("CCSDS Reader", "[ccsds-reader]") { + auto params = SpacePacketParams(PacketId(ccsds::PacketType::TC, true, 0x02), + PacketSeqCtrl(ccsds::SequenceFlags::FIRST_SEGMENT, 0x34), 0x16); + SpacePacketCreator base = SpacePacketCreator(params); + // This is enough to hold 0x16 (22) bytes + 6 (SP header length) + 1 as defined as the full packet + // length derived from the length field + std::array buf{}; + uint8_t* bufPtr = buf.data(); + size_t serLen = 0; + SpacePacketReader reader; + + auto checkReader = [&](SpacePacketReader& reader) { + REQUIRE(reader.getPacketDataLen() == 0x16); + REQUIRE(reader.getBufSize() == SpacePacketIF::getHeaderLen()); + REQUIRE(reader.getFullData() == buf.data()); + REQUIRE(reader.getFullPacketLen() == 0x16 + SpacePacketReader::getHeaderLen() + 1); + REQUIRE(reader.getPacketIdRaw() == 0x1802); + REQUIRE(reader.getSequenceFlags() == ccsds::SequenceFlags::FIRST_SEGMENT); + REQUIRE(reader.getSequenceCount() == 0x34); + REQUIRE(reader.getPacketSeqCtrlRaw() == 0x4034); + REQUIRE(reader.hasSecHeader()); + REQUIRE(reader.getApid() == 0x02); + REQUIRE(not reader.isNull()); + // We only serialized the 6 bytes of the header, so the packer data should be invalid + REQUIRE(reader.getPacketData() == nullptr); + }; + + SECTION("Empty Reader") { + REQUIRE(SpacePacketIF::getHeaderLen() == 6); + REQUIRE(reader.isNull()); + REQUIRE(reader.checkSize() == returnvalue::FAILED); + } + + SECTION("Basic Read") { + REQUIRE(base.serialize(&bufPtr, &serLen, buf.size(), SerializeIF::Endianness::NETWORK) == + returnvalue::OK); + SECTION("Setter") { + reader.setReadOnlyData(buf.data(), SpacePacketIF::getHeaderLen()); + checkReader(reader); + } + SECTION("Direct Construction") { + SpacePacketReader secondReader(buf.data(), serLen); + checkReader(secondReader); + } + } + + SECTION("Read with additional data") { + REQUIRE(base.serialize(&bufPtr, &serLen, buf.size(), SerializeIF::Endianness::NETWORK) == + returnvalue::OK); + REQUIRE(reader.setReadOnlyData(buf.data(), buf.size()) == returnvalue::OK); + REQUIRE(reader.getBufSize() == buf.size()); + REQUIRE(reader.getFullPacketLen() == FULL_PACKET_LEN); + REQUIRE(reader.getPacketData() == buf.data() + SpacePacketIF::getHeaderLen()); + } + + SECTION("Invalid Size") { + for (size_t i = 0; i < 5; i++) { + REQUIRE(reader.setReadOnlyData(buf.data(), i) == SerializeIF::STREAM_TOO_SHORT); + REQUIRE(reader.isNull()); + REQUIRE(reader.getPacketData() == nullptr); + } + } +} \ No newline at end of file diff --git a/unittests/tmtcpacket/testPusTcCreator.cpp b/unittests/tmtcpacket/testPusTcCreator.cpp new file mode 100644 index 00000000..58f8cbf9 --- /dev/null +++ b/unittests/tmtcpacket/testPusTcCreator.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include "fsfw/globalfunctions/CRC.h" +#include "fsfw/tmtcpacket/pus/tc.h" +#include "mocks/SimpleSerializable.h" + +TEST_CASE("PUS TC Creator", "[pus-tc-creator]") { + auto packetId = PacketId(ccsds::PacketType::TC, true, 0x02); + auto spParams = + SpacePacketParams(packetId, PacketSeqCtrl(ccsds::SequenceFlags::UNSEGMENTED, 0x34), 0x00); + auto pusParams = PusTcParams(17, 1); + PusTcCreator creator(spParams, pusParams); + std::array buf{}; + uint8_t* dataPtr = buf.data(); + size_t serLen = 0; + + SECTION("State") { + CHECK(creator.isTc()); + CHECK(creator.hasSecHeader()); + CHECK(creator.getService() == 17); + CHECK(creator.getSubService() == 1); + CHECK(creator.getApid() == 0x02); + CHECK(creator.getPusVersion() == 2); + CHECK(creator.getAcknowledgeFlags() == 0b1111); + CHECK(creator.getSourceId() == 0x00); + CHECK(creator.getPacketSeqCtrlRaw() == 0xc034); + // bytes CCSDS header, 5 bytes secondary header, 2 bytes CRC, 3 bytes app data + CHECK(creator.getFullPacketLen() == 13); + // The data length field is the full packet length minus the primary header minus 1 + CHECK(creator.getPacketDataLen() == 6); + auto& paramsLocal = creator.getSpParams(); + CHECK(paramsLocal.packetId == packetId); + } + + SECTION("Serialized") { + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + REQUIRE(serLen == 13); + REQUIRE(buf[0] == 0x18); + REQUIRE(buf[1] == 0x02); + // Unsegmented, first 2 bits 11 + REQUIRE(buf[2] == 0xc0); + // Packet Sequence count only occupies lower byte of packet sequence control + REQUIRE(buf[3] == 0x34); + // Data length packed big endian + REQUIRE(buf[4] == 0x00); + REQUIRE(buf[5] == 0x06); + // PUS Version C (2) + REQUIRE(((buf[6] >> 4) & 0b1111) == 2); + // All Ack Fields is default + REQUIRE((buf[6] & 0b1111) == 0b1111); + // Service and subservice + REQUIRE(buf[7] == 17); + REQUIRE(buf[8] == 1); + // Source ID is 0 + REQUIRE(((buf[9] << 8) | buf[10]) == 0); + // CRC16 check + REQUIRE(CRC::crc16ccitt(buf.data(), serLen) == 0); + REQUIRE(buf[11] == 0xee); + REQUIRE(buf[12] == 0x63); + } + + SECTION("Custom Source ID") { + auto& params = creator.getPusParams(); + params.sourceId = 0x5ff; + REQUIRE(creator.getSourceId() == 0x5ff); + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + REQUIRE(((buf[9] << 8) | buf[10]) == 0x5ff); + } + + SECTION("Test with Application Data Raw") { + auto& params = creator.getPusParams(); + std::array data{1, 2, 3}; + params.setRawAppData(data.data(), data.size()); + // To get correct size information, the SP length field needs to be updated automatically + REQUIRE(creator.getSerializedSize() == 13); + creator.updateSpLengthField(); + REQUIRE(creator.getSerializedSize() == 16); + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + REQUIRE(serLen == 16); + REQUIRE(buf[11] == 1); + REQUIRE(buf[12] == 2); + REQUIRE(buf[13] == 3); + } + + SECTION("Test with Application Data Serializable") { + auto& params = creator.getPusParams(); + auto simpleSer = SimpleSerializable(); + creator.setSerializableUserData(simpleSer); + REQUIRE(creator.getSerializedSize() == 16); + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + REQUIRE(serLen == 16); + REQUIRE(buf[11] == 1); + REQUIRE(buf[12] == 2); + REQUIRE(buf[13] == 3); + } + + SECTION("Test with Application Data Serializable Simple Ser API") { + auto& params = creator.getPusParams(); + auto simpleSer = SimpleSerializable(); + creator.setSerializableUserData(simpleSer); + REQUIRE(creator.getSerializedSize() == 16); + REQUIRE(creator.serializeBe(dataPtr, serLen, buf.size()) == returnvalue::OK); + REQUIRE(serLen == 16); + REQUIRE(buf[11] == 1); + REQUIRE(buf[12] == 2); + REQUIRE(buf[13] == 3); + } + + SECTION("Deserialization Fails") { + SerializeIF& deser = creator; + size_t deserLen = buf.size(); + const uint8_t* roPtr = buf.data(); + REQUIRE(deser.deSerialize(&roPtr, &deserLen, SerializeIF::Endianness::NETWORK) == + returnvalue::FAILED); + } + + SECTION("Serialize with invalid buffer length") { + size_t reqSize = creator.getSerializedSize(); + for (size_t maxSize = 0; maxSize < reqSize; maxSize++) { + dataPtr = buf.data(); + serLen = 0; + REQUIRE(creator.serializeBe(&dataPtr, &serLen, maxSize) == SerializeIF::BUFFER_TOO_SHORT); + } + } + + SECTION("Invalid PUS Version") { + auto& params = creator.getPusParams(); + params.pusVersion = 0; + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == PusIF::INVALID_PUS_VERSION); + } +} \ No newline at end of file diff --git a/unittests/tmtcpacket/testPusTcReader.cpp b/unittests/tmtcpacket/testPusTcReader.cpp new file mode 100644 index 00000000..3dbb8f81 --- /dev/null +++ b/unittests/tmtcpacket/testPusTcReader.cpp @@ -0,0 +1,85 @@ +#include +#include + +#include "fsfw/tmtcpacket/pus/tc/PusTcCreator.h" +#include "fsfw/tmtcpacket/pus/tc/PusTcReader.h" + +TEST_CASE("PUS TC Reader", "[pus-tc-reader]") { + auto packetId = PacketId(ccsds::PacketType::TC, true, 0x02); + auto spParams = + SpacePacketParams(packetId, PacketSeqCtrl(ccsds::SequenceFlags::UNSEGMENTED, 0x34), 0x00); + auto pusParams = PusTcParams(17, 1); + PusTcCreator creator(spParams, pusParams); + std::array buf{}; + uint8_t* dataPtr = buf.data(); + size_t serLen = 0; + PusTcReader reader; + + SECTION("State") { + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + REQUIRE(reader.isNull()); + REQUIRE(not reader); + PusTcReader* readerPtr = nullptr; + bool callDelete = false; + SECTION("Setter") { + readerPtr = &reader; + REQUIRE(readerPtr->setReadOnlyData(buf.data(), serLen) == returnvalue::OK); + REQUIRE(readerPtr->parseDataWithCrcCheck() == returnvalue::OK); + } + SECTION("Directly Constructed") { + callDelete = true; + readerPtr = new PusTcReader(buf.data(), serLen); + REQUIRE(not readerPtr->isNull()); + REQUIRE(readerPtr->parseDataWithCrcCheck() == returnvalue::OK); + } + REQUIRE(not readerPtr->isNull()); + REQUIRE(*readerPtr); + REQUIRE(readerPtr->getPacketType() == ccsds::PacketType::TC); + REQUIRE(readerPtr->getApid() == 0x02); + REQUIRE(readerPtr->getService() == 17); + REQUIRE(readerPtr->getSubService() == 1); + REQUIRE(readerPtr->getFullPacketLen() == 13); + REQUIRE(readerPtr->getPacketDataLen() == 6); + REQUIRE(readerPtr->getPusVersion() == 2); + REQUIRE(readerPtr->getSequenceCount() == 0x34); + REQUIRE(readerPtr->getUserData() == nullptr); + REQUIRE(readerPtr->getUserDataLen() == 0); + REQUIRE(readerPtr->getFullData() == buf.data()); + REQUIRE(readerPtr->getSourceId() == 0x00); + REQUIRE(readerPtr->getAcknowledgeFlags() == 0b1111); + // This value was verified to be correct + REQUIRE(readerPtr->getErrorControl() == 0xee63); + if (callDelete) { + delete readerPtr; + } + } + + SECTION("Invalid CRC") { + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + REQUIRE(reader.setReadOnlyData(buf.data(), serLen) == returnvalue::OK); + buf[11] = 0x00; + REQUIRE(reader.parseDataWithCrcCheck() == PusIF::INVALID_CRC_16); + } + + SECTION("Invalid CRC but no check") { + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + REQUIRE(reader.setReadOnlyData(buf.data(), serLen) == returnvalue::OK); + buf[11] = 0x00; + REQUIRE(reader.parseDataWithoutCrcCheck() == returnvalue::OK); + } + + SECTION("With application data") { + auto& params = creator.getPusParams(); + std::array data{1, 2, 3}; + creator.setRawUserData(data.data(), data.size()); + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + REQUIRE(reader.setReadOnlyData(buf.data(), serLen) == returnvalue::OK); + REQUIRE(reader.parseDataWithCrcCheck() == returnvalue::OK); + const uint8_t* userDataPtr = reader.getUserData(); + REQUIRE(userDataPtr != nullptr); + REQUIRE(reader.getUserDataLen() == 3); + REQUIRE(userDataPtr[0] == 1); + REQUIRE(userDataPtr[1] == 2); + REQUIRE(userDataPtr[2] == 3); + } +} \ No newline at end of file diff --git a/unittests/tmtcpacket/testPusTmCreator.cpp b/unittests/tmtcpacket/testPusTmCreator.cpp new file mode 100644 index 00000000..fc86dcbe --- /dev/null +++ b/unittests/tmtcpacket/testPusTmCreator.cpp @@ -0,0 +1,158 @@ +#include + +#include "fsfw/globalfunctions/CRC.h" +#include "fsfw/globalfunctions/arrayprinter.h" +#include "fsfw/tmtcpacket/pus/tm.h" +#include "mocks/CdsShortTimestamperMock.h" +#include "mocks/SimpleSerializable.h" + +TEST_CASE("PUS TM Creator", "[pus-tm-creator]") { + auto packetId = PacketId(ccsds::PacketType::TC, true, 0xef); + auto spParams = + SpacePacketParams(packetId, PacketSeqCtrl(ccsds::SequenceFlags::UNSEGMENTED, 22), 0x00); + auto timeStamper = CdsShortTimestamperMock(); + auto pusTmParams = PusTmParams(17, 2, &timeStamper); + timeStamper.valueToStamp = {1, 2, 3, 4, 5, 6, 7}; + PusTmCreator creator(spParams, pusTmParams); + std::array buf{}; + uint8_t* dataPtr = buf.data(); + size_t serLen = 0; + + SECTION("State") { + CHECK(creator.isTm()); + CHECK(creator.hasSecHeader()); + CHECK(creator.getApid() == 0xef); + CHECK(creator.getPusVersion() == 2); + CHECK(creator.getScTimeRefStatus() == 0); + CHECK(creator.getService() == 17); + CHECK(creator.getSubService() == 2); + CHECK(creator.getTimestamper() == &timeStamper); + CHECK(creator.getSequenceFlags() == ccsds::SequenceFlags::UNSEGMENTED); + CHECK(creator.getSequenceCount() == 22); + // 6 bytes CCSDS header, 7 bytes secondary header, 7 bytes CDS short timestamp, + // 0 bytes application data, 2 bytes CRC + CHECK(creator.getFullPacketLen() == 22); + // As specified in standard, the data length fields is the total size of the packet without + // the primary header minus 1 + CHECK(creator.getPacketDataLen() == 15); + CHECK(timeStamper.getSizeCallCount == 1); + } + + SECTION("SP Params") { + auto& spParamsRef = creator.getSpParams(); + REQUIRE(spParamsRef.dataLen == 15); + REQUIRE(spParamsRef.packetId.apid == 0xef); + } + + SECTION("Serialization") { + REQUIRE(creator.SerializeIF::serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + REQUIRE(buf[0] == 0x08); + REQUIRE(buf[1] == 0xef); + // Unsegmented is the default + REQUIRE(buf[2] == 0xc0); + REQUIRE(buf[3] == 22); + REQUIRE(buf[4] == 0); + REQUIRE(buf[5] == 15); + REQUIRE(((buf[6] >> 4) & 0b1111) == ecss::PusVersion::PUS_C); + // SC time reference field + REQUIRE((buf[6] & 0b1111) == 0); + // Service and subservice field + REQUIRE(buf[7] == 17); + REQUIRE(buf[8] == 2); + // Message Sequence Count + REQUIRE(((buf[9] << 8) | buf[10]) == 0); + // Destination ID + REQUIRE(((buf[11] << 8) | buf[12]) == 0); + // Custom timestamp + for (size_t i = 1; i < 8; i++) { + REQUIRE(buf[12 + i] == i); + } + REQUIRE(serLen == 22); + REQUIRE(CRC::crc16ccitt(buf.data(), serLen) == 0); + REQUIRE(buf[20] == 0x03); + REQUIRE(buf[21] == 0x79); + REQUIRE(timeStamper.serializeCallCount == 1); + } + + SECTION("Custom Fields") { + creator.setApid(0x3ff); + SECTION("Using Params") { + auto& pusParams = creator.getParams(); + pusParams.secHeader.destId = 0xfff; + pusParams.secHeader.messageTypeCounter = 0x313; + } + SECTION("Using Setters") { + auto& pusParams = creator.getParams(); + creator.setDestId(0xfff); + creator.setMessageTypeCounter(0x313); + } + REQUIRE(creator.getApid() == 0x3ff); + REQUIRE(creator.getDestId() == 0xfff); + REQUIRE(creator.getMessageTypeCounter() == 0x313); + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + // Message Sequence Count + REQUIRE(((buf[9] << 8) | buf[10]) == 0x313); + // Destination ID + REQUIRE(((buf[11] << 8) | buf[12]) == 0xfff); + } + + SECTION("Deserialization fails") { + SerializeIF& deser = creator; + const uint8_t* roDataPtr = nullptr; + REQUIRE(deser.deSerialize(&roDataPtr, &serLen, SerializeIF::Endianness::NETWORK) == + returnvalue::FAILED); + } + + SECTION("Serialize with Raw Data") { + std::array data{1, 2, 3}; + creator.setRawUserData(data.data(), data.size()); + REQUIRE(creator.getFullPacketLen() == 25); + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + REQUIRE(buf[20] == 1); + REQUIRE(buf[21] == 2); + REQUIRE(buf[22] == 3); + } + + SECTION("Serialize with Serializable") { + auto simpleSer = SimpleSerializable(); + creator.setSerializableUserData(simpleSer); + REQUIRE(creator.getFullPacketLen() == 25); + REQUIRE(creator.serialize(&dataPtr, &serLen, buf.size(), SerializeIF::Endianness::NETWORK) == + returnvalue::OK); + REQUIRE(buf[20] == 1); + REQUIRE(buf[21] == 2); + REQUIRE(buf[22] == 3); + } + + SECTION("Empty Ctor") { + PusTmCreator creatorFromEmptyCtor; + // 6 bytes CCSDS header, 7 bytes secondary header, no timestamp (IF is null), + // 0 bytes application data, 2 bytes CRC + REQUIRE(creatorFromEmptyCtor.getFullPacketLen() == 15); + // As specified in standard, the data length fields is the total size of the packet without + // the primary header minus 1 + REQUIRE(creatorFromEmptyCtor.getPacketDataLen() == 8); + creatorFromEmptyCtor.setTimeStamper(timeStamper); + REQUIRE(creatorFromEmptyCtor.getFullPacketLen() == 22); + REQUIRE(creatorFromEmptyCtor.getPacketDataLen() == 15); + } + + SECTION("Invalid Buffer Sizes") { + size_t reqSize = creator.getSerializedSize(); + for (size_t maxSize = 0; maxSize < reqSize; maxSize++) { + dataPtr = buf.data(); + serLen = 0; + REQUIRE(creator.serialize(&dataPtr, &serLen, maxSize, SerializeIF::Endianness::NETWORK) == + SerializeIF::BUFFER_TOO_SHORT); + } + } + + SECTION("No CRC Generation") { + creator.disableCrcCalculation(); + REQUIRE(not creator.crcCalculationEnabled()); + REQUIRE(creator.serializeBe(dataPtr, serLen, buf.size()) == returnvalue::OK); + REQUIRE(serLen == 22); + REQUIRE(buf[20] == 0x00); + REQUIRE(buf[21] == 0x00); + } +} \ No newline at end of file diff --git a/unittests/tmtcpacket/testPusTmReader.cpp b/unittests/tmtcpacket/testPusTmReader.cpp new file mode 100644 index 00000000..1180fd23 --- /dev/null +++ b/unittests/tmtcpacket/testPusTmReader.cpp @@ -0,0 +1,109 @@ +#include + +#include "fsfw/tmtcpacket/pus/tm/PusTmCreator.h" +#include "fsfw/tmtcpacket/pus/tm/PusTmReader.h" +#include "mocks/CdsShortTimestamperMock.h" + +TEST_CASE("PUS TM Reader", "[pus-tm-reader]") { + auto packetId = PacketId(ccsds::PacketType::TC, true, 0xef); + auto spParams = + SpacePacketParams(packetId, PacketSeqCtrl(ccsds::SequenceFlags::UNSEGMENTED, 22), 0x00); + auto timeStamperAndReader = CdsShortTimestamperMock(); + auto pusTmParams = PusTmParams(17, 2, &timeStamperAndReader); + timeStamperAndReader.valueToStamp = {1, 2, 3, 4, 5, 6, 7}; + PusTmCreator creator(spParams, pusTmParams); + PusTmReader reader(&timeStamperAndReader); + std::array buf{}; + uint8_t* dataPtr = buf.data(); + size_t serLen = 0; + + SECTION("Basic") { + PusTmReader* readerPtr = &reader; + bool deleteReader = false; + dataPtr = buf.data(); + serLen = 0; + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + REQUIRE(not(*readerPtr)); + REQUIRE(readerPtr->isNull()); + + SECTION("Setter") { + REQUIRE(readerPtr->setReadOnlyData(buf.data(), serLen) == returnvalue::OK); + } + SECTION("Full Construction") { + readerPtr = new PusTmReader(&timeStamperAndReader, buf.data(), serLen); + deleteReader = true; + } + SECTION("Time Stamper set manually") { + readerPtr = new PusTmReader(buf.data(), serLen); + readerPtr->setTimeReader(&timeStamperAndReader); + deleteReader = true; + } + REQUIRE(not *readerPtr); + REQUIRE(readerPtr->isNull()); + REQUIRE(readerPtr->parseDataWithCrcCheck() == returnvalue::OK); + REQUIRE(not readerPtr->isNull()); + REQUIRE(readerPtr->getService() == 17); + REQUIRE(readerPtr->getSubService() == 2); + REQUIRE(readerPtr->getApid() == 0xef); + REQUIRE(readerPtr->getSequenceFlags() == ccsds::SequenceFlags::UNSEGMENTED); + REQUIRE(readerPtr->getScTimeRefStatus() == 0); + REQUIRE(readerPtr->getDestId() == 0); + REQUIRE(readerPtr->getMessageTypeCounter() == 0); + REQUIRE(readerPtr->getTimeReader() == &timeStamperAndReader); + REQUIRE(readerPtr->getPusVersion() == 2); + REQUIRE(readerPtr->getPacketDataLen() == 15); + REQUIRE(readerPtr->getFullPacketLen() == 22); + REQUIRE(readerPtr->getUserDataLen() == 0); + REQUIRE(readerPtr->getUserData() == nullptr); + REQUIRE(readerPtr->getFullData() == buf.data()); + if (deleteReader) { + delete readerPtr; + } + } + + SECTION("Invalid CRC") { + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + buf[20] = 0; + REQUIRE(reader.setReadOnlyData(buf.data(), serLen) == returnvalue::OK); + REQUIRE(reader.parseDataWithCrcCheck() == PusIF::INVALID_CRC_16); + } + + SECTION("Set Time Reader") { + reader.setTimeReader(nullptr); + REQUIRE(reader.getTimeReader() == nullptr); + } + + SECTION("Invalid CRC ignored") { + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + buf[20] = 0; + REQUIRE(reader.setReadOnlyData(buf.data(), serLen) == returnvalue::OK); + REQUIRE(reader.parseDataWithoutCrcCheck() == returnvalue::OK); + } + + SECTION("Read with source data") { + std::array data{1, 2, 3}; + creator.setRawUserData(data.data(), data.size()); + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + REQUIRE(reader.setReadOnlyData(buf.data(), serLen) == returnvalue::OK); + REQUIRE(reader.parseDataWithCrcCheck() == returnvalue::OK); + REQUIRE(reader.getUserDataLen() == 3); + const uint8_t* roData = reader.getUserData(); + REQUIRE(roData[0] == 1); + REQUIRE(roData[1] == 2); + REQUIRE(roData[2] == 3); + } + + SECTION("Invalid stream lengths") { + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + for (size_t i = 0; i < serLen - 1; i++) { + REQUIRE(reader.setReadOnlyData(buf.data(), i) == SerializeIF::STREAM_TOO_SHORT); + } + } + + SECTION("Reading timestamp fails") { + timeStamperAndReader.nextDeserFails = true; + REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); + REQUIRE(reader.setReadOnlyData(buf.data(), serLen) == returnvalue::OK); + REQUIRE(reader.parseDataWithCrcCheck() == returnvalue::FAILED); + } +} \ No newline at end of file diff --git a/unittests/tmtcpacket/testZcTmWriter.cpp b/unittests/tmtcpacket/testZcTmWriter.cpp new file mode 100644 index 00000000..12e88ea1 --- /dev/null +++ b/unittests/tmtcpacket/testZcTmWriter.cpp @@ -0,0 +1,42 @@ +#include + +#include "fsfw/globalfunctions/CRC.h" +#include "fsfw/tmtcpacket/pus/tm.h" +#include "fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h" +#include "mocks/CdsShortTimestamperMock.h" + +TEST_CASE("TM ZC Helper", "[tm-zc-helper]") { + auto packetId = PacketId(ccsds::PacketType::TC, true, 0xef); + auto spParams = + SpacePacketParams(packetId, PacketSeqCtrl(ccsds::SequenceFlags::UNSEGMENTED, 22), 0x00); + auto timeStamper = CdsShortTimestamperMock(); + auto pusTmParams = PusTmParams(17, 2, &timeStamper); + timeStamper.valueToStamp = {1, 2, 3, 4, 5, 6, 7}; + PusTmCreator creator(spParams, pusTmParams); + std::array buf{}; + uint8_t* dataPtr = buf.data(); + size_t serLen = 0; + + SECTION("No Crash For Uninitialized Object") { + REQUIRE(creator.serializeBe(dataPtr, serLen, buf.size()) == returnvalue::OK); + PusTmZeroCopyWriter writer(timeStamper, dataPtr, serLen); + REQUIRE(writer.getSequenceCount() == 22); + writer.setSequenceCount(23); + // Can't set anything, parse function was not called + REQUIRE(writer.getSequenceCount() == 22); + writer.updateErrorControl(); + } + + SECTION("Basic") { + REQUIRE(creator.serializeBe(dataPtr, serLen, buf.size()) == returnvalue::OK); + PusTmZeroCopyWriter writer(timeStamper, dataPtr, serLen); + REQUIRE(writer.parseDataWithoutCrcCheck() == returnvalue::OK); + REQUIRE(writer.getSequenceCount() == 22); + writer.setSequenceCount(23); + REQUIRE(writer.getSequenceCount() == 23); + // CRC is invalid now + REQUIRE(CRC::crc16ccitt(dataPtr, serLen) != 0); + writer.updateErrorControl(); + REQUIRE(CRC::crc16ccitt(dataPtr, serLen) == 0); + } +} \ No newline at end of file diff --git a/unittests/tmtcservices/CMakeLists.txt b/unittests/tmtcservices/CMakeLists.txt new file mode 100644 index 00000000..1004a5f9 --- /dev/null +++ b/unittests/tmtcservices/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE testStoreHelper.cpp testSendHelper.cpp + testStoreAndSendHelper.cpp testPsb.cpp) diff --git a/unittests/tmtcservices/testPsb.cpp b/unittests/tmtcservices/testPsb.cpp new file mode 100644 index 00000000..93d8aec5 --- /dev/null +++ b/unittests/tmtcservices/testPsb.cpp @@ -0,0 +1,247 @@ +#include + +#include "fsfw/ipc/QueueFactory.h" +#include "fsfw/storagemanager/LocalPool.h" +#include "fsfw/storagemanager/PoolManager.h" +#include "mocks/AcceptsTmMock.h" +#include "mocks/CdsShortTimestamperMock.h" +#include "mocks/InternalErrorReporterMock.h" +#include "mocks/MessageQueueMock.h" +#include "mocks/PusDistributorMock.h" +#include "mocks/PusServiceBaseMock.h" +#include "mocks/PusVerificationReporterMock.h" + +TEST_CASE("Pus Service Base", "[pus-service-base]") { + uint16_t apid = 2; + auto verificationReporter = PusVerificationReporterMock(); + auto msgQueue = MessageQueueMock(1); + auto tmReceiver = AcceptsTmMock(2); + auto psbParams = PsbParams(0, apid, 17); + + LocalPool::LocalPoolConfig cfg = {{5, 32}, {2, 64}}; + LocalPool pool(objects::NO_OBJECT, cfg); + + psbParams.verifReporter = &verificationReporter; + psbParams.reqQueue = &msgQueue; + psbParams.tmReceiver = &tmReceiver; + psbParams.tcPool = &pool; + auto psb = PsbMock(psbParams); + + store_address_t storeId; + TmTcMessage tmtcMsg; + + // Components to create valid PUS packets + auto packetId = PacketId(ccsds::PacketType::TC, true, 0x02); + auto spParams = + SpacePacketParams(packetId, PacketSeqCtrl(ccsds::SequenceFlags::UNSEGMENTED, 0x34), 0x00); + auto pusParams = PusTcParams(17, 1); + PusTcCreator creator(spParams, pusParams); + + REQUIRE(psb.initialize() == returnvalue::OK); + + SECTION("State") { + REQUIRE(psb.getIdentifier() == 17); + REQUIRE(psb.getObjectId() == 0); + REQUIRE(psb.getRequestQueue() == msgQueue.getId()); + auto psbParamsLocal = psb.getParams(); + REQUIRE(psbParamsLocal.errReporter == nullptr); + } + + SECTION("Perform Service") { + REQUIRE(psb.performServiceCallCnt == 0); + REQUIRE(psb.performOperation(0) == returnvalue::OK); + REQUIRE(psb.performServiceCallCnt == 1); + } + + SECTION("Send Request with Successful Handling") { + REQUIRE(psb.performServiceCallCnt == 0); + uint8_t* dataPtr; + REQUIRE(pool.getFreeElement(&storeId, creator.getSerializedSize(), &dataPtr) == + returnvalue::OK); + size_t serLen = 0; + REQUIRE(creator.serializeBe(dataPtr, serLen, creator.getSerializedSize()) == returnvalue::OK); + tmtcMsg.setStorageId(storeId); + msgQueue.addReceivedMessage(tmtcMsg); + REQUIRE(psb.performOperation(0) == returnvalue::OK); + uint8_t subservice = 0; + REQUIRE(psb.getAndPopNextSubservice(subservice)); + REQUIRE(subservice == 1); + REQUIRE(psb.performServiceCallCnt == 1); + // PSB should take care of freeing the pool slot + REQUIRE(not pool.hasDataAtId(storeId)); + REQUIRE(verificationReporter.successCallCount() == 1); + REQUIRE(verificationReporter.failCallCount() == 0); + auto verifParams = verificationReporter.getNextSuccessCallParams(); + REQUIRE(verifParams.tcPacketId == creator.getPacketIdRaw()); + REQUIRE(verifParams.tcPsc == creator.getPacketSeqCtrlRaw()); + } + + SECTION("Send Request with Failed Handling") { + uint8_t* dataPtr; + REQUIRE(pool.getFreeElement(&storeId, creator.getSerializedSize(), &dataPtr) == + returnvalue::OK); + size_t serLen = 0; + REQUIRE(creator.serializeBe(dataPtr, serLen, creator.getSerializedSize()) == returnvalue::OK); + tmtcMsg.setStorageId(storeId); + msgQueue.addReceivedMessage(tmtcMsg); + psb.makeNextHandleReqCallFail(3); + REQUIRE(psb.performOperation(0) == returnvalue::OK); + uint8_t subservice = 0; + REQUIRE(psb.getAndPopNextSubservice(subservice)); + REQUIRE(subservice == 1); + REQUIRE(psb.performServiceCallCnt == 1); + // PSB should take care of freeing the pool slot + REQUIRE(not pool.hasDataAtId(storeId)); + REQUIRE(verificationReporter.successCallCount() == 0); + REQUIRE(verificationReporter.failCallCount() == 1); + auto verifParams = verificationReporter.getNextFailCallParams(); + REQUIRE(verifParams.tcPacketId == creator.getPacketIdRaw()); + REQUIRE(verifParams.tcPsc == creator.getPacketSeqCtrlRaw()); + } + + SECTION("Invalid Packet Sent") { + tmtcMsg.setStorageId(store_address_t::invalid()); + msgQueue.addReceivedMessage(tmtcMsg); + REQUIRE(psb.performOperation(0) == returnvalue::OK); + REQUIRE(verificationReporter.failCallCount() == 1); + auto verifParams = verificationReporter.getNextFailCallParams(); + REQUIRE(verifParams.tcPacketId == 0); + REQUIRE(verifParams.tcPsc == 0); + } + + SECTION("Set Verif Reporter") { + auto verificationReporter2 = PusVerificationReporterMock(); + psb.setVerificationReporter(verificationReporter2); + auto& p = psb.getParams(); + REQUIRE(p.verifReporter == &verificationReporter2); + } + + SECTION("Set Request Queue") { + auto msgQueueMock = MessageQueueMock(2); + psb.setRequestQueue(msgQueueMock); + auto& p = psb.getParams(); + REQUIRE(p.reqQueue == &msgQueueMock); + } + + SECTION("Set TM Receiver") { + auto tmReceiver2 = AcceptsTmMock(3); + psb.setTmReceiver(tmReceiver2); + auto& p = psb.getParams(); + REQUIRE(p.tmReceiver == &tmReceiver2); + } + + SECTION("Set TC Store") { + LocalPool tcStore2(5, cfg); + psb.setTcPool(tcStore2); + auto& p = psb.getParams(); + REQUIRE(p.tcPool == &tcStore2); + } + + SECTION("Set error reporter") { + auto errReporter = InternalErrorReporterMock(); + psb.setErrorReporter(errReporter); + auto& p = psb.getParams(); + REQUIRE(p.errReporter == &errReporter); + } + SECTION("Owner Queue") { + // This will cause the initialize function to create a new owner queue + psbParams.reqQueue = nullptr; + psbParams.objectId = 1; + auto mockWithOwnerQueue = PsbMock(psbParams); + REQUIRE(mockWithOwnerQueue.getRequestQueue() == MessageQueueIF::NO_QUEUE); + REQUIRE(mockWithOwnerQueue.initialize() == returnvalue::OK); + REQUIRE(mockWithOwnerQueue.getRequestQueue() != MessageQueueIF::NO_QUEUE); + } + + SECTION("TM Store Helper Initializer") { + TmStoreHelper storeHelper(0); + psb.initializeTmStoreHelper(storeHelper); + REQUIRE(storeHelper.getApid() == apid); + } + + SECTION("TM Send Helper Initializer") { + TmSendHelper sendHelper; + psb.initializeTmSendHelper(sendHelper); + REQUIRE(sendHelper.getMsgQueue() == &msgQueue); + REQUIRE(sendHelper.getDefaultDestination() == msgQueue.getDefaultDestination()); + } + + SECTION("TM Store And Send Helper Initializer") { + TmStoreHelper storeHelper(0); + TmSendHelper sendHelper; + psb.initializeTmHelpers(sendHelper, storeHelper); + REQUIRE(sendHelper.getMsgQueue() == &msgQueue); + REQUIRE(sendHelper.getDefaultDestination() == msgQueue.getDefaultDestination()); + REQUIRE(storeHelper.getApid() == apid); + } + + SECTION("TM Send Helper Initializer With Error Reporter") { + TmSendHelper sendHelper; + auto errReporter = InternalErrorReporterMock(); + psb.setErrorReporter(errReporter); + psb.initializeTmSendHelper(sendHelper); + REQUIRE(sendHelper.getMsgQueue() == &msgQueue); + REQUIRE(sendHelper.getDefaultDestination() == msgQueue.getDefaultDestination()); + REQUIRE(sendHelper.getInternalErrorReporter() == &errReporter); + } + + SECTION("Auto Initialize PUS Distributor") { + psbParams.objectId = 1; + object_id_t distributorId = 3; + auto psb2 = PsbMock(psbParams); + auto pusDistrib = PusDistributorMock(distributorId); + PsbMock::setStaticPusDistributor(distributorId); + REQUIRE(PsbMock::getStaticPusDistributor() == distributorId); + REQUIRE(psb2.initialize() == returnvalue::OK); + REQUIRE(pusDistrib.registerCallCount == 1); + REQUIRE(pusDistrib.registeredServies.front() == &psb2); + } + + SECTION("Auto Initialize Packet Destination") { + psbParams.tmReceiver = nullptr; + psbParams.objectId = 1; + object_id_t destId = 3; + auto psb2 = PsbMock(psbParams); + auto packetDest = AcceptsTmMock(destId, 2); + PsbMock::setStaticTmDest(destId); + REQUIRE(PsbMock::getStaticTmDest() == destId); + REQUIRE(psb2.initialize() == returnvalue::OK); + auto& p = psb2.getParams(); + REQUIRE(p.tmReceiver == &packetDest); + } + + SECTION("Auto Initialize Verification Reporter") { + psbParams.verifReporter = nullptr; + psbParams.objectId = 1; + object_id_t reporterId = objects::VERIFICATION_REPORTER; + PusVerificationReporterMock otherReporter(reporterId); + auto psb2 = PsbMock(psbParams); + REQUIRE(psb2.initialize() == returnvalue::OK); + auto& p = psb2.getParams(); + REQUIRE(p.verifReporter == &otherReporter); + } + + SECTION("Auto Initialize TC Pool") { + PoolManager tcStoreGlobal(objects::TC_STORE, cfg); + psbParams.tcPool = nullptr; + psbParams.objectId = 1; + auto psb2 = PsbMock(psbParams); + REQUIRE(psb2.initialize() == returnvalue::OK); + auto& p = psb2.getParams(); + REQUIRE(p.tcPool == &tcStoreGlobal); + } + + SECTION("Invalid Verification Reporter") { + psbParams.verifReporter = nullptr; + psbParams.objectId = 1; + auto psb2 = PsbMock(psbParams); + REQUIRE(psb2.initialize() == ObjectManagerIF::CHILD_INIT_FAILED); + } + + SECTION("Invalid TC Store") { + psbParams.tcPool = nullptr; + psbParams.objectId = 1; + auto psb2 = PsbMock(psbParams); + REQUIRE(psb2.initialize() == ObjectManagerIF::CHILD_INIT_FAILED); + } +} diff --git a/unittests/tmtcservices/testSendHelper.cpp b/unittests/tmtcservices/testSendHelper.cpp new file mode 100644 index 00000000..43816835 --- /dev/null +++ b/unittests/tmtcservices/testSendHelper.cpp @@ -0,0 +1,106 @@ +#include + +#include "fsfw/storagemanager/LocalPool.h" +#include "fsfw/tmtcservices/TmSendHelper.h" +#include "fsfw/tmtcservices/TmStoreHelper.h" +#include "mocks/CdsShortTimestamperMock.h" +#include "mocks/InternalErrorReporterMock.h" +#include "mocks/MessageQueueMock.h" + +TEST_CASE("TM Send Helper", "[tm-send-helper]") { + MessageQueueId_t destId = 2; + auto errReporter = InternalErrorReporterMock(); + auto msgQueue = MessageQueueMock(1); + msgQueue.setDefaultDestination(destId); + TmSendHelper sendHelper(msgQueue, errReporter, destId); + auto timeStamper = CdsShortTimestamperMock(); + LocalPool::LocalPoolConfig cfg = {{5, 32}, {2, 64}}; + LocalPool pool(objects::NO_OBJECT, cfg); + auto storeHelper = TmStoreHelper(2, pool, timeStamper); + + SECTION("State and Setters") { + REQUIRE(sendHelper.getInternalErrorReporter() == &errReporter); + REQUIRE(sendHelper.getDefaultDestination() == destId); + REQUIRE(sendHelper.getMsgQueue() == &msgQueue); + } + + SECTION("Setters") { + REQUIRE(not sendHelper.areFaultsIgnored()); + sendHelper.ignoreFaults(); + REQUIRE(sendHelper.areFaultsIgnored()); + sendHelper.dontIgnoreFaults(); + REQUIRE(not sendHelper.areFaultsIgnored()); + REQUIRE(sendHelper.getDefaultDestination() == destId); + sendHelper.setDefaultDestination(destId + 1); + REQUIRE(sendHelper.getDefaultDestination() == destId + 1); + auto errReporter2 = InternalErrorReporterMock(); + sendHelper.setInternalErrorReporter(errReporter2); + REQUIRE(sendHelper.getInternalErrorReporter() == &errReporter2); + } + + SECTION("Default CTOR") { + TmSendHelper emptyHelper; + REQUIRE(emptyHelper.getInternalErrorReporter() == nullptr); + REQUIRE(emptyHelper.getDefaultDestination() == MessageQueueIF::NO_QUEUE); + store_address_t dummy; + // basic robustness + REQUIRE(emptyHelper.sendPacket(dummy) == returnvalue::FAILED); + } + + SECTION("One Arg CTOR") { + TmSendHelper helper(errReporter); + REQUIRE(helper.getInternalErrorReporter() == &errReporter); + REQUIRE(helper.getDefaultDestination() == MessageQueueIF::NO_QUEUE); + REQUIRE(helper.getMsgQueue() == nullptr); + } + + SECTION("Two Arg CTOR") { + TmSendHelper helper(msgQueue, errReporter); + REQUIRE(helper.getInternalErrorReporter() == &errReporter); + REQUIRE(helper.getDefaultDestination() == 2); + REQUIRE(helper.getMsgQueue() == &msgQueue); + } + SECTION("Send") { + REQUIRE(storeHelper.preparePacket(17, 2, 0) == returnvalue::OK); + store_address_t storeId; + SECTION("Separate Helpers") { + REQUIRE(storeHelper.addPacketToStore() == returnvalue::OK); + storeId = storeHelper.getCurrentAddr(); + REQUIRE(sendHelper.sendPacket(storeId) == returnvalue::OK); + } + REQUIRE(msgQueue.wasMessageSent()); + REQUIRE(msgQueue.numberOfSentMessagesToDefault() == 1); + TmTcMessage msg; + REQUIRE(msgQueue.getNextSentMessage(msg) == returnvalue::OK); + REQUIRE(msg.getStorageId() == storeId); + REQUIRE(pool.hasDataAtId(msg.getStorageId())); + } + + SECTION("Send to Non-Default") { + storeHelper.preparePacket(17, 2, 0); + REQUIRE(storeHelper.addPacketToStore() == returnvalue::OK); + store_address_t storeId = storeHelper.getCurrentAddr(); + REQUIRE(sendHelper.sendPacket(destId + 1, storeId) == returnvalue::OK); + REQUIRE(msgQueue.wasMessageSent()); + REQUIRE(msgQueue.numberOfSentMessagesToDest(destId + 1) == 1); + } + + SECTION("Sending fails, errors not ignored") { + msgQueue.makeNextSendFail(returnvalue::FAILED); + storeHelper.preparePacket(17, 2, 0); + REQUIRE(storeHelper.addPacketToStore() == returnvalue::OK); + store_address_t storeId = storeHelper.getCurrentAddr(); + REQUIRE(sendHelper.sendPacket(destId + 1, storeId) == returnvalue::FAILED); + REQUIRE(errReporter.lostTmCallCnt == 1); + } + + SECTION("Sending fails, errors ignored") { + msgQueue.makeNextSendFail(returnvalue::FAILED); + storeHelper.preparePacket(17, 2, 0); + sendHelper.ignoreFaults(); + REQUIRE(storeHelper.addPacketToStore() == returnvalue::OK); + store_address_t storeId = storeHelper.getCurrentAddr(); + REQUIRE(sendHelper.sendPacket(destId + 1, storeId) == returnvalue::FAILED); + REQUIRE(errReporter.lostTmCallCnt == 0); + } +} \ No newline at end of file diff --git a/unittests/tmtcservices/testStoreAndSendHelper.cpp b/unittests/tmtcservices/testStoreAndSendHelper.cpp new file mode 100644 index 00000000..46418dfe --- /dev/null +++ b/unittests/tmtcservices/testStoreAndSendHelper.cpp @@ -0,0 +1,90 @@ +#include + +#include "fsfw/storagemanager/LocalPool.h" +#include "fsfw/tmtcservices/TmSendHelper.h" +#include "fsfw/tmtcservices/TmStoreAndSendHelper.h" +#include "fsfw/tmtcservices/TmStoreHelper.h" +#include "mocks/CdsShortTimestamperMock.h" +#include "mocks/InternalErrorReporterMock.h" +#include "mocks/MessageQueueMock.h" +#include "mocks/SimpleSerializable.h" + +TEST_CASE("TM Store And Send Helper", "[tm-store-send-helper]") { + auto timeStamper = CdsShortTimestamperMock(); + LocalPool::LocalPoolConfig cfg = {{5, 32}, {2, 64}}; + LocalPool pool(objects::NO_OBJECT, cfg); + auto storeHelper = TmStoreHelper(2, pool, timeStamper); + + MessageQueueId_t destId = 1; + auto errReporter = InternalErrorReporterMock(); + auto msgQueue = MessageQueueMock(2); + msgQueue.setDefaultDestination(destId); + TmSendHelper sendHelper(msgQueue, errReporter, destId); + TmStoreAndSendWrapper tmHelper(17, storeHelper, sendHelper); + + SECTION("State") { + CHECK(tmHelper.sendCounter == 0); + CHECK(tmHelper.defaultService == 17); + CHECK(tmHelper.delOnFailure); + CHECK(tmHelper.incrementSendCounter); + CHECK(&tmHelper.sendHelper == &sendHelper); + CHECK(&tmHelper.storeHelper == &storeHelper); + } + + SECTION("Storage Fails") { + // Too large to fit in store + std::array data{}; + REQUIRE(storeHelper.setSourceDataRaw(data.data(), data.size()) == returnvalue::OK); + REQUIRE(tmHelper.storeAndSendTmPacket() == StorageManagerIF::DATA_TOO_LARGE); + } + + SECTION("Base Test") { + tmHelper.prepareTmPacket(2); + auto& creator = storeHelper.getCreatorRef(); + REQUIRE(creator.getSubService() == 2); + REQUIRE(creator.getService() == 17); + auto& params = creator.getParams(); + REQUIRE(params.sourceData == nullptr); + REQUIRE(tmHelper.sendCounter == 0); + REQUIRE(tmHelper.storeAndSendTmPacket() == returnvalue::OK); + REQUIRE(tmHelper.sendCounter == 1); + auto storeId = storeHelper.getCurrentAddr(); + REQUIRE(msgQueue.wasMessageSent()); + REQUIRE(msgQueue.numberOfSentMessagesToDefault() == 1); + TmTcMessage msg; + REQUIRE(msgQueue.getNextSentMessage(msg) == returnvalue::OK); + REQUIRE(msg.getStorageId() == storeId); + REQUIRE(pool.hasDataAtId(msg.getStorageId())); + storeHelper.deletePacket(); + } + + SECTION("Raw Data Helper") { + std::array data = {1, 2, 3}; + REQUIRE(tmHelper.prepareTmPacket(2, data.data(), data.size()) == returnvalue::OK); + auto& creator = storeHelper.getCreatorRef(); + auto& params = creator.getParams(); + REQUIRE(params.sourceData != nullptr); + REQUIRE(params.sourceData->getSerializedSize() == data.size()); + REQUIRE(params.adapter.getConstBuffer() == data.data()); + } + + SECTION("Serializable Helper") { + auto simpleSer = SimpleSerializable(); + REQUIRE(tmHelper.prepareTmPacket(2, simpleSer) == returnvalue::OK); + auto& creator = storeHelper.getCreatorRef(); + auto& params = creator.getParams(); + REQUIRE(params.sourceData == &simpleSer); + } + + SECTION("Object ID prefix Helper") { + uint32_t objectId = 0x01020304; + std::array data = {1, 2, 3}; + telemetry::DataWithObjectIdPrefix dataWithObjId(objectId, data.data(), data.size()); + REQUIRE(tmHelper.prepareTmPacket(2, dataWithObjId) == returnvalue::OK); + auto& creator = storeHelper.getCreatorRef(); + auto& params = creator.getParams(); + REQUIRE(params.sourceData == &dataWithObjId); + } + + // TODO: Error handling +} diff --git a/unittests/tmtcservices/testStoreHelper.cpp b/unittests/tmtcservices/testStoreHelper.cpp new file mode 100644 index 00000000..dd73305d --- /dev/null +++ b/unittests/tmtcservices/testStoreHelper.cpp @@ -0,0 +1,110 @@ +#include + +#include "fsfw/storagemanager/LocalPool.h" +#include "fsfw/tmtcservices/TmStoreHelper.h" +#include "fsfw/tmtcservices/tmHelpers.h" +#include "mocks/CdsShortTimestamperMock.h" +#include "mocks/SimpleSerializable.h" + +TEST_CASE("TM Store Helper", "[tm-store-helper]") { + auto timeStamper = CdsShortTimestamperMock(); + LocalPool::LocalPoolConfig cfg = {{5, 32}, {2, 64}}; + LocalPool pool(objects::NO_OBJECT, cfg); + auto storeHelper = TmStoreHelper(2, pool, timeStamper); + + SECTION("State") { + REQUIRE(storeHelper.getCurrentAddr() == store_address_t::invalid()); + REQUIRE(storeHelper.getTimeStamper() == &timeStamper); + REQUIRE(storeHelper.getTmStore() == &pool); + REQUIRE(storeHelper.preparePacket(17, 1, 1) == returnvalue::OK); + auto& creator = storeHelper.getCreatorRef(); + REQUIRE(creator.getApid() == 2); + REQUIRE(creator.getService() == 17); + REQUIRE(creator.getSubService() == 1); + REQUIRE(creator.getSequenceCount() == 0); + REQUIRE(creator.getMessageTypeCounter() == 1); + } + + SECTION("Timestamper Setter") { + auto timeStamper2 = CdsShortTimestamperMock(); + storeHelper.setTimeStamper(timeStamper2); + REQUIRE(storeHelper.getTimeStamper() == &timeStamper2); + } + + SECTION("Pool Setter") { + LocalPool::LocalPoolConfig cfg2 = {{10, 32}, {5, 64}}; + LocalPool pool2(objects::NO_OBJECT, cfg); + storeHelper.setTmStore(pool2); + REQUIRE(storeHelper.getTmStore() == &pool2); + } + + SECTION("APID Setter") { + storeHelper.setApid(3); + auto& creator = storeHelper.getCreatorRef(); + REQUIRE(creator.getApid() == 3); + } + + SECTION("Basic") { + REQUIRE(storeHelper.preparePacket(17, 1, 1) == returnvalue::OK); + REQUIRE(storeHelper.addPacketToStore() == returnvalue::OK); + REQUIRE(storeHelper.getCurrentAddr() != store_address_t::invalid()); + auto accessor = pool.getData(storeHelper.getCurrentAddr()); + REQUIRE(accessor.first == returnvalue::OK); + // Not going to verify individual fields, the creator was unittested separately + REQUIRE(accessor.second.size() == 22); + } + + SECTION("Deletion") { + REQUIRE(storeHelper.preparePacket(17, 1, 1) == returnvalue::OK); + REQUIRE(storeHelper.addPacketToStore() == returnvalue::OK); + REQUIRE(storeHelper.getCurrentAddr() != store_address_t::invalid()); + { + auto accessor = pool.getData(storeHelper.getCurrentAddr()); + REQUIRE(accessor.first == returnvalue::OK); + REQUIRE(accessor.second.size() == 22); + accessor.second.release(); + } + REQUIRE(storeHelper.deletePacket() == returnvalue::OK); + REQUIRE(storeHelper.getCurrentAddr() == store_address_t::invalid()); + auto accessor = pool.getData(storeHelper.getCurrentAddr()); + REQUIRE(accessor.first != returnvalue::OK); + } + + SECTION("With App Data Raw") { + REQUIRE(storeHelper.preparePacket(17, 1, 1) == returnvalue::OK); + std::array data = {1, 2, 3}; + REQUIRE(storeHelper.setSourceDataRaw(data.data(), data.size()) == returnvalue::OK); + REQUIRE(storeHelper.addPacketToStore() == returnvalue::OK); + REQUIRE(storeHelper.getCurrentAddr() != store_address_t::invalid()); + auto accessor = pool.getData(storeHelper.getCurrentAddr()); + REQUIRE(accessor.first == returnvalue::OK); + // Not going to verify individual fields, the creator was unittested separately + REQUIRE(accessor.second.size() == 25); + } + + SECTION("With App Data Serializable") { + REQUIRE(storeHelper.preparePacket(17, 1, 1) == returnvalue::OK); + auto serializable = SimpleSerializable(); + REQUIRE(storeHelper.setSourceDataSerializable(serializable) == returnvalue::OK); + REQUIRE(storeHelper.addPacketToStore() == returnvalue::OK); + REQUIRE(storeHelper.getCurrentAddr() != store_address_t::invalid()); + auto accessor = pool.getData(storeHelper.getCurrentAddr()); + REQUIRE(accessor.first == returnvalue::OK); + // Not going to verify individual fields, the creator was unittested separately + REQUIRE(accessor.second.size() == 25); + } + + SECTION("APID Only CTOR") { + auto storeHelperApidOnly = TmStoreHelper(2); + REQUIRE(storeHelperApidOnly.getApid() == 2); + REQUIRE(storeHelperApidOnly.getTmStore() == nullptr); + REQUIRE(storeHelperApidOnly.getTimeStamper() == nullptr); + } + + SECTION("APID and TM Store Only CTOR") { + auto storeHelperApidOnly = TmStoreHelper(2, pool); + REQUIRE(storeHelperApidOnly.getApid() == 2); + REQUIRE(storeHelperApidOnly.getTmStore() == &pool); + REQUIRE(storeHelperApidOnly.getTimeStamper() == nullptr); + } +} \ No newline at end of file diff --git a/unittests/util/CMakeLists.txt b/unittests/util/CMakeLists.txt new file mode 100644 index 00000000..fb660d54 --- /dev/null +++ b/unittests/util/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE testUnsignedByteField.cpp) diff --git a/unittests/util/testUnsignedByteField.cpp b/unittests/util/testUnsignedByteField.cpp new file mode 100644 index 00000000..df1ff483 --- /dev/null +++ b/unittests/util/testUnsignedByteField.cpp @@ -0,0 +1,73 @@ + +#include +#include + +#include "fsfw/util/UnsignedByteField.h" + +TEST_CASE("Unsigned Byte Field", "[unsigned-byte-field]") { + auto testByteField = UnsignedByteField(10); + auto u32ByteField = U32ByteField(10); + auto u16ByteField = U16ByteField(5); + auto u8ByteField = U8ByteField(2); + std::array buf{}; + size_t serLen = 0; + SECTION("State") { + CHECK(testByteField.getValue() == 10); + CHECK(testByteField.getSerializedSize() == 4); + CHECK(u32ByteField.getValue() == 10); + CHECK(u32ByteField.getSerializedSize() == 4); + CHECK(u16ByteField.getValue() == 5); + CHECK(u8ByteField.getValue() == 2); + CHECK(u8ByteField.getSerializedSize() == 1); + } + + SECTION("Setter") { + u32ByteField.setValue(20); + REQUIRE(u32ByteField.getValue() == 20); + } + + SECTION("Serialize U32") { + CHECK(testByteField.serializeBe(buf.data(), serLen, buf.size()) == returnvalue::OK); + CHECK(serLen == 4); + CHECK(buf[0] == 0); + CHECK(buf[3] == 10); + } + + SECTION("Serialize U32 Concrete") { + CHECK(u32ByteField.serializeBe(buf.data(), serLen, buf.size()) == returnvalue::OK); + CHECK(serLen == 4); + CHECK(buf[0] == 0); + CHECK(buf[3] == 10); + } + + SECTION("Serialize U16 Concrete") { + CHECK(u16ByteField.serializeBe(buf.data(), serLen, buf.size()) == returnvalue::OK); + CHECK(serLen == 2); + CHECK(buf[0] == 0); + CHECK(buf[1] == 5); + } + + SECTION("Serialize U8 Concrete") { + CHECK(u8ByteField.serializeBe(buf.data(), serLen, buf.size()) == returnvalue::OK); + CHECK(serLen == 1); + CHECK(buf[0] == 2); + } + + SECTION("Deserialize") { + buf[0] = 0x50; + buf[1] = 0x40; + buf[2] = 0x30; + buf[3] = 0x20; + size_t deserLen = 0; + CHECK(testByteField.deSerializeBe(buf.data(), deserLen, buf.size()) == returnvalue::OK); + CHECK(testByteField.getValue() == 0x50403020); + } + + SECTION("Deserialize U16") { + buf[0] = 0x50; + buf[1] = 0x40; + size_t deserLen = 0; + CHECK(u16ByteField.deSerializeBe(buf.data(), deserLen, buf.size()) == returnvalue::OK); + CHECK(u16ByteField.getValue() == 0x5040); + } +} \ No newline at end of file