Compare commits

..

33 Commits

Author SHA1 Message Date
efc2773f84 docker update for windows 2023-02-06 16:29:53 +01:00
87bb29a66a compiler parameter tuning 2023-02-06 13:10:50 +01:00
45963b2064 tuning win build 2023-01-27 17:26:03 +01:00
bc312243df clang -Weverything -Wno-gnu-anonymous-struct 2023-01-27 00:50:10 +01:00
9589d702dd windows unittests succeed 2023-01-26 18:14:35 +01:00
c66fab90f9 filesystem stuff works on linux/host 2023-01-26 17:05:25 +01:00
3e8446ba8b windows building again 2023-01-26 15:30:23 +01:00
e37af4fe70 format 2023-01-26 13:40:44 +01:00
941bf61f28 constant number of assertions in unittests 2023-01-26 13:26:11 +01:00
70fd9ff3e5 fixed impact of windows fixes on other builds 2023-01-26 12:33:39 +01:00
81c5b2ec95 Merge branch 'mohr/rtems' into windows 2023-01-26 11:55:16 +01:00
7426e10f82 clocks suck a little less 2023-01-26 11:33:40 +01:00
uli
123c81777a clocks suck 2023-01-26 00:01:40 +01:00
dcc28622a5 windows compiles, some unittests give exceptions 2023-01-25 23:54:46 +01:00
6d85fa155e cleaning up unittest build 2023-01-20 16:05:04 +01:00
e6af6200ae updating CI 2023-01-19 17:32:23 +01:00
5ca3e83934 working on rtems CI build 2023-01-19 16:46:43 +01:00
6adabb059a fixing rtems cmake config 2023-01-19 16:27:10 +01:00
5d0a5cd201 exiting qemu nonzero when tests fail 2023-01-19 14:47:40 +01:00
adb8483bb0 unittests for rtems working 2023-01-19 14:24:33 +01:00
fdfdce2fb0 compiling, crashing when run 2023-01-18 00:25:25 +01:00
90efb132d0 fixing rebase error 2023-01-16 12:41:23 +01:00
fe9804d922 format 2023-01-16 12:35:14 +01:00
a0eae66c35 checking if this helps docker build 2023-01-16 12:32:16 +01:00
e131480d5f two errors found by valgrind 2023-01-16 12:32:15 +01:00
90bafbb6de typos in Jenkinsfile 2023-01-16 12:31:54 +01:00
47d85fb61c finished freertos unittests, valgrind not happy yet 2023-01-16 12:31:53 +01:00
39dad5f45b unittests running but failing 2023-01-16 12:31:53 +01:00
a993c4e0d4 adding linux ci and fixing problems 2023-01-16 12:31:53 +01:00
fe9cc20d00 make get const 2023-01-16 12:31:53 +01:00
552a12a6ad updates for source sequence counter 2023-01-16 12:31:47 +01:00
13639feec6 FreeRTOS unittests building (but not running) 2023-01-16 12:30:36 +01:00
654de0f586 WIP 2023-01-16 12:30:36 +01:00
129 changed files with 1214 additions and 1399 deletions
.gitmodulesCHANGELOG.mdCMakeLists.txt
automation
scripts
src
fsfw
cfdp
container
datapoollocal
devicehandlers
events
globalfunctions
health
housekeeping
internalerror
modes
monitoring
osal
parameters
power
pus
serialize
storagemanager
subsystem
tasks
thermal
timemanager
tmtcpacket
tmtcservices
fsfw_hal
fsfw_tests
internal
unittests

3
.gitmodules vendored

@ -0,0 +1,3 @@
[submodule "automation/msvc-wine"]
path = automation/msvc-wine
url = https://github.com/mstorsjo/msvc-wine

@ -8,47 +8,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased]
## Fixes
- PUS Health Service: Size check for set health command.
- PUS Health Service: Perform operation completion for announce health command.
## Changed
- Assert that `FixedArrayList` is larger than 0 at compile time.
# [v6.0.0] 2023-02-10
# [v6.0.0]
## 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
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710/files
- 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
@ -58,82 +25,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `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.
to 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
@ -163,41 +70,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `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
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
interface itself so it can be re-used more easily. Also add new
abstract function `bool hasDataAtId(store_address_t storeId) const`.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
- 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
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
interface itself so it can be re-used more easily. Also add new
abstract function `bool hasDataAtId(store_address_t storeId) const`.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
## CFDP
@ -217,7 +101,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
implementation without an extra component
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682
# [v5.0.0] 2022-07-25
# [v5.0.0] 25.07.2022
## Changes

@ -13,7 +13,7 @@ list(APPEND CMAKE_MODULE_PATH
# Version file handling #
# ##############################################################################
set(FSFW_VERSION_IF_GIT_FAILS 6)
set(FSFW_VERSION_IF_GIT_FAILS 5)
set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
set(FSFW_REVISION_IF_GIT_FAILS 0)
@ -64,6 +64,12 @@ elseif(${CMAKE_CXX_STANDARD} LESS 17)
"${MSG_PREFIX} Compiling the FSFW requires a minimum of C++17 support")
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# Manually tweak MSVC to emit (about) the same warnings as clang and gcc on linux
add_compile_options("/permissive-" /wd4267 /wd4244 /wd4244 /wd4305 /wd4805 /wd4267 /wd4646 /wd4065 /Dand=&& /Dor=|| /Dnot=!)
add_compile_definitions(NOMINMAX)
endif()
set(FSFW_SOURCES_DIR "${CMAKE_SOURCE_DIR}/src/fsfw")
set(FSFW_ETL_LIB_NAME etl)
@ -158,7 +164,7 @@ if(FSFW_BUILD_TESTS)
if(NOT Catch2_FOUND)
message(
STATUS
"${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent."
"${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent"
)
include(FetchContent)
@ -174,6 +180,27 @@ if(FSFW_BUILD_TESTS)
configure_file(unittests/testcfg/FSFWConfig.h.in FSFWConfig.h)
configure_file(unittests/testcfg/TestsConfig.h.in tests/TestsConfig.h)
if(FSFW_OSAL MATCHES "freertos")
message(STATUS "${MSG_PREFIX} Downloading FreeRTOS with FetchContent")
include(FetchContent)
set(FreeRTOS_PORT posix)
FetchContent_Declare(
FreeRTOS
GIT_REPOSITORY https://egit.irs.uni-stuttgart.de/fsfw/FreeRTOS-LTS
GIT_TAG develop
GIT_SUBMODULES FreeRTOS/FreeRTOS-Kernel)
FetchContent_MakeAvailable(FreeRTOS)
set(LIB_OS_NAME FreeRTOS)
target_include_directories(FreeRTOS PUBLIC unittests/testcfg/freertos)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(FreeRTOS PRIVATE ${CMAKE_THREAD_LIBS_INIT})
endif()
project(${FSFW_TEST_TGT} CXX C)
add_executable(${FSFW_TEST_TGT})
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
@ -201,8 +228,8 @@ find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
message(
STATUS
"${MSG_PREFIX} ETL installation not found. Downloading ETL with FetchContent."
)
"${MSG_PREFIX} No ETL installation was found with find_package. Installing and providing "
"etl with FindPackage")
include(FetchContent)
FetchContent_Declare(
@ -226,6 +253,7 @@ if(FSFW_FETCH_CONTENT_TARGETS)
# GitHub issue: https://github.com/catchorg/Catch2/issues/2417
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
endif()
endif()
set(FSFW_CORE_INC_PATH "inc")
@ -360,6 +388,9 @@ if(FSFW_BUILD_TESTS)
endif()
target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2
${LIB_FSFW_NAME})
if(FSFW_OSAL MATCHES "freertos")
target_link_libraries(${FSFW_TEST_TGT} PRIVATE FreeRTOS)
endif()
endif()
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. If
@ -447,8 +478,8 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(COMPILER_FLAGS "/permissive-")
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(FSFW_WARNING_FLAGS -Wall -Wno-gnu-anonymous-struct)
endif()
# Required include paths to compile the FSFW

@ -5,7 +5,7 @@ RUN apt-get --yes upgrade
#tzdata is a dependency, won't install otherwise
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping python3 pip doxygen graphviz rsync
RUN apt-get --yes install ca-certificates clang cmake doxygen g++ gcc git graphviz iputils-ping lcov make msitools nano ninja-build pip python3 python3-simplejson python3-six qemu-system-arm rsync valgrind wget winbind wine64-development
RUN python3 -m pip install sphinx breathe
@ -21,8 +21,27 @@ RUN git clone https://github.com/ETLCPP/etl.git && \
cmake -B build . && \
cmake --install build/
# install our own rtems build
RUN wget -qO- https://buggy.irs.uni-stuttgart.de/rtems_releases/rtems6-12.2.1.tar.bz2 | tar -xj -C /opt/
ENV PATH="$PATH:/opt/rtems/6/bin"
# install msvc using https://github.com/mstorsjo/msvc-wine
# see msvc-wine/LICENSE.txt
COPY msvc-wine/lowercase msvc-wine/fixinclude msvc-wine/install.sh msvc-wine/vsdownload.py ./
COPY msvc-wine/wrappers/* ./wrappers/
RUN PYTHONUNBUFFERED=1 ./vsdownload.py --accept-license --dest /opt/msvc && \
./install.sh /opt/msvc && \
rm lowercase fixinclude install.sh vsdownload.py && \
rm -rf wrappers
COPY msvc-wine/msvcenv-native.sh /opt/msvc
RUN wine64 wineboot --init && \
while pgrep wineserver > /dev/null; do sleep 1; done
#ssh needs a valid user to work
RUN adduser --uid 114 jenkins
RUN adduser -q --uid 114 jenkins
#add documentation server to known hosts
RUN echo "|1|/LzCV4BuTmTb2wKnD146l9fTKgQ=|NJJtVjvWbtRt8OYqFgcYRnMQyVw= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts

105
automation/Jenkinsfile vendored

@ -2,86 +2,61 @@ pipeline {
environment {
BUILDDIR_HOST = 'cmake-build-tests-host'
BUILDDIR_LINUX = 'cmake-build-tests-linux'
BUILDDIR_FREERTOS = 'cmake-build-tests-freertos'
BUILDDIR_RTEMS = 'cmake-build-tests-rtems'
DOCDDIR = 'cmake-build-documentation'
}
agent {
docker {
image 'fsfw-ci:d6'
image 'fsfw-ci:d7'
args '--network host --sysctl fs.mqueue.msg_max=100'
}
}
stages {
stage('Host') {
stages{
stage('Clean') {
steps {
sh 'rm -rf $BUILDDIR_HOST'
}
}
stage('Configure') {
steps {
dir(BUILDDIR_HOST) {
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
}
}
}
stage('Build') {
steps {
dir(BUILDDIR_HOST) {
sh 'cmake --build . -j4'
}
}
}
stage('Unittests') {
steps {
dir(BUILDDIR_HOST) {
sh 'cmake --build . -- fsfw-tests_coverage -j4'
}
}
}
stage('Valgrind') {
steps {
dir(BUILDDIR_HOST) {
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
}
}
steps {
sh 'rm -rf $BUILDDIR_HOST'
dir(BUILDDIR_HOST) {
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
sh 'cmake --build . -j4'
sh 'cmake --build . -- fsfw-tests_coverage -j4'
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
}
}
}
stage('Linux') {
stages{
stage('Clean') {
steps {
sh 'rm -rf $BUILDDIR_LINUX'
}
steps {
sh 'rm -rf $BUILDDIR_LINUX'
dir(BUILDDIR_LINUX) {
sh 'cmake -DFSFW_OSAL=linux -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
sh 'cmake --build . -j4'
sh 'cmake --build . -- fsfw-tests_coverage -j4'
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
}
stage('Configure') {
steps {
dir(BUILDDIR_LINUX) {
sh 'cmake -DFSFW_OSAL=linux -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
}
}
}
}
stage('FreeRTOS') {
steps {
sh 'rm -rf $BUILDDIR_FREERTOS'
dir(BUILDDIR_FREERTOS) {
sh 'cmake -DFSFW_OSAL=freertos -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
sh 'cmake --build . -j4'
sh 'cmake --build . -- fsfw-tests_coverage -j4'
//sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
}
stage('Build') {
steps {
dir(BUILDDIR_LINUX) {
sh 'cmake --build . -j4'
}
}
}
stage('Unittests') {
steps {
dir(BUILDDIR_LINUX) {
sh 'cmake --build . -- fsfw-tests_coverage -j4'
}
}
}
stage('Valgrind') {
steps {
dir(BUILDDIR_LINUX) {
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
}
}
}
}
stage('rtems') {
steps {
sh 'rm -rf $BUILDDIR_RTEMS'
dir(BUILDDIR_RTEMS) {
sh 'cmake -DFSFW_OSAL=rtems -DFSFW_BUILD_TESTS=ON -DFSFW_TESTS_GEN_COV=OFF -DFSFW_CICD_BUILD=ON -DCMAKE_TOOLCHAIN_FILE=../unittests/testcfg/rtems/cmake/aarch64-rtems6-toolchain.cmake ..'
sh 'cmake --build . -j4'
sh 'qemu-system-aarch64 -no-reboot -nographic -serial mon:stdio -semihosting -machine virt,gic-version=3 -cpu cortex-a72 -m 4000 -kernel fsfw-tests'
}
}
}

1
automation/msvc-wine Submodule

Submodule automation/msvc-wine added at 2d2d7db0b5

@ -1,110 +0,0 @@
#! /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()

@ -21,7 +21,7 @@ struct FileSize : public SerializeIF {
this->largeFile = isLarge;
return serialize(buffer, size, maxSize, streamEndianness);
}
using SerializeIF::serialize;
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override {
if (not largeFile) {

@ -3,7 +3,7 @@
#include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/serviceinterface.h"
cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, size_t value) : VarLenField() {
cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, uint64_t value) : VarLenField() {
ReturnValue_t result = this->setValue(width, value);
if (result != returnvalue::OK) {
#if FSFW_DISABLE_PRINTOUT == 0
@ -20,7 +20,7 @@ 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, uint64_t value_) {
switch (widthInBytes) {
case (cfdp::WidthInBytes::ONE_BYTE): {
if (value_ > UINT8_MAX) {
@ -51,7 +51,7 @@ ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_
return returnvalue::OK;
}
size_t cfdp::VarLenField::getValue() const {
uint64_t cfdp::VarLenField::getValue() const {
switch (width) {
case (cfdp::WidthInBytes::ONE_BYTE): {
return value.oneByte;

@ -25,13 +25,13 @@ class VarLenField : public SerializeIF {
template <typename T>
explicit VarLenField(UnsignedByteField<T> byteField);
VarLenField(cfdp::WidthInBytes width, size_t value);
VarLenField(cfdp::WidthInBytes width, uint64_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 setValue(cfdp::WidthInBytes, uint64_t value);
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override;
@ -42,7 +42,7 @@ class VarLenField : public SerializeIF {
Endianness streamEndianness);
[[nodiscard]] cfdp::WidthInBytes getWidth() const;
[[nodiscard]] size_t getValue() const;
[[nodiscard]] uint64_t getValue() const;
#if FSFW_CPP_OSTREAM_ENABLED == 1
friend std::ostream &operator<<(std::ostream &os, const VarLenField &id) {
@ -53,6 +53,7 @@ class VarLenField : public SerializeIF {
#endif
private:
using SerializeIF::deSerialize;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;

@ -9,6 +9,11 @@
#include "fsfw/returnvalues/FwClassIds.h"
#include "fsfw/returnvalues/returnvalue.h"
// Thanks, windows
#ifdef NO_ERROR
#undef NO_ERROR
#endif
namespace cfdp {
static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5";

@ -42,6 +42,6 @@ size_t EofInfo::getSerializedSize(bool fssLarge) {
return size;
}
ReturnValue_t EofInfo::setFileSize(size_t fileSize, bool isLarge) {
ReturnValue_t EofInfo::setFileSize(uint64_t fileSize, bool isLarge) {
return this->fileSize.setFileSize(fileSize, isLarge);
}

@ -21,7 +21,7 @@ struct EofInfo {
void setChecksum(uint32_t checksum);
void setConditionCode(cfdp::ConditionCode conditionCode);
void setFaultLoc(EntityIdTlv* faultLoc);
ReturnValue_t setFileSize(size_t size, bool isLarge);
ReturnValue_t setFileSize(uint64_t size, bool isLarge);
private:
cfdp::ConditionCode conditionCode;

@ -1,5 +1,10 @@
#include "FinishedPduReader.h"
// Thanks, windows
#ifdef NO_ERROR
#undef NO_ERROR
#endif
FinishPduReader::FinishPduReader(const uint8_t* pduBuf, size_t maxSize, FinishedInfo& info)
: FileDirectiveReader(pduBuf, maxSize), finishedInfo(info) {}

@ -23,6 +23,7 @@ class EntityIdTlv : public TlvIF {
*/
ReturnValue_t deSerialize(cfdp::Tlv& tlv, Endianness endianness);
using SerializeIF::deSerialize;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;

@ -26,6 +26,7 @@ class FilestoreRequestTlv : public cfdp::FilestoreTlvBase {
*/
ReturnValue_t deSerialize(cfdp::Tlv &tlv, Endianness endianness);
using SerializeIF::deSerialize;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;

@ -29,6 +29,7 @@ class FilestoreResponseTlv : public cfdp::FilestoreTlvBase {
*/
ReturnValue_t deSerialize(const cfdp::Tlv& tlv, Endianness endianness);
using SerializeIF::deSerialize;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;

@ -12,7 +12,6 @@ template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
class FixedArrayList : public ArrayList<T, count_t> {
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
"count_t is not large enough to hold MAX_SIZE");
static_assert(MAX_SIZE > 0, "MAX_SIZE is 0");
private:
T data[MAX_SIZE];

@ -364,6 +364,10 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
void printWarningOrError(sif::OutputTypes outputType, const char* functionName,
ReturnValue_t errorCode = returnvalue::FAILED,
const char* errorPrint = nullptr);
private:
using ProvidesDataPoolSubscriptionIF::subscribeForPeriodicPacket;
using ProvidesDataPoolSubscriptionIF::subscribeForUpdatePacket;
};
template <class T>

@ -1,6 +1,5 @@
#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"
@ -322,8 +321,7 @@ void DeviceHandlerBase::doStateMachine() {
if (mode != currentMode) {
break;
}
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
uint32_t currentUptime = Clock::getUptime_ms();
if (currentUptime - timeoutStart >= childTransitionDelay) {
#if FSFW_VERBOSE_LEVEL >= 1 && FSFW_OBJ_EVENT_TRANSLATION == 0
char printout[60];
@ -347,8 +345,7 @@ void DeviceHandlerBase::doStateMachine() {
setMode(_MODE_WAIT_ON);
break;
case _MODE_WAIT_ON: {
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
uint32_t currentUptime = Clock::getUptime_ms();
if (powerSwitcher != nullptr and
currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
@ -367,8 +364,7 @@ void DeviceHandlerBase::doStateMachine() {
}
} break;
case _MODE_WAIT_OFF: {
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
uint32_t currentUptime = Clock::getUptime_ms();
if (powerSwitcher == nullptr) {
setMode(MODE_OFF);
@ -578,7 +574,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
modeHelper.modeChanged(newMode, newSubmode);
announceMode(false);
}
Clock::getUptime(&timeoutStart);
timeoutStart = Clock::getUptime_ms();
if (mode == MODE_OFF and thermalSet != nullptr) {
ReturnValue_t result = thermalSet->read();
@ -1509,10 +1505,7 @@ DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() {
for (const auto& reply : deviceReplyMap) {
if (reply.second.dataSet != nullptr) {
PoolReadGuard pg(reply.second.dataSet);
if (pg.getReadResult() == returnvalue::OK) {
reply.second.dataSet->setValidity(false, true);
}
reply.second.dataSet->setValidity(false, true);
}
}
}

@ -206,9 +206,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
Mode_t getTransitionSourceMode() const;
Submode_t getTransitionSourceSubMode() const;
virtual void getMode(Mode_t *mode, Submode_t *submode);
HealthState getHealth();
ReturnValue_t setHealth(HealthState health);
virtual void getMode(Mode_t *mode, Submode_t *submode) override;
HealthState getHealth() override;
ReturnValue_t setHealth(HealthState health) override;
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues,
@ -1073,7 +1073,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
bool forceDirectTm = false);
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode);
uint32_t *msToReachTheMode) override;
virtual ReturnValue_t letChildHandleMessage(CommandMessage *message);

@ -28,22 +28,23 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
MessageQueueId_t getEventReportQueue();
MessageQueueId_t getEventReportQueue() override;
ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false);
ReturnValue_t registerListener(MessageQueueId_t listener,
bool forwardAllButSelected = false) override;
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 subscribeToEvent(MessageQueueId_t listener, EventId_t event) override;
ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object) override;
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);
bool reporterInverted = false) override;
ReturnValue_t unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object) override;
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);
bool reporterInverted = false) override;
ReturnValue_t performOperation(uint8_t opCode) override;
protected:
MessageQueueIF* eventReportQueue = nullptr;

@ -52,6 +52,7 @@ ReturnValue_t DleParser::parseRingBuf(size_t& readSize) {
// without skipping the STX
readSize = vectorIdx;
ErrorInfo info;
info.len = vectorIdx;
setErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info);
return POSSIBLE_PACKET_LOSS;
}

@ -58,7 +58,7 @@ class Type : public SerializeIF {
template <typename T>
struct PodTypeConversion {
static_assert(not std::is_same<T, bool>::value,
static_assert(!std::is_same<T, bool>::value,
"Do not use boolean for the PoolEntry type, use uint8_t "
"instead! The ECSS standard defines a boolean as a one bit "
"field. Therefore it is preferred to store a boolean as an "

@ -37,16 +37,16 @@ void arrayprinter::print(const uint8_t *data, size_t size, OutputType type, bool
}
}
void arrayprinter::printHex(const uint8_t *data, size_t size, size_t maxCharPerLine) {
void arrayprinter::printHex(const uint8_t *data, size_t datasize, size_t maxCharPerLine) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
if (sif::info.crAdditionEnabled()) {
std::cout << "\r" << std::endl;
}
std::cout << "hex [" << std::setfill('0') << std::hex;
for (size_t i = 0; i < size; i++) {
for (size_t i = 0; i < datasize; i++) {
std::cout << std::setw(2) << static_cast<int>(data[i]);
if (i < size - 1) {
if (i < datasize - 1) {
std::cout << ",";
if (i > 0 and (i + 1) % maxCharPerLine == 0) {
std::cout << std::endl;
@ -56,27 +56,11 @@ void arrayprinter::printHex(const uint8_t *data, size_t size, size_t maxCharPerL
std::cout << std::dec << std::setfill(' ');
std::cout << "]" << std::endl;
#else
// General format: 0x01, 0x02, 0x03 so it is number of chars times 6
// plus line break plus small safety margin.
char printBuffer[(size + 1) * 7 + 1] = {};
size_t currentPos = 0;
for (size_t i = 0; i < size; i++) {
// To avoid buffer overflows.
if (sizeof(printBuffer) - currentPos <= 7) {
break;
}
currentPos += snprintf(printBuffer + currentPos, 6, "%02x", data[i]);
if (i < size - 1) {
currentPos += sprintf(printBuffer + currentPos, ",");
if ((i + 1) % maxCharPerLine == 0) {
currentPos += sprintf(printBuffer + currentPos, "\n");
}
}
printf("hex [");
for (size_t i = 0; i < datasize; i++) {
printf("0x%02x ", data[i]);
}
#if FSFW_DISABLE_PRINTOUT == 0
printf("hex [%s]\n", printBuffer);
#endif /* FSFW_DISABLE_PRINTOUT == 0 */
printf("]\n");
#endif
}
@ -100,26 +84,10 @@ void arrayprinter::printDec(const uint8_t *data, size_t size, size_t maxCharPerL
#else
// General format: 32,243,-12 so it is number of chars times 4
// plus line break plus small safety margin.
uint16_t expectedLines = ceil((double)size / maxCharPerLine);
char printBuffer[size * 4 + 1 + expectedLines] = {};
size_t currentPos = 0;
for (size_t i = 0; i < size; i++) {
// To avoid buffer overflows.
if (sizeof(printBuffer) - currentPos <= 4) {
break;
}
currentPos += snprintf(printBuffer + currentPos, 4, "%d", data[i]);
if (i < size - 1) {
currentPos += sprintf(printBuffer + currentPos, ",");
if ((i + 1) % maxCharPerLine == 0) {
currentPos += sprintf(printBuffer + currentPos, "\n");
}
}
for (size_t i = 0; i < size; i++) {
// TODO
}
#if FSFW_DISABLE_PRINTOUT == 0
printf("dec [%s]\n", printBuffer);
#endif /* FSFW_DISABLE_PRINTOUT == 0 */
#endif
}

@ -16,24 +16,26 @@ class HasHealthIF {
};
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
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 ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1);
static const ReturnValue_t INVALID_HEALTH_STATE = MAKE_RETURN_CODE(2);
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);
//! 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);
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.
virtual ~HasHealthIF() {}
virtual MessageQueueId_t getCommandQueue() const = 0;

@ -8,8 +8,6 @@
#include "HealthTableIF.h"
class HealthTable : public HealthTableIF, public SystemObject {
friend class CServiceHealthCommanding;
public:
explicit HealthTable(object_id_t objectid);
~HealthTable() override;

@ -55,7 +55,7 @@ class HousekeepingSnapshot : public SerializeIF {
: timeStamp(timeStamp), timeStampSize(timeStampSize), updateData(dataSetPtr){};
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const {
Endianness streamEndianness) const override {
if (timeStamp != nullptr) {
/* Endianness will always be MACHINE, so we can simply use memcpy
here. */
@ -70,7 +70,7 @@ class HousekeepingSnapshot : public SerializeIF {
return updateData->serialize(buffer, size, maxSize, streamEndianness);
}
virtual size_t getSerializedSize() const {
virtual size_t getSerializedSize() const override {
if (updateData == nullptr) {
return 0;
}

@ -7,10 +7,10 @@
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();
}

@ -24,19 +24,3 @@ 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); }

@ -45,9 +45,6 @@ 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);
};

@ -18,7 +18,7 @@ class AbsLimitMonitor : public MonitorBase<T> {
violationEvent(violationEvent),
aboveIsViolation(aboveIsViolation) {}
virtual ~AbsLimitMonitor() {}
virtual ReturnValue_t checkSample(T sample, T *crossedLimit) {
ReturnValue_t checkSample(T sample, T *crossedLimit) override {
*crossedLimit = limit;
if (aboveIsViolation) {
if ((std::abs(sample) > limit)) {
@ -32,9 +32,9 @@ class AbsLimitMonitor : public MonitorBase<T> {
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<T>::getParameter(
domainId, parameterId, parameterWrapper, newValues, startAtIndex);
// We'll reuse the DOMAIN_ID of MonitorReporter,
@ -61,7 +61,7 @@ class AbsLimitMonitor : public MonitorBase<T> {
void setLimit(T value) { limit = value; }
protected:
void sendTransitionEvent(T currentValue, ReturnValue_t state) {
void sendTransitionEvent(T currentValue, ReturnValue_t state) override {
switch (state) {
case MonitoringIF::OUT_OF_RANGE:
EventManagerIF::triggerEvent(this->reportingId, violationEvent, this->globalPoolId.objectId,

@ -18,10 +18,7 @@ elseif(FSFW_OSAL MATCHES "host")
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)

@ -24,8 +24,11 @@
#else
#ifdef WIN32
#include <windows.h>
// Thanks, windows
// clang-format off
#include <winsock2.h>
#include <windows.h>
// clang-format on
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
#define BYTE_ORDER_SYSTEM LITTLE_ENDIAN
#else

@ -16,7 +16,7 @@
#ifdef PLATFORM_WIN
#include <winsock2.h>
#include <ws2tcpip.h>
typedef SSIZE_T ssize_t;
#elif defined(PLATFORM_UNIX)
#include <netdb.h>
@ -26,12 +26,12 @@
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
TcpTmTcServer::TcpConfig cfg, size_t receptionBufferSize,
size_t ringBufferSize, ReceptionModes receptionMode)
size_t receptionBufferSize, size_t ringBufferSize,
std::string customTcpServerPort, ReceptionModes receptionMode)
: SystemObject(objectId),
tmtcBridgeId(tmtcTcpBridge),
receptionMode(receptionMode),
tcpConfig(cfg),
tcpConfig(std::move(customTcpServerPort)),
receptionBuffer(receptionBufferSize),
ringBuffer(ringBufferSize, true) {}
@ -91,15 +91,6 @@ ReturnValue_t TcpTmTcServer::initialize() {
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
retval = bind(listenerTcpSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen));
if (retval == SOCKET_ERROR) {

@ -41,11 +41,11 @@ class SpacePacketParser;
*/
class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableObjectIF {
public:
enum class ReceptionModes { SPACE_PACKETS };
struct TcpConfig {
public:
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) {}
explicit TcpConfig(std::string tcpPort) : tcpPort(std::move(tcpPort)) {}
/**
* Passed to the recv call
@ -63,23 +63,8 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
*/
int tcpTmFlags = 0;
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;
const std::string tcpPort;
};
enum class ReceptionModes { SPACE_PACKETS };
static const std::string DEFAULT_SERVER_PORT;
@ -95,9 +80,10 @@ 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::TcpConfig cfg,
TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
size_t receptionBufferSize = RING_BUFFER_SIZE,
size_t ringBufferSize = RING_BUFFER_SIZE,
std::string customTcpServerPort = DEFAULT_SERVER_PORT,
ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS);
~TcpTmTcServer() override;
@ -130,7 +116,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;

@ -8,6 +8,7 @@
#ifdef PLATFORM_WIN
#include <winsock2.h>
typedef SSIZE_T ssize_t;
#elif defined(PLATFORM_UNIX)
#include <sys/socket.h>
#include <sys/types.h>

@ -7,6 +7,7 @@
#ifdef PLATFORM_WIN
#include <ws2tcpip.h>
typedef SSIZE_T ssize_t;
#elif defined(PLATFORM_UNIX)
#include <arpa/inet.h>
#include <netdb.h>

@ -40,7 +40,7 @@ class BinarySemaphoreUsingTask : public SemaphoreIF {
void refreshTaskHandle();
ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING,
uint32_t timeoutMs = portMAX_DELAY) override;
uint32_t timeoutMs = 0) override;
ReturnValue_t release() override;
uint8_t getSemaphoreCounter() const override;
static uint8_t getSemaphoreCounter(TaskHandle_t taskHandle);

@ -51,7 +51,7 @@ class BinarySemaphore : public SemaphoreIF {
* -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/
ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING,
uint32_t timeoutMs = portMAX_DELAY) override;
uint32_t timeoutMs = 0) override;
/**
* Same as lockBinarySemaphore() with timeout in FreeRTOS ticks.

@ -11,19 +11,6 @@
// TODO sanitize input?
// TODO much of this code can be reused for tick-only systems
uint32_t Clock::getTicksPerSecond(void) { return 1000; }
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
timeval time_timeval;
ReturnValue_t result = convertTimeOfDayToTimeval(time, &time_timeval);
if (result != returnvalue::OK) {
return result;
}
return setClock(&time_timeval);
}
ReturnValue_t Clock::setClock(const timeval* time) {
timeval uptime = getUptime();
@ -44,81 +31,12 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
return returnvalue::OK;
}
ReturnValue_t Clock::getUptime(timeval* uptime) {
*uptime = getUptime();
return returnvalue::OK;
}
timeval Clock::getUptime() {
TickType_t ticksSinceStart = xTaskGetTickCount();
return Timekeeper::ticksToTimeval(ticksSinceStart);
}
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
timeval uptime = getUptime();
*uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000;
return returnvalue::OK;
}
// uint32_t Clock::getUptimeSeconds() {
// timeval uptime = getUptime();
// return uptime.tv_sec;
// }
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval time_timeval;
ReturnValue_t result = getClock_timeval(&time_timeval);
if (result != returnvalue::OK) {
return result;
}
*time = time_timeval.tv_sec * 1000000 + time_timeval.tv_usec;
return returnvalue::OK;
}
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
timeval time_timeval;
ReturnValue_t result = getClock_timeval(&time_timeval);
if (result != returnvalue::OK) {
return result;
}
struct tm time_tm;
gmtime_r(&time_timeval.tv_sec, &time_tm);
time->year = time_tm.tm_year + 1900;
time->month = time_tm.tm_mon + 1;
time->day = time_tm.tm_mday;
time->hour = time_tm.tm_hour;
time->minute = time_tm.tm_min;
time->second = time_tm.tm_sec;
time->usecond = time_timeval.tv_usec;
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
struct tm time_tm = {};
time_tm.tm_year = from->year - 1900;
time_tm.tm_mon = from->month - 1;
time_tm.tm_mday = from->day;
time_tm.tm_hour = from->hour;
time_tm.tm_min = from->minute;
time_tm.tm_sec = from->second;
time_t seconds = mktime(&time_tm);
to->tv_sec = seconds;
to->tv_usec = from->usecond;
// Fails in 2038..
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
return returnvalue::OK;
}

@ -34,7 +34,7 @@ class CountingSemaphoreUsingTask : public SemaphoreIF {
* -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/
ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING,
uint32_t timeoutMs = portMAX_DELAY) override;
uint32_t timeoutMs = 0) override;
/**
* Release a semaphore, increasing the number of available counting

@ -56,7 +56,9 @@ ReturnValue_t FixedTimeslotTask::startTask() {
// start time for the first entry.
auto slotListIter = pollingSeqTable.current;
pollingSeqTable.intializeSequenceAfterTaskCreation();
ReturnValue_t result = pollingSeqTable.intializeSequenceAfterTaskCreation();
// Ignore returnvalue for now
static_cast<void>(result);
// The start time for the first entry is read.
uint32_t intervalMs = slotListIter->pollingTimeMs;

@ -22,7 +22,7 @@ ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) {
return MutexIF::MUTEX_NOT_FOUND;
}
// If the timeout type is BLOCKING, this will be the correct value.
uint32_t timeout = portMAX_DELAY;
TickType_t timeout = portMAX_DELAY;
if (timeoutType == TimeoutType::POLLING) {
timeout = 0;
} else if (timeoutType == TimeoutType::WAITING) {

@ -3,16 +3,16 @@
void TaskManagement::vRequestContextSwitchFromTask() { vTaskDelay(0); }
void TaskManagement::requestContextSwitch(CallContext callContext = CallContext::TASK) {
if (callContext == CallContext::ISR) {
// This function depends on the partmacro.h definition for the specific device
vRequestContextSwitchFromISR();
} else {
vRequestContextSwitchFromTask();
}
// if (callContext == CallContext::ISR) {
// // This function depends on the partmacro.h definition for the specific device
// vRequestContextSwitchFromISR();
// } else {
vRequestContextSwitchFromTask();
// }
}
TaskHandle_t TaskManagement::getCurrentTaskHandle() { return xTaskGetCurrentTaskHandle(); }
size_t TaskManagement::getTaskStackHighWatermark(TaskHandle_t task) {
return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t);
}
// size_t TaskManagement::getTaskStackHighWatermark(TaskHandle_t task) {
// return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t);
// }

@ -11,7 +11,7 @@
* Architecture dependant portmacro.h function call.
* Should be implemented in bsp.
*/
extern "C" void vRequestContextSwitchFromISR();
// extern "C" void vRequestContextSwitchFromISR();
/*!
* Used by functions to tell if they are being called from
@ -53,7 +53,7 @@ TaskHandle_t getCurrentTaskHandle();
* @return Smallest value of stack remaining since the task was started in
* words.
*/
size_t getTaskStackHighWatermark(TaskHandle_t task = nullptr);
// size_t getTaskStackHighWatermark(TaskHandle_t task = nullptr);
}; // namespace TaskManagement

@ -15,27 +15,6 @@
using SystemClock = std::chrono::system_clock;
uint32_t Clock::getTicksPerSecond(void) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getTicksPerSecond: Not implemented for host OSAL" << std::endl;
#else
sif::printWarning("Clock::getTicksPerSecond: Not implemented for host OSAL\n");
#endif
/* To avoid division by zero */
return 1;
}
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
/* I don't know why someone would need to set a clock which is probably perfectly fine on a
host system with internet access so this is not implemented for now. */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::setClock: Not implemented for host OSAL" << std::endl;
#else
sif::printWarning("Clock::setClock: Not implemented for host OSAL\n");
#endif
return returnvalue::OK;
}
ReturnValue_t Clock::setClock(const timeval* time) {
/* I don't know why someone would need to set a clock which is probably perfectly fine on a
host system with internet access so this is not implemented for now. */
@ -66,6 +45,7 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
time->tv_usec = timeUnix.tv_nsec / 1000.0;
return returnvalue::OK;
#else
#warning Clock::getClock_timeval() not implemented for your platform
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl;
#else
@ -75,15 +55,6 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
#endif
}
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
if (time == nullptr) {
return returnvalue::FAILED;
}
using namespace std::chrono;
*time = duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
return returnvalue::OK;
}
timeval Clock::getUptime() {
timeval timeval;
#if defined(PLATFORM_WIN)
@ -100,73 +71,10 @@ timeval Clock::getUptime() {
timeval.tv_usec = uptimeSeconds * (double)1e6 - (timeval.tv_sec * 1e6);
}
#else
#warning Clock::getUptime() not implemented for your platform
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
#endif
#endif
return timeval;
}
ReturnValue_t Clock::getUptime(timeval* uptime) {
*uptime = getUptime();
return returnvalue::OK;
}
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
timeval uptime = getUptime();
*uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000;
return returnvalue::OK;
}
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
/* Do some magic with chrono (C++20!) */
/* Right now, the library doesn't have the new features to get the required values yet.
so we work around that for now. */
auto now = SystemClock::now();
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
auto fraction = now - seconds;
time_t tt = SystemClock::to_time_t(now);
ReturnValue_t result = checkOrCreateClockMutex();
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;
timeInfo = gmtime(&tt);
time->year = timeInfo->tm_year + 1900;
time->month = timeInfo->tm_mon + 1;
time->day = timeInfo->tm_mday;
time->hour = timeInfo->tm_hour;
time->minute = timeInfo->tm_min;
time->second = timeInfo->tm_sec;
auto usecond = std::chrono::duration_cast<std::chrono::microseconds>(fraction);
time->usecond = usecond.count();
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
struct tm time_tm {};
time_tm.tm_year = from->year - 1900;
time_tm.tm_mon = from->month - 1;
time_tm.tm_mday = from->day;
time_tm.tm_hour = from->hour;
time_tm.tm_min = from->minute;
time_tm.tm_sec = from->second;
time_tm.tm_isdst = 0;
time_t seconds = timegm(&time_tm);
to->tv_sec = seconds;
to->tv_usec = from->usecond;
// Fails in 2038..
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
return returnvalue::OK;
}

@ -9,7 +9,6 @@
#include "fsfw/serviceinterface/ServiceInterface.h"
#if defined(PLATFORM_WIN)
#include <processthreadsapi.h>
#include "fsfw/osal/windows/winTaskHelpers.h"
#elif defined(PLATFORM_UNIX)

@ -50,6 +50,6 @@ void TaskFactory::printMissedDeadline() {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TaskFactory::printMissedDeadline: " << name << std::endl;
#else
sif::printWarning("TaskFactory::printMissedDeadline: %s\n", name);
sif::printWarning("TaskFactory::printMissedDeadline: %s\n", name.c_str());
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
}

@ -3,6 +3,7 @@
#include <fsfw/returnvalues/returnvalue.h>
#include <string>
#include <thread>
namespace tasks {

@ -10,26 +10,6 @@
#include "fsfw/ipc/MutexGuard.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
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{};
convertTimeOfDayToTimeval(time, &timeTimeval);
timeUnix.tv_sec = timeTimeval.tv_sec;
timeUnix.tv_nsec = (__syscall_slong_t)timeTimeval.tv_usec * 1000;
int status = clock_settime(CLOCK_REALTIME, &timeUnix);
if (status != 0) {
// TODO errno
return returnvalue::FAILED;
}
return returnvalue::OK;
}
ReturnValue_t Clock::setClock(const timeval* time) {
timespec timeUnix{};
timeUnix.tv_sec = time->tv_sec;
@ -53,104 +33,12 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
return returnvalue::OK;
}
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval timeVal{};
ReturnValue_t result = getClock_timeval(&timeVal);
if (result != returnvalue::OK) {
return result;
}
*time = static_cast<uint64_t>(timeVal.tv_sec) * 1e6 + timeVal.tv_usec;
return returnvalue::OK;
}
timeval Clock::getUptime() {
timeval uptime{};
auto result = getUptime(&uptime);
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Clock::getUptime: Error getting uptime" << std::endl;
#endif
timeval uptime{0, 0};
double uptimeSeconds;
if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) {
uptime.tv_sec = uptimeSeconds;
uptime.tv_usec = uptimeSeconds * (double)1e6 - (uptime.tv_sec * 1e6);
}
return uptime;
}
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) {
uptime->tv_sec = uptimeSeconds;
uptime->tv_usec = uptimeSeconds * (double)1e6 - (uptime->tv_sec * 1e6);
}
return returnvalue::OK;
}
// Wait for new FSFW Clock function delivering seconds uptime.
// uint32_t Clock::getUptimeSeconds() {
// //TODO This is not posix compatible and delivers only seconds precision
// struct sysinfo sysInfo;
// int result = sysinfo(&sysInfo);
// if(result != 0){
// return returnvalue::FAILED;
// }
// return sysInfo.uptime;
//}
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
timeval uptime{};
ReturnValue_t result = getUptime(&uptime);
if (result != returnvalue::OK) {
return result;
}
*uptimeMs = uptime.tv_sec * 1e3 + uptime.tv_usec / 1e3;
return returnvalue::OK;
}
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
timespec timeUnix{};
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
if (status != 0) {
// TODO errno
return returnvalue::FAILED;
}
ReturnValue_t result = checkOrCreateClockMutex();
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 std::tm* timeInfo;
timeInfo = gmtime(&timeUnix.tv_sec);
time->year = timeInfo->tm_year + 1900;
time->month = timeInfo->tm_mon + 1;
time->day = timeInfo->tm_mday;
time->hour = timeInfo->tm_hour;
time->minute = timeInfo->tm_min;
time->second = timeInfo->tm_sec;
time->usecond = timeUnix.tv_nsec / 1000.0;
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
std::tm fromTm{};
// Note: Fails for years before AD
fromTm.tm_year = from->year - 1900;
fromTm.tm_mon = from->month - 1;
fromTm.tm_mday = from->day;
fromTm.tm_hour = from->hour;
fromTm.tm_min = from->minute;
fromTm.tm_sec = from->second;
fromTm.tm_isdst = 0;
to->tv_sec = timegm(&fromTm);
to->tv_usec = from->usecond;
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
return returnvalue::OK;
}

@ -2,6 +2,8 @@
#include <rtems/rtems/sem.h>
// TODO
BinarySemaphore::BinarySemaphore() {}
BinarySemaphore::~BinarySemaphore() {}

@ -6,20 +6,21 @@
#include "fsfw/ipc/MutexGuard.h"
#include "fsfw/osal/rtems/RtemsBasic.h"
uint32_t Clock::getTicksPerSecond(void) {
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
return static_cast<uint32_t>(ticks_per_second);
}
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
ReturnValue_t Clock::setClock(const timeval* time) {
TimeOfDay_t time_tod;
ReturnValue_t result = convertTimevalToTimeOfDay(time, &time_tod);
if (result != returnvalue::OK) {
return result;
}
rtems_time_of_day timeRtems;
timeRtems.year = time->year;
timeRtems.month = time->month;
timeRtems.day = time->day;
timeRtems.hour = time->hour;
timeRtems.minute = time->minute;
timeRtems.second = time->second;
timeRtems.ticks = time->usecond * getTicksPerSecond() / 1e6;
timeRtems.year = time_tod.year;
timeRtems.month = time_tod.month;
timeRtems.day = time_tod.day;
timeRtems.hour = time_tod.hour;
timeRtems.minute = time_tod.minute;
timeRtems.second = time_tod.second;
timeRtems.ticks =
static_cast<uint64_t>(time_tod.usecond) * rtems_clock_get_ticks_per_second() / 1e6;
rtems_status_code status = rtems_clock_set(&timeRtems);
switch (status) {
case RTEMS_SUCCESSFUL:
@ -33,27 +34,6 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
}
}
ReturnValue_t Clock::setClock(const timeval* time) {
timespec newTime;
newTime.tv_sec = time->tv_sec;
if (time->tv_usec < 0) {
// better returnvalue.
return returnvalue::FAILED;
}
newTime.tv_nsec = time->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND;
ISR_lock_Context context;
_TOD_Lock();
_TOD_Acquire(&context);
Status_Control status = _TOD_Set(&newTime, &context);
_TOD_Unlock();
if (status == STATUS_SUCCESSFUL) {
return returnvalue::OK;
}
// better returnvalue
return returnvalue::FAILED;
}
ReturnValue_t Clock::getClock_timeval(timeval* time) {
// Callable from ISR
rtems_status_code status = rtems_clock_get_tod_timeval(time);
@ -67,86 +47,13 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
}
}
ReturnValue_t Clock::getUptime(timeval* uptime) {
timeval Clock::getUptime() {
// According to docs.rtems.org for rtems 5 this method is more accurate than
// rtems_clock_get_ticks_since_boot
timeval time_timeval;
timespec time;
rtems_status_code status = rtems_clock_get_uptime(&time);
uptime->tv_sec = time.tv_sec;
time.tv_nsec = time.tv_nsec / 1000;
uptime->tv_usec = time.tv_nsec;
switch (status) {
case RTEMS_SUCCESSFUL:
return returnvalue::OK;
default:
return returnvalue::FAILED;
}
}
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
// This counter overflows after 50 days
*uptimeMs = rtems_clock_get_ticks_since_boot();
return returnvalue::OK;
}
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval temp_time;
rtems_status_code returnValue = rtems_clock_get_tod_timeval(&temp_time);
*time = ((uint64_t)temp_time.tv_sec * 1000000) + temp_time.tv_usec;
switch (returnValue) {
case RTEMS_SUCCESSFUL:
return returnvalue::OK;
default:
return returnvalue::FAILED;
}
}
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
/* For all but the last field, the struct will be filled with the correct values */
rtems_time_of_day timeRtems;
rtems_status_code status = rtems_clock_get_tod(&timeRtems);
switch (status) {
case RTEMS_SUCCESSFUL: {
/* The last field now contains the RTEMS ticks of the seconds from 0
to rtems_clock_get_ticks_per_second() minus one.
We calculate the microseconds accordingly */
time->day = timeRtems.day;
time->hour = timeRtems.hour;
time->minute = timeRtems.minute;
time->month = timeRtems.month;
time->second = timeRtems.second;
time->usecond =
static_cast<float>(timeRtems.ticks) / rtems_clock_get_ticks_per_second() * 1e6;
time->year = timeRtems.year;
return returnvalue::OK;
}
case RTEMS_NOT_DEFINED:
/* System date and time is not set */
return returnvalue::FAILED;
case RTEMS_INVALID_ADDRESS:
/* time_buffer is NULL */
return returnvalue::FAILED;
default:
return returnvalue::FAILED;
}
}
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
// Fails in 2038..
rtems_time_of_day timeRtems;
timeRtems.year = from->year;
timeRtems.month = from->month;
timeRtems.day = from->day;
timeRtems.hour = from->hour;
timeRtems.minute = from->minute;
timeRtems.second = from->second;
timeRtems.ticks = from->usecond * getTicksPerSecond() / 1e6;
to->tv_sec = _TOD_To_seconds(&timeRtems);
to->tv_usec = from->usecond;
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
return returnvalue::OK;
time_timeval.tv_sec = time.tv_sec;
time_timeval.tv_usec = time.tv_nsec / 1000;
return time_timeval;
}

@ -93,8 +93,8 @@ ReturnValue_t CpuUsage::serialize(uint8_t** buffer, size_t* size, size_t maxSize
streamEndianness);
}
uint32_t CpuUsage::getSerializedSize() const {
uint32_t size = 0;
size_t CpuUsage::getSerializedSize() const {
size_t size = 0;
size += sizeof(timeSinceLastReset);
size += SerialArrayListAdapter<ThreadData>::getSerializedSize(&threadData);
@ -136,8 +136,8 @@ ReturnValue_t CpuUsage::ThreadData::serialize(uint8_t** buffer, size_t* size, si
return returnvalue::OK;
}
uint32_t CpuUsage::ThreadData::getSerializedSize() const {
uint32_t size = 0;
size_t CpuUsage::ThreadData::getSerializedSize() const {
size_t size = 0;
size += sizeof(id);
size += MAX_LENGTH_OF_THREAD_NAME;

@ -35,20 +35,19 @@ ReturnValue_t InternalErrorCodes::translate(uint8_t code) {
return OUT_OF_PROXIES;
case INTERNAL_ERROR_INVALID_GLOBAL_ID:
return INVALID_GLOBAL_ID;
#ifndef STM32H743ZI_NUCLEO
case INTERNAL_ERROR_BAD_STACK_HOOK:
return BAD_STACK_HOOK;
#endif
// case INTERNAL_ERROR_BAD_ATTRIBUTES:
// return BAD_ATTRIBUTES;
// case INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY:
// return IMPLEMENTATION_KEY_CREATE_INCONSISTENCY;
// case INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL:
// return IMPLEMENTATION_BLOCKING_OPERATION_CANCEL;
// case INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE:
// return MUTEX_OBTAIN_FROM_BAD_STATE;
// case INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0:
// return UNLIMITED_AND_MAXIMUM_IS_0;
// TODO this one is not there anymore in rtems-6 (5 as well?)
// case INTERNAL_ERROR_BAD_STACK_HOOK:
// return BAD_STACK_HOOK;
// case INTERNAL_ERROR_BAD_ATTRIBUTES:
// return BAD_ATTRIBUTES;
// case INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY:
// return IMPLEMENTATION_KEY_CREATE_INCONSISTENCY;
// case INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL:
// return IMPLEMENTATION_BLOCKING_OPERATION_CANCEL;
// case INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE:
// return MUTEX_OBTAIN_FROM_BAD_STATE;
// case INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0:
// return UNLIMITED_AND_MAXIMUM_IS_0;
default:
return returnvalue::FAILED;
}

@ -18,7 +18,9 @@ SemaphoreFactory* SemaphoreFactory::instance() {
}
SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) {
return new BinarySemaphore();
return nullptr;
// TODO
// return new BinarySemaphore();
}
SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount, uint8_t initCount,

@ -5,7 +5,11 @@
#ifdef _WIN32
#include <minwindef.h>
// Thanks, windows
// clang-format off
#include <windows.h>
#include <processthreadsapi.h>
// clang-format on
namespace tasks {

@ -45,6 +45,7 @@ class ParameterWrapper : public SerializeIF {
virtual size_t getSerializedSize() const override;
using SerializeIF::deSerialize;
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;

@ -62,13 +62,13 @@ class Fuse : public SystemObject,
SerializeIF::Endianness streamEndianness) override;
void setAllMonitorsToUnchecked();
ReturnValue_t performOperation(uint8_t opCode);
MessageQueueId_t getCommandQueue() const;
MessageQueueId_t getCommandQueue() const override;
void setDataPoolEntriesInvalid();
ReturnValue_t setHealth(HealthState health);
HasHealthIF::HealthState getHealth();
ReturnValue_t setHealth(HealthState health) override;
HasHealthIF::HealthState getHealth() override;
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
const ParameterWrapper *newValues, uint16_t startAtIndex) override;
private:
uint8_t oldFuseState;

@ -10,15 +10,15 @@ class PowerComponent : public PowerComponentIF {
PowerComponent(object_id_t setId, uint8_t moduleId, float minPower, float maxPower,
uint8_t switchId1, bool twoSwitches = false, uint8_t switchId2 = 0xFF);
virtual object_id_t getDeviceObjectId();
object_id_t getDeviceObjectId() override;
virtual uint8_t getSwitchId1();
virtual uint8_t getSwitchId2();
uint8_t getSwitchId1() override;
uint8_t getSwitchId2() override;
bool hasTwoSwitches();
bool hasTwoSwitches() override;
float getMin();
float getMax();
float getMin() override;
float getMax() override;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
@ -29,7 +29,7 @@ class PowerComponent : public PowerComponentIF {
Endianness streamEndianness) override;
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex);
const ParameterWrapper* newValues, uint16_t startAtIndex) override;
private:
const object_id_t deviceObjectId = objects::NO_OBJECT;

@ -9,4 +9,4 @@ target_sources(
Service17Test.cpp
Service20ParameterManagement.cpp
CService200ModeCommanding.cpp
CServiceHealthCommanding.cpp)
CService201HealthCommanding.cpp)

@ -19,8 +19,7 @@ ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) {
switch (subservice) {
case (Subservice::COMMAND_MODE_COMMAND):
case (Subservice::COMMAND_MODE_READ):
case (Subservice::COMMAND_MODE_ANNOUNCE):
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
case (Subservice::COMMAND_MODE_ANNCOUNCE):
return returnvalue::OK;
default:
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
@ -54,32 +53,16 @@ ReturnValue_t CService200ModeCommanding::checkInterfaceAndAcquireMessageQueue(
ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
const uint8_t *tcData, size_t tcDataLen,
uint32_t *state, object_id_t objectId) {
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 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;
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;
}
ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply,
@ -90,10 +73,8 @@ ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply
ReturnValue_t result = returnvalue::FAILED;
switch (replyId) {
case (ModeMessage::REPLY_MODE_REPLY): {
if (previousCommand != ModeMessage::CMD_MODE_COMMAND) {
return prepareModeReply(reply, objectId);
}
return returnvalue::OK;
result = prepareModeReply(reply, objectId);
break;
}
case (ModeMessage::REPLY_WRONG_MODE_REPLY): {
result = prepareWrongModeReply(reply, objectId);

@ -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_ANNOUNCE = 4,
COMMAND_MODE_ANNCOUNCE = 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,

@ -0,0 +1,106 @@
#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, "PUS 201 Health MGMT", serviceId, numParallelCommands,
commandTimeoutSeconds) {}
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 returnvalue::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, const object_id_t *objectId) {
auto *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
if (destination == nullptr) {
return CommandingServiceBase::INVALID_OBJECT;
}
*messageQueueToSet = destination->getCommandQueue();
return returnvalue::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 = returnvalue::OK;
switch (subservice) {
case (Subservice::COMMAND_SET_HEALTH): {
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);
break;
}
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE_ALL);
break;
}
default: {
// Should never happen, subservice was already checked
result = returnvalue::FAILED;
}
}
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
[[maybe_unused]] ReturnValue_t CService201HealthCommanding::prepareHealthSetReply(
const CommandMessage *reply) {
auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
HealthSetReply healthSetReply(health, oldHealth);
return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply);
}

@ -1,26 +1,8 @@
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
#include <fsfw/health/HealthTable.h>
#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
* implementing hasHealthIF.
@ -35,12 +17,11 @@ struct HealthServiceCfg {
* child class like this service
*
*/
class CServiceHealthCommanding : public CommandingServiceBase {
class CService201HealthCommanding : public CommandingServiceBase {
public:
CServiceHealthCommanding(HealthServiceCfg args);
~CServiceHealthCommanding() override = default;
ReturnValue_t initialize() override;
CService201HealthCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId,
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
~CService201HealthCommanding() override = default;
protected:
/* CSB abstract function implementations */
@ -56,14 +37,7 @@ class CServiceHealthCommanding : public CommandingServiceBase {
CommandMessage *optionalNextCommand, object_id_t objectId,
bool *isStep) override;
void doPeriodicOperation() override;
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);

@ -1,161 +0,0 @@
#include <fsfw/events/EventManagerIF.h>
#include <fsfw/pus/CServiceHealthCommanding.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"
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<HealthTable>(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<HasHealthIF>(*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<uint8_t>(HealthMessage::getHealth(reply));
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
HealthSetReply healthSetReply(health, oldHealth);
return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply);
}
ReturnValue_t CServiceHealthCommanding::iterateHealthTable(bool reset) {
std::pair<object_id_t, HasHealthIF::HealthState> 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;
}
}

@ -13,7 +13,7 @@ Service1TelecommandVerification::Service1TelecommandVerification(object_id_t obj
uint16_t messageQueueDepth,
TimeWriterIF* timeStamper)
: SystemObject(objectId),
apid(apid),
// apid(apid),
serviceId(serviceId),
targetDestination(targetDestination),
storeHelper(apid),

@ -72,7 +72,7 @@ class Service1TelecommandVerification : public AcceptsVerifyMessageIF,
ReturnValue_t initialize() override;
private:
uint16_t apid = 0;
// uint16_t apid = 0;
uint8_t serviceId = 0;
object_id_t targetDestination = objects::NO_OBJECT;

@ -69,14 +69,14 @@ ReturnValue_t Service20ParameterManagement::checkInterfaceAndAcquireMessageQueue
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Service20ParameterManagement::checkInterfaceAndAcquire"
<< "MessageQueue: Can't access object" << std::endl;
sif::error << "Object ID: 0x" << std::hex << *objectId << std::dec << std::endl;
sif::error << "Make sure it implements ReceivesParameterMessagesIF" << std::endl;
sif::error << "Object ID: " << 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;

@ -1,7 +1,5 @@
#include "fsfw/pus/Service9TimeManagement.h"
#include <cmath>
#include "fsfw/events/EventManagerIF.h"
#include "fsfw/pus/servicepackets/Service9Packets.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
@ -17,17 +15,9 @@ 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<uint32_t>(std::floor(static_cast<double>(newTime.tv_usec) / 1000.0));
triggerEvent(CLOCK_DUMP, newTime.tv_sec, subsecondMs);
return returnvalue::OK;
}
default:
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
}
@ -43,14 +33,13 @@ ReturnValue_t Service9TimeManagement::setTime() {
return result;
}
timeval time;
Clock::getClock_timeval(&time);
// TODO maybe switch to getClock_usecs to report more meaningful data
uint32_t formerUptime = Clock::getUptime_ms();
result = Clock::setClock(&timeToSet);
if (result == returnvalue::OK) {
timeval newTime;
Clock::getClock_timeval(&newTime);
triggerEvent(CLOCK_SET, time.tv_sec, newTime.tv_sec);
uint32_t newUptime = Clock::getUptime_ms();
triggerEvent(CLOCK_SET, newUptime, formerUptime);
return returnvalue::OK;
} else {
triggerEvent(CLOCK_SET_FAILURE, result, 0);

@ -6,13 +6,10 @@
class Service9TimeManagement : public PusServiceBase {
public:
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
//!< 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 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.
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;
@ -33,9 +30,8 @@ class Service9TimeManagement : public PusServiceBase {
virtual ReturnValue_t setTime();
private:
enum Subservice {
SET_TIME = 128, //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format
DUMP_TIME = 129,
enum SUBSERVICE {
SET_TIME = 128 //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format
};
};

@ -69,7 +69,7 @@ class FailureReport : public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 2, 4, 6
return result;
}
virtual size_t getSerializedSize() const {
virtual size_t getSerializedSize() const override {
size_t size = 0;
size += SerializeAdapter::getSerializedSize(&packetId);
size += sizeof(packetSequenceControl);

@ -33,7 +33,7 @@
* @author baetz
* @ingroup serialize
*/
template <typename T, typename count_t = uint8_t>
template <typename T, typename count_t = size_t>
class SerialLinkedListAdapter : public SinglyLinkedList<T>, public SerializeIF {
public:
SerialLinkedListAdapter(typename LinkedElement<T>::Iterator start, bool printCount = false)

@ -109,7 +109,8 @@ ReturnValue_t LocalPool::deleteData(uint8_t* ptr, size_t size, store_address_t*
ReturnValue_t result = ILLEGAL_ADDRESS;
for (uint16_t n = 0; n < NUMBER_OF_SUBPOOLS; n++) {
// Not sure if new allocates all stores in order. so better be careful.
if ((store[n].data() <= ptr) and (&store[n][numberOfElements[n] * elementSizes[n]] > ptr)) {
if ((store[n].data() <= ptr) and
(&store[n][numberOfElements[n] * elementSizes[n] - 1] >= ptr)) {
localId.poolIndex = n;
uint32_t deltaAddress = ptr - store[n].data();
// Getting any data from the right "block" is ok.

@ -91,11 +91,10 @@ void Subsystem::performChildOperation() {
}
if (currentSequenceIterator->getWaitSeconds() != 0) {
if (uptimeStartTable == 0) {
Clock::getUptime(&uptimeStartTable);
uptimeStartTable = Clock::getUptime_ms();
return;
} else {
uint32_t uptimeNow;
Clock::getUptime(&uptimeNow);
uint32_t uptimeNow = Clock::getUptime_ms();
if ((uptimeNow - uptimeStartTable) < (currentSequenceIterator->getWaitSeconds() * 1000)) {
return;
}
@ -586,7 +585,12 @@ void Subsystem::sendSerializablesAsCommandMessage(Command_t command, SerializeIF
return;
}
for (uint8_t i = 0; i < count; i++) {
elements[i]->serialize(&storeBuffer, &size, maxSize, SerializeIF::Endianness::BIG);
result = elements[i]->serialize(&storeBuffer, &size, maxSize, SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) {
replyToCommand(result, 0);
IPCStore->deleteData(address);
return;
}
}
CommandMessage reply;
ModeSequenceMessage::setModeSequenceMessage(&reply, command, address);

@ -9,7 +9,6 @@ class FixedTimeslotTaskBase : public FixedTimeslotTaskIF {
public:
explicit FixedTimeslotTaskBase(TaskPeriod period, TaskDeadlineMissedFunction dlmFunc = nullptr);
~FixedTimeslotTaskBase() override = default;
;
protected:
/**

@ -196,12 +196,11 @@ void Heater::setSwitch(uint8_t number, ReturnValue_t state, uint32_t* uptimeOfSw
if (powerSwitcher->getSwitchState(number) == state) {
*uptimeOfSwitching = INVALID_UPTIME;
} else {
if ((*uptimeOfSwitching == INVALID_UPTIME)) {
if (*uptimeOfSwitching == INVALID_UPTIME) {
powerSwitcher->sendSwitchCommand(number, state);
Clock::getUptime(uptimeOfSwitching);
*uptimeOfSwitching = Clock::getUptime_ms();
} else {
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
uint32_t currentUptime = Clock::getUptime_ms();
if (currentUptime - *uptimeOfSwitching > powerSwitcher->getSwitchDelayMs()) {
*uptimeOfSwitching = INVALID_UPTIME;
if (healthHelper.healthTable->isHealthy(getObjectId())) {

@ -552,10 +552,7 @@ ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const CCSDSTime::CDS_short*
if (to == nullptr or from == nullptr) {
return returnvalue::FAILED;
}
uint16_t days = (from->dayMSB << 8) + from->dayLSB;
if (days <= DAYS_CCSDS_TO_UNIX_EPOCH) {
return INVALID_TIME_FORMAT;
}
int32_t days = (from->dayMSB << 8) + from->dayLSB;
days -= DAYS_CCSDS_TO_UNIX_EPOCH;
to->tv_sec = days * SECONDS_PER_DAY;
uint32_t msDay =

@ -1,4 +1,9 @@
target_sources(
${LIB_FSFW_NAME}
PRIVATE CCSDSTime.cpp Countdown.cpp Stopwatch.cpp TimeMessage.cpp
CdsShortTimeStamper.cpp ClockCommon.cpp)
PRIVATE CCSDSTime.cpp
Countdown.cpp
Stopwatch.cpp
TimeMessage.cpp
CdsShortTimeStamper.cpp
ClockCommon.cpp
boost_timegm.cpp)

@ -4,8 +4,6 @@
#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,

@ -18,7 +18,6 @@
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.

@ -16,6 +16,7 @@
class Clock {
public:
// https://xkcd.com/927/
typedef struct {
uint32_t year; //!< Year, A.D.
uint32_t month; //!< Month, 1 .. 12.
@ -26,14 +27,6 @@ class Clock {
uint32_t usecond; //!< Microseconds, 0 .. 999999
} TimeOfDay_t;
/**
* This method returns the number of clock ticks per second.
* In RTEMS, this is typically 1000.
* @return The number of ticks.
*
* @deprecated, we should not worry about ticks, but only time
*/
static uint32_t getTicksPerSecond();
/**
* This system call sets the system time.
* To set the time, it uses a TimeOfDay_t struct.
@ -61,13 +54,8 @@ 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 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()
* @return a timeval struct where the uptime is stored
*/
static ReturnValue_t getUptime(timeval *uptime);
static timeval getUptime();
/**
@ -79,7 +67,7 @@ class Clock {
* @param ms uptime in ms
* @return returnvalue::OK on success. Otherwise, the OS failure code is returned.
*/
static ReturnValue_t getUptime(uint32_t *uptimeMs);
static uint32_t getUptime_ms();
/**
* Returns the time in microseconds since an OS-defined epoch.
@ -90,6 +78,7 @@ class Clock {
* - Otherwise, the OS failure code is returned.
*/
static ReturnValue_t getClock_usecs(uint64_t *time);
/**
* Returns the time in a TimeOfDay_t struct.
* @param time A pointer to a TimeOfDay_t struct.
@ -106,6 +95,7 @@ class Clock {
* @return
*/
static ReturnValue_t convertTimevalToTimeOfDay(const timeval *from, TimeOfDay_t *to);
/**
* Converts a time of day struct to POSIX seconds.
* @param time The time of day as input

@ -1,5 +1,7 @@
#include <cstdlib>
#include <ctime>
#include "boost_timegm.h"
#include "fsfw/ipc/MutexGuard.h"
#include "fsfw/timemanager/Clock.h"
@ -53,34 +55,58 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
}
ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* to) {
struct tm* timeInfo;
// According to https://en.cppreference.com/w/c/chrono/gmtime, the implementation of gmtime_s
// in the Windows CRT is incompatible with the C standard but this should not be an issue for
// this implementation
ReturnValue_t result = checkOrCreateClockMutex();
if (result != returnvalue::OK) {
return result;
struct tm time_tm;
// WINDOWS does not provide gmtime_r, but gmtime_s
#ifdef _MSC_VER
time_t seconds = from->tv_sec;
errno_t result = gmtime_s(&time_tm, &seconds);
if (result != 0) {
return returnvalue::FAILED;
}
// 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);
void* result = gmtime_r(&from->tv_sec, &time_tm);
if (result == nullptr) {
return returnvalue::FAILED;
}
#endif
to->year = timeInfo->tm_year + 1900;
to->month = timeInfo->tm_mon + 1;
to->day = timeInfo->tm_mday;
to->hour = timeInfo->tm_hour;
to->minute = timeInfo->tm_min;
to->second = timeInfo->tm_sec;
to->year = time_tm.tm_year + 1900;
to->month = time_tm.tm_mon + 1;
to->day = time_tm.tm_mday;
to->hour = time_tm.tm_hour;
to->minute = time_tm.tm_min;
to->second = time_tm.tm_sec;
to->usecond = from->tv_usec;
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
struct tm time_tm = {};
time_tm.tm_year = from->year - 1900;
time_tm.tm_mon = from->month - 1;
time_tm.tm_mday = from->day;
time_tm.tm_hour = from->hour;
time_tm.tm_min = from->minute;
time_tm.tm_sec = from->second;
time_tm.tm_isdst = 0;
time_t seconds = internal_timegm(&time_tm);
to->tv_sec = seconds;
to->tv_usec = from->usecond;
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
return returnvalue::OK;
}
ReturnValue_t Clock::checkOrCreateClockMutex() {
if (timeMutex == nullptr) {
MutexFactory* mutexFactory = MutexFactory::instance();
@ -94,3 +120,37 @@ ReturnValue_t Clock::checkOrCreateClockMutex() {
}
return returnvalue::OK;
}
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
timeval time_timeval;
ReturnValue_t result = getClock_timeval(&time_timeval);
if (result != returnvalue::OK) {
return result;
}
return convertTimevalToTimeOfDay(&time_timeval, time);
}
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval timeVal{};
ReturnValue_t result = getClock_timeval(&timeVal);
if (result != returnvalue::OK) {
return result;
}
*time = static_cast<uint64_t>(timeVal.tv_sec) * 1e6 + timeVal.tv_usec;
return returnvalue::OK;
}
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
timeval timeTimeval{};
ReturnValue_t result = convertTimeOfDayToTimeval(time, &timeTimeval);
if (result != returnvalue::OK) {
return result;
}
return setClock(&timeTimeval);
}
uint32_t Clock::getUptime_ms() {
timeval uptime = getUptime();
// TODO verify that overflow is correct
return uptime.tv_sec * 1e3 + uptime.tv_usec / 1e3;
}

@ -7,9 +7,9 @@ Countdown::Countdown(uint32_t initialTimeout) : timeout(initialTimeout) {
Countdown::~Countdown() {}
ReturnValue_t Countdown::setTimeout(uint32_t milliseconds) {
ReturnValue_t returnValue = Clock::getUptime(&startTime);
startTime = Clock::getUptime_ms();
timeout = milliseconds;
return returnValue;
return returnvalue::OK;
}
bool Countdown::hasTimedOut() const {
@ -38,8 +38,4 @@ uint32_t Countdown::getRemainingMillis() const {
}
}
uint32_t Countdown::getCurrentTime() const {
uint32_t currentTime;
Clock::getUptime(&currentTime);
return currentTime;
}
uint32_t Countdown::getCurrentTime() const { return Clock::getUptime_ms(); }

@ -9,10 +9,10 @@
Stopwatch::Stopwatch(bool displayOnDestruction, StopwatchDisplayMode displayMode)
: displayOnDestruction(displayOnDestruction), displayMode(displayMode) {
// Measures start time on initialization.
Clock::getUptime(&startTime);
startTime = Clock::getUptime();
}
void Stopwatch::start() { Clock::getUptime(&startTime); }
void Stopwatch::start() { startTime = Clock::getUptime(); }
dur_millis_t Stopwatch::stop(bool display) {
stopInternal();
@ -62,7 +62,6 @@ void Stopwatch::setDisplayMode(StopwatchDisplayMode displayMode) {
StopwatchDisplayMode Stopwatch::getDisplayMode() const { return displayMode; }
void Stopwatch::stopInternal() {
timeval endTime;
Clock::getUptime(&endTime);
timeval endTime = Clock::getUptime();
elapsedTime = endTime - startTime;
}

@ -3,12 +3,17 @@
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include "fsfw/platform.h"
#ifdef PLATFORM_WIN
// wtf? Required for timeval!
// Thanks, windows
// clang-format off
#include <winsock2.h>
#include <winsock.h>
// clang-format off
#endif
#include "TimeStampIF.h"

@ -0,0 +1,66 @@
// (C) Copyright Howard Hinnant
// (C) Copyright 2010-2011 Vicente J. Botet Escriba
// Use, modification and distribution are subject to 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).
//===-------------------------- locale ------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// This code was adapted by Vicente from Howard Hinnant's experimental work
// on chrono i/o to Boost and some functions from libc++/locale to emulate the missing
// time_get::get()
#include "boost_timegm.h"
#include <cstdint>
int32_t is_leap(int32_t year) {
if (year % 400 == 0) return 1;
if (year % 100 == 0) return 0;
if (year % 4 == 0) return 1;
return 0;
}
int32_t days_from_0(int32_t year) {
year--;
return 365 * year + (year / 400) - (year / 100) + (year / 4);
}
int32_t days_from_1970(int32_t year) {
static const int32_t days_from_0_to_1970 = days_from_0(1970);
return days_from_0(year) - days_from_0_to_1970;
}
int32_t days_from_1jan(int32_t year, int32_t month, int32_t day) {
static const int32_t days[2][12] = {{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}};
return days[is_leap(year)][month - 1] + day - 1;
}
time_t internal_timegm(std::tm const *t) {
int year = t->tm_year + 1900;
int month = t->tm_mon;
if (month > 11) {
year += month / 12;
month %= 12;
} else if (month < 0) {
int years_diff = (-month + 11) / 12;
year -= years_diff;
month += 12 * years_diff;
}
month++;
int day = t->tm_mday;
int day_of_year = days_from_1jan(year, month, day);
int days_since_epoch = days_from_1970(year) + day_of_year;
time_t seconds_in_day = 3600 * 24;
time_t result =
seconds_in_day * days_since_epoch + 3600 * t->tm_hour + 60 * t->tm_min + t->tm_sec;
return result;
}

@ -0,0 +1,3 @@
#include <ctime>
time_t internal_timegm(std::tm const *t);

@ -100,6 +100,5 @@ ReturnValue_t PusTcCreator::setSerializableUserData(const SerializeIF &serializa
void PusTcCreator::setup() {
spCreator.setPacketType(ccsds::PacketType::TC);
spCreator.setSecHeaderFlag();
spCreator.setSeqFlags(ccsds::SequenceFlags::UNSEGMENTED);
updateSpLengthField();
}

@ -119,7 +119,6 @@ void PusTmCreator::setup() {
updateSpLengthField();
spCreator.setPacketType(ccsds::PacketType::TM);
spCreator.setSecHeaderFlag();
spCreator.setSeqFlags(ccsds::SequenceFlags::UNSEGMENTED);
}
void PusTmCreator::setMessageTypeCounter(uint16_t messageTypeCounter) {

@ -348,7 +348,7 @@ void CommandingServiceBase::startExecution(store_address_t storeId, CommandMapIt
sendResult = commandQueue->sendMessage(iter.value->first, &command);
}
if (sendResult == returnvalue::OK) {
Clock::getUptime(&iter->second.uptimeOfStart);
iter->second.uptimeOfStart = Clock::getUptime_ms();
iter->second.step = 0;
iter->second.subservice = tcReader.getSubService();
iter->second.command = command.getCommand();
@ -434,8 +434,7 @@ inline void CommandingServiceBase::doPeriodicOperation() {}
MessageQueueId_t CommandingServiceBase::getCommandQueue() { return commandQueue->getId(); }
void CommandingServiceBase::checkTimeout() {
uint32_t uptime;
Clock::getUptime(&uptime);
uint32_t uptime = Clock::getUptime_ms();
CommandMapIter iter;
for (iter = commandMap.begin(); iter != commandMap.end(); ++iter) {
if ((iter->second.uptimeOfStart + (timeoutSeconds * 1000)) < uptime) {

@ -16,9 +16,7 @@ TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDes
tcDestination(tcDestination)
{
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(
TMTC_RECEPTION_QUEUE_DEPTH, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH);
}
TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); }
@ -37,7 +35,7 @@ ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle(uint8_t sentPacketsPerC
}
}
ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored) {
ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored) {
if (maxNumberOfPacketsStored <= LIMIT_DOWNLINK_PACKETS_STORED) {
this->maxNumberOfPacketsStored = maxNumberOfPacketsStored;
return returnvalue::OK;
@ -145,17 +143,13 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
#endif /* FSFW_VERBOSE_LEVEL >= 3 */
if (communicationLinkUp == false or packetSentCounter >= sentPacketsPerCycle) {
ReturnValue_t result = storeDownlinkData(&message);
if (result != returnvalue::OK) {
tmStore->deleteData(message.getStorageId());
}
storeDownlinkData(&message);
continue;
}
result = tmStore->getData(message.getStorageId(), &data, &size);
if (result != returnvalue::OK) {
status = result;
tmStore->deleteData(message.getStorageId());
continue;
}
@ -163,9 +157,9 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
if (result != returnvalue::OK) {
status = result;
} else {
tmStore->deleteData(message.getStorageId());
packetSentCounter++;
}
tmStore->deleteData(message.getStorageId());
}
return status;
}
@ -177,18 +171,15 @@ ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage* message) {
}
if (tmFifo->full()) {
if (warningSwitch) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number "
"of stored packet IDs reached!"
<< std::endl;
sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number "
"of stored packet IDs reached!"
<< std::endl;
#else
sif::printWarning(
"TmTcBridge::storeDownlinkData: TM downlink max. number "
"of stored packet IDs reached!\n");
sif::printWarning(
"TmTcBridge::storeDownlinkData: TM downlink max. number "
"of stored packet IDs reached!\n");
#endif
warningSwitch = false;
}
if (overwriteOld) {
tmFifo->retrieve(&storeId);
tmStore->deleteData(storeId);
@ -230,7 +221,6 @@ ReturnValue_t TmTcBridge::handleStoredTm() {
packetSentCounter++;
if (tmFifo->empty()) {
warningSwitch = true;
tmStored = false;
}
tmStore->deleteData(storeId);

@ -17,7 +17,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
public:
static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 500;
static constexpr uint8_t LIMIT_DOWNLINK_PACKETS_STORED = 200;
static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
@ -42,7 +42,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
* @return -@c returnvalue::OK if value was set successfully
* -@c returnvalue::FAILED otherwise, stored value stays the same
*/
ReturnValue_t setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored);
ReturnValue_t setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored);
/**
* This will set up the bridge to overwrite old data in the FIFO.
@ -91,7 +91,6 @@ 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;
@ -153,7 +152,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
*/
DynamicFIFO<store_address_t>* tmFifo = nullptr;
uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE;
unsigned int maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
};
#endif /* FSFW_TMTCSERVICES_TMTCBRIDGE_H_ */

@ -1,7 +1,7 @@
#include <stdbool.h>
#include <stdio.h>
void __attribute__((weak)) printChar(const char* character, bool errStream) {
void printChar(const char* character, bool errStream) {
if (errStream) {
fprintf(stderr, "%c", *character);
} else {

@ -72,7 +72,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
uint32_t transitionDelay;
// Single SPI command has 2 bytes, first for adress, second for content
size_t singleComandSize = 2;
// size_t singleComandSize = 2;
// Has the size for all adresses of the lis3mdl + the continous write bit
uint8_t commandBuffer[MGMLIS3MDL::NR_OF_DATA_AND_CFG_REGISTERS + 1];
@ -87,7 +87,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
*/
uint8_t registers[MGMLIS3MDL::NR_OF_CTRL_REGISTERS];
uint8_t statusRegister = 0;
// uint8_t statusRegister = 0;
bool goToNormalMode = false;
enum class InternalState {

@ -325,7 +325,7 @@ 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[9] << 8)) >> 8;
int32_t fieldStrengthRawZ = ((packet[7] << 24) | (packet[8] << 16) | (packet[3] << 8)) >> 8;
// Now scale to physical value in microtesla
float fieldStrengthX = fieldStrengthRawX * scaleFactorX;

@ -72,7 +72,7 @@ class MgmRM3100Handler : public DeviceHandlerBase {
RM3100::Rm3100PrimaryDataset primaryDataset;
uint8_t commandBuffer[10];
uint8_t commandBufferLen = 0;
// uint8_t commandBufferLen = 0;
uint8_t cmmRegValue = RM3100::CMM_VALUE;
uint8_t tmrcRegValue = RM3100::TMRC_DEFAULT_VALUE;

@ -67,7 +67,7 @@ void CommandExecutor::printLastError(std::string funcName) const {
sif::warning << funcName << " pclose failed with code " << lastError << ": "
<< strerror(lastError) << std::endl;
#else
sif::printError("%s pclose failed with code %d: %s\n", funcName, lastError,
sif::printError("%s pclose failed with code %d: %s\n", funcName.c_str(), lastError,
strerror(lastError));
#endif
}
@ -119,7 +119,7 @@ ReturnValue_t CommandExecutor::check(bool& replyReceived) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << currentCmd << " | " << readVec.data();
#else
sif::printInfo("%s | %s", currentCmd, readVec.data());
sif::printInfo("%s | %s", currentCmd.c_str(), readVec.data());
#endif
}
if (ringBuffer != nullptr) {
@ -188,7 +188,7 @@ ReturnValue_t CommandExecutor::executeBlocking() {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << currentCmd << " | " << output;
#else
sif::printInfo("%s | %s", currentCmd, output);
sif::printInfo("%s | %s", currentCmd.c_str(), output.c_str());
#endif
}
if (ringBuffer != nullptr) {

@ -180,6 +180,10 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe
}
#else
#endif
#endif
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "I2cComIF::requestReceiveMessage: Read " << readLen << " of " << requestLen
<< " bytes" << std::endl;
#endif
return returnvalue::FAILED;
}

@ -146,8 +146,9 @@ ReturnValue_t testserialize::test_autoserialization() {
}
// These epsilon values were just guessed.. It appears to work though.
if (abs(tv_float - tv::tv_float) > 0.0001 or abs(tv_double - tv::tv_double) > 0.01 or
abs(tv_sfloat - tv::tv_sfloat) > 0.0001 or abs(tv_sdouble - tv::tv_sdouble) > 0.01) {
if (std::abs(tv_float - tv::tv_float) > 0.0001 or std::abs(tv_double - tv::tv_double) > 0.01 or
std::abs(tv_sfloat - tv::tv_sfloat) > 0.0001 or
std::abs(tv_sdouble - tv::tv_sdouble) > 0.01) {
return unitt::put_error(id);
}

Some files were not shown because too many files have changed in this diff Show More