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
124 changed files with 1107 additions and 1009 deletions

3
.gitmodules vendored
View File

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

View File

@ -12,26 +12,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Fixes ## Fixes
- Bugfix in `Service11TelecommandScheduling` which allowed commands
time tagged in the past to be inserted.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/738
- `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.
- 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
- Bugfix for RM3100 MGM sensors. Z value was previously calculated
with bytes of the X value.
- DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity
to false correctly because the `read` and `write` calls were missing.
- PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead
of the correct unsegmented flags (0b11) as specified in the standard.
- TC Scheduler Service 11: Add size and CRC check for contained TC. - TC Scheduler Service 11: Add size and CRC check for contained TC.
- Only delete health table entry in `HealthHelper` destructor if - Only delete health table entry in `HealthHelper` destructor if
health table was set. health table was set.
@ -48,13 +28,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Added ## 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. - `DleParser` helper class to parse DLE encoded packets from a byte stream.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/711 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/711
- `UioMapper` is able to resolve symlinks now. - `UioMapper` is able to resolve symlinks now.

View File

@ -64,6 +64,12 @@ elseif(${CMAKE_CXX_STANDARD} LESS 17)
"${MSG_PREFIX} Compiling the FSFW requires a minimum of C++17 support") "${MSG_PREFIX} Compiling the FSFW requires a minimum of C++17 support")
endif() 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_SOURCES_DIR "${CMAKE_SOURCE_DIR}/src/fsfw")
set(FSFW_ETL_LIB_NAME etl) set(FSFW_ETL_LIB_NAME etl)
@ -158,7 +164,7 @@ if(FSFW_BUILD_TESTS)
if(NOT Catch2_FOUND) if(NOT Catch2_FOUND)
message( message(
STATUS 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) include(FetchContent)
@ -174,6 +180,27 @@ if(FSFW_BUILD_TESTS)
configure_file(unittests/testcfg/FSFWConfig.h.in FSFWConfig.h) configure_file(unittests/testcfg/FSFWConfig.h.in FSFWConfig.h)
configure_file(unittests/testcfg/TestsConfig.h.in tests/TestsConfig.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) project(${FSFW_TEST_TGT} CXX C)
add_executable(${FSFW_TEST_TGT}) add_executable(${FSFW_TEST_TGT})
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO) 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) if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
message( message(
STATUS 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) include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
@ -226,6 +253,7 @@ if(FSFW_FETCH_CONTENT_TARGETS)
# GitHub issue: https://github.com/catchorg/Catch2/issues/2417 # GitHub issue: https://github.com/catchorg/Catch2/issues/2417
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "") set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
endif() endif()
endif() endif()
set(FSFW_CORE_INC_PATH "inc") set(FSFW_CORE_INC_PATH "inc")
@ -360,6 +388,9 @@ if(FSFW_BUILD_TESTS)
endif() endif()
target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2 target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2
${LIB_FSFW_NAME}) ${LIB_FSFW_NAME})
if(FSFW_OSAL MATCHES "freertos")
target_link_libraries(${FSFW_TEST_TGT} PRIVATE FreeRTOS)
endif()
endif() endif()
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. If # 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() endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(COMPILER_FLAGS "/permissive-") set(FSFW_WARNING_FLAGS -Wall -Wno-gnu-anonymous-struct)
endif() endif()
# Required include paths to compile the FSFW # Required include paths to compile the FSFW

View File

@ -5,7 +5,7 @@ RUN apt-get --yes upgrade
#tzdata is a dependency, won't install otherwise #tzdata is a dependency, won't install otherwise
ARG DEBIAN_FRONTEND=noninteractive 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 RUN python3 -m pip install sphinx breathe
@ -21,8 +21,27 @@ RUN git clone https://github.com/ETLCPP/etl.git && \
cmake -B build . && \ cmake -B build . && \
cmake --install 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 #ssh needs a valid user to work
RUN adduser --uid 114 jenkins RUN adduser -q --uid 114 jenkins
#add documentation server to known hosts #add documentation server to known hosts
RUN echo "|1|/LzCV4BuTmTb2wKnD146l9fTKgQ=|NJJtVjvWbtRt8OYqFgcYRnMQyVw= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts RUN echo "|1|/LzCV4BuTmTb2wKnD146l9fTKgQ=|NJJtVjvWbtRt8OYqFgcYRnMQyVw= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts

105
automation/Jenkinsfile vendored
View File

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

1
automation/msvc-wine Submodule

Submodule automation/msvc-wine added at 2d2d7db0b5

View File

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

View File

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

View File

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

View File

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

View File

@ -42,6 +42,6 @@ size_t EofInfo::getSerializedSize(bool fssLarge) {
return size; 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); return this->fileSize.setFileSize(fileSize, isLarge);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 FSFW_CPP_OSTREAM_ENABLED == 1
if (sif::info.crAdditionEnabled()) { if (sif::info.crAdditionEnabled()) {
std::cout << "\r" << std::endl; std::cout << "\r" << std::endl;
} }
std::cout << "hex [" << std::setfill('0') << std::hex; 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]); std::cout << std::setw(2) << static_cast<int>(data[i]);
if (i < size - 1) { if (i < datasize - 1) {
std::cout << ","; std::cout << ",";
if (i > 0 and (i + 1) % maxCharPerLine == 0) { if (i > 0 and (i + 1) % maxCharPerLine == 0) {
std::cout << std::endl; 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::dec << std::setfill(' ');
std::cout << "]" << std::endl; std::cout << "]" << std::endl;
#else #else
// General format: 0x01, 0x02, 0x03 so it is number of chars times 6 printf("hex [");
// plus line break plus small safety margin. for (size_t i = 0; i < datasize; i++) {
char printBuffer[(size + 1) * 7 + 1] = {}; printf("0x%02x ", data[i]);
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");
}
}
} }
#if FSFW_DISABLE_PRINTOUT == 0 printf("]\n");
printf("hex [%s]\n", printBuffer);
#endif /* FSFW_DISABLE_PRINTOUT == 0 */
#endif #endif
} }
@ -100,26 +84,10 @@ void arrayprinter::printDec(const uint8_t *data, size_t size, size_t maxCharPerL
#else #else
// General format: 32,243,-12 so it is number of chars times 4 // General format: 32,243,-12 so it is number of chars times 4
// plus line break plus small safety margin. // 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]); for (size_t i = 0; i < size; i++) {
if (i < size - 1) { // TODO
currentPos += sprintf(printBuffer + currentPos, ",");
if ((i + 1) % maxCharPerLine == 0) {
currentPos += sprintf(printBuffer + currentPos, "\n");
}
}
} }
#if FSFW_DISABLE_PRINTOUT == 0
printf("dec [%s]\n", printBuffer);
#endif /* FSFW_DISABLE_PRINTOUT == 0 */
#endif #endif
} }

View File

@ -16,24 +16,26 @@ class HasHealthIF {
}; };
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF; static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
static constexpr ReturnValue_t OBJECT_NOT_HEALTHY = returnvalue::makeCode(INTERFACE_ID, 1); static const ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1);
static constexpr ReturnValue_t INVALID_HEALTH_STATE = returnvalue::makeCode(INTERFACE_ID, 2); static const ReturnValue_t INVALID_HEALTH_STATE = MAKE_RETURN_CODE(2);
static constexpr ReturnValue_t IS_EXTERNALLY_CONTROLLED = returnvalue::makeCode(INTERFACE_ID, 3);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER_1; 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 HEALTH_INFO = MAKE_EVENT(6, severity::INFO);
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO); static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO);
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW); static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW);
//! Assembly overwrites health information of children to keep satellite alive. static const Event OVERWRITING_HEALTH =
static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, severity::LOW); MAKE_EVENT(9, severity::LOW); //!< Assembly overwrites health information of children to keep
//! Someone starts a recovery of a component (typically power-cycle). No parameters. //!< satellite alive.
static const Event TRYING_RECOVERY = MAKE_EVENT(10, severity::MEDIUM); static const Event TRYING_RECOVERY =
//! Recovery is ongoing. Comes twice during recovery. MAKE_EVENT(10, severity::MEDIUM); //!< Someone starts a recovery of a component (typically
//! P1: 0 for the first, 1 for the second event. P2: 0 //!< power-cycle). No parameters.
static const Event RECOVERY_STEP = MAKE_EVENT(11, severity::MEDIUM); static const Event RECOVERY_STEP =
//! Recovery was completed. Not necessarily successful. No parameters. MAKE_EVENT(11, severity::MEDIUM); //!< Recovery is ongoing. Comes twice during recovery. P1:
static const Event RECOVERY_DONE = MAKE_EVENT(12, severity::MEDIUM); //!< 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 ~HasHealthIF() {}
virtual MessageQueueId_t getCommandQueue() const = 0; virtual MessageQueueId_t getCommandQueue() const = 0;

View File

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

View File

@ -7,10 +7,10 @@
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth) InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
: SystemObject(setObjectId), : SystemObject(setObjectId),
commandQueue(QueueFactory::instance()->createMessageQueue(messageQueueDepth)),
poolManager(this, commandQueue), poolManager(this, commandQueue),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID), internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) { internalErrorDataset(this) {
commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
} }

View File

@ -24,19 +24,3 @@ void ModeMessage::setCantReachMode(CommandMessage* message, ReturnValue_t reason
message->setParameter(reason); message->setParameter(reason);
message->setParameter2(0); 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); }

View File

@ -45,9 +45,6 @@ class ModeMessage {
static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode, static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode,
Submode_t submode); 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 setCantReachMode(CommandMessage* message, ReturnValue_t reason);
static void clear(CommandMessage* message); static void clear(CommandMessage* message);
}; };

View File

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

View File

@ -18,10 +18,7 @@ elseif(FSFW_OSAL MATCHES "host")
endif() endif()
set(FSFW_OSAL_HOST 1) set(FSFW_OSAL_HOST 1)
else() else()
message( message(WARNING "The OS_FSFW variable was not set. Assuming host OS..")
WARNING
"${MSG_PREFIX} The FSFW_OSAL variable was not set. Assuming host OS..")
# Not set. Assumuing this is a host build, try to determine host OS # Not set. Assumuing this is a host build, try to determine host OS
if(WIN32) if(WIN32)
add_subdirectory(host) add_subdirectory(host)

View File

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

View File

@ -16,7 +16,7 @@
#ifdef PLATFORM_WIN #ifdef PLATFORM_WIN
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> typedef SSIZE_T ssize_t;
#elif defined(PLATFORM_UNIX) #elif defined(PLATFORM_UNIX)
#include <netdb.h> #include <netdb.h>
@ -26,12 +26,12 @@
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT; const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge, TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
TcpTmTcServer::TcpConfig cfg, size_t receptionBufferSize, size_t receptionBufferSize, size_t ringBufferSize,
size_t ringBufferSize, ReceptionModes receptionMode) std::string customTcpServerPort, ReceptionModes receptionMode)
: SystemObject(objectId), : SystemObject(objectId),
tmtcBridgeId(tmtcTcpBridge), tmtcBridgeId(tmtcTcpBridge),
receptionMode(receptionMode), receptionMode(receptionMode),
tcpConfig(cfg), tcpConfig(std::move(customTcpServerPort)),
receptionBuffer(receptionBufferSize), receptionBuffer(receptionBufferSize),
ringBuffer(ringBufferSize, true) {} ringBuffer(ringBufferSize, true) {}
@ -91,15 +91,6 @@ ReturnValue_t TcpTmTcServer::initialize() {
return returnvalue::FAILED; return returnvalue::FAILED;
} }
if (tcpConfig.reuseAddr) {
unsigned int enable = 1;
setsockopt(listenerTcpSocket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
}
if (tcpConfig.reusePort) {
unsigned int enable = 1;
setsockopt(listenerTcpSocket, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable));
}
// Bind to the address found by getaddrinfo // Bind to the address found by getaddrinfo
retval = bind(listenerTcpSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen)); retval = bind(listenerTcpSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen));
if (retval == SOCKET_ERROR) { if (retval == SOCKET_ERROR) {

View File

@ -41,11 +41,11 @@ class SpacePacketParser;
*/ */
class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableObjectIF { class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableObjectIF {
public: public:
enum class ReceptionModes { SPACE_PACKETS };
struct TcpConfig { struct TcpConfig {
public: public:
TcpConfig(bool reuseAddr, bool reusePort) : reuseAddr(reuseAddr), reusePort(reusePort) {} explicit TcpConfig(std::string tcpPort) : tcpPort(std::move(tcpPort)) {}
TcpConfig(std::string tcpPort, bool reuseAddr, bool reusePort)
: tcpPort(std::move(tcpPort)), reuseAddr(reuseAddr), reusePort(reusePort) {}
/** /**
* Passed to the recv call * Passed to the recv call
@ -63,24 +63,8 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
*/ */
int tcpTmFlags = 0; int tcpTmFlags = 0;
std::string tcpPort = DEFAULT_SERVER_PORT; const std::string tcpPort;
/**
* Sets the SO_REUSEADDR option on the socket. See
* https://man7.org/linux/man-pages/man7/socket.7.html for more details. This option is
* especially useful in a debugging and development environment where an OBSW image might be
* re-flashed oftentimes and where all incoming telecommands are received on a dedicated TCP
* port.
*/
bool reuseAddr = false;
/**
* Sets the SO_REUSEPORT option on the socket. See
* https://man7.org/linux/man-pages/man7/socket.7.html for more details.
*/
bool reusePort = false;
}; };
enum class ReceptionModes { SPACE_PACKETS };
static const std::string DEFAULT_SERVER_PORT; static const std::string DEFAULT_SERVER_PORT;
@ -96,9 +80,10 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
* size will be the Ethernet MTU size * size will be the Ethernet MTU size
* @param customTcpServerPort The user can specify another port than the default (7301) here. * @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 receptionBufferSize = RING_BUFFER_SIZE,
size_t ringBufferSize = RING_BUFFER_SIZE, size_t ringBufferSize = RING_BUFFER_SIZE,
std::string customTcpServerPort = DEFAULT_SERVER_PORT,
ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS); ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS);
~TcpTmTcServer() override; ~TcpTmTcServer() override;
@ -131,7 +116,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
ReceptionModes receptionMode; ReceptionModes receptionMode;
TcpConfig tcpConfig; TcpConfig tcpConfig;
struct sockaddr tcpAddress = {}; // struct sockaddr tcpAddress = {};
socket_t listenerTcpSocket = 0; socket_t listenerTcpSocket = 0;
MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE; MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE;

View File

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

View File

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

View File

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

View File

@ -51,7 +51,7 @@ class BinarySemaphore : public SemaphoreIF {
* -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/ */
ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, 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. * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks.

View File

@ -11,19 +11,6 @@
// TODO sanitize input? // TODO sanitize input?
// TODO much of this code can be reused for tick-only systems // 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) { ReturnValue_t Clock::setClock(const timeval* time) {
timeval uptime = getUptime(); timeval uptime = getUptime();
@ -44,81 +31,12 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t Clock::getUptime(timeval* uptime) {
*uptime = getUptime();
return returnvalue::OK;
}
timeval Clock::getUptime() { timeval Clock::getUptime() {
TickType_t ticksSinceStart = xTaskGetTickCount(); TickType_t ticksSinceStart = xTaskGetTickCount();
return Timekeeper::ticksToTimeval(ticksSinceStart); 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() { // uint32_t Clock::getUptimeSeconds() {
// timeval uptime = getUptime(); // timeval uptime = getUptime();
// return uptime.tv_sec; // 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;
}

View File

@ -34,7 +34,7 @@ class CountingSemaphoreUsingTask : public SemaphoreIF {
* -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/ */
ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, 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 * Release a semaphore, increasing the number of available counting

View File

@ -56,7 +56,9 @@ ReturnValue_t FixedTimeslotTask::startTask() {
// start time for the first entry. // start time for the first entry.
auto slotListIter = pollingSeqTable.current; 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. // The start time for the first entry is read.
uint32_t intervalMs = slotListIter->pollingTimeMs; uint32_t intervalMs = slotListIter->pollingTimeMs;

View File

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

View File

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

View File

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

View File

@ -15,27 +15,6 @@
using SystemClock = std::chrono::system_clock; 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) { 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 /* 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. */ 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; time->tv_usec = timeUnix.tv_nsec / 1000.0;
return returnvalue::OK; return returnvalue::OK;
#else #else
#warning Clock::getClock_timeval() not implemented for your platform
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl; sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl;
#else #else
@ -75,15 +55,6 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
#endif #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 Clock::getUptime() {
timeval timeval; timeval timeval;
#if defined(PLATFORM_WIN) #if defined(PLATFORM_WIN)
@ -100,73 +71,10 @@ timeval Clock::getUptime() {
timeval.tv_usec = uptimeSeconds * (double)1e6 - (timeval.tv_sec * 1e6); timeval.tv_usec = uptimeSeconds * (double)1e6 - (timeval.tv_sec * 1e6);
} }
#else #else
#warning Clock::getUptime() not implemented for your platform
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
#endif #endif
#endif #endif
return timeval; 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;
}

View File

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

View File

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

View File

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

View File

@ -10,26 +10,6 @@
#include "fsfw/ipc/MutexGuard.h" #include "fsfw/ipc/MutexGuard.h"
#include "fsfw/serviceinterface/ServiceInterface.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) { ReturnValue_t Clock::setClock(const timeval* time) {
timespec timeUnix{}; timespec timeUnix{};
timeUnix.tv_sec = time->tv_sec; timeUnix.tv_sec = time->tv_sec;
@ -53,104 +33,12 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
return returnvalue::OK; 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 Clock::getUptime() {
timeval uptime{}; timeval uptime{0, 0};
auto result = getUptime(&uptime); double uptimeSeconds;
if (result != returnvalue::OK) { if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 uptime.tv_sec = uptimeSeconds;
sif::error << "Clock::getUptime: Error getting uptime" << std::endl; uptime.tv_usec = uptimeSeconds * (double)1e6 - (uptime.tv_sec * 1e6);
#endif
} }
return uptime; 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;
}

View File

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

View File

@ -6,20 +6,21 @@
#include "fsfw/ipc/MutexGuard.h" #include "fsfw/ipc/MutexGuard.h"
#include "fsfw/osal/rtems/RtemsBasic.h" #include "fsfw/osal/rtems/RtemsBasic.h"
uint32_t Clock::getTicksPerSecond(void) { ReturnValue_t Clock::setClock(const timeval* time) {
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second(); TimeOfDay_t time_tod;
return static_cast<uint32_t>(ticks_per_second); ReturnValue_t result = convertTimevalToTimeOfDay(time, &time_tod);
} if (result != returnvalue::OK) {
return result;
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { }
rtems_time_of_day timeRtems; rtems_time_of_day timeRtems;
timeRtems.year = time->year; timeRtems.year = time_tod.year;
timeRtems.month = time->month; timeRtems.month = time_tod.month;
timeRtems.day = time->day; timeRtems.day = time_tod.day;
timeRtems.hour = time->hour; timeRtems.hour = time_tod.hour;
timeRtems.minute = time->minute; timeRtems.minute = time_tod.minute;
timeRtems.second = time->second; timeRtems.second = time_tod.second;
timeRtems.ticks = time->usecond * getTicksPerSecond() / 1e6; timeRtems.ticks =
static_cast<uint64_t>(time_tod.usecond) * rtems_clock_get_ticks_per_second() / 1e6;
rtems_status_code status = rtems_clock_set(&timeRtems); rtems_status_code status = rtems_clock_set(&timeRtems);
switch (status) { switch (status) {
case RTEMS_SUCCESSFUL: 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) { ReturnValue_t Clock::getClock_timeval(timeval* time) {
// Callable from ISR // Callable from ISR
rtems_status_code status = rtems_clock_get_tod_timeval(time); 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 // According to docs.rtems.org for rtems 5 this method is more accurate than
// rtems_clock_get_ticks_since_boot // rtems_clock_get_ticks_since_boot
timeval time_timeval;
timespec time; timespec time;
rtems_status_code status = rtems_clock_get_uptime(&time); rtems_status_code status = rtems_clock_get_uptime(&time);
uptime->tv_sec = time.tv_sec; time_timeval.tv_sec = time.tv_sec;
time.tv_nsec = time.tv_nsec / 1000; time_timeval.tv_usec = time.tv_nsec / 1000;
uptime->tv_usec = time.tv_nsec; return time_timeval;
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;
} }

View File

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

View File

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

View File

@ -1,5 +1,5 @@
#include "fsfw/osal/rtems/BinarySemaphore.h" #include "fsfw/osal/rtems/BinarySemaphore.h"
//#include "fsfw/osal/rtems/CountingSemaphore.h" // #include "fsfw/osal/rtems/CountingSemaphore.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/tasks/SemaphoreFactory.h" #include "fsfw/tasks/SemaphoreFactory.h"
@ -18,7 +18,9 @@ SemaphoreFactory* SemaphoreFactory::instance() {
} }
SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) { SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) {
return new BinarySemaphore(); return nullptr;
// TODO
// return new BinarySemaphore();
} }
SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount, uint8_t initCount, SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount, uint8_t initCount,

View File

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

View File

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

View File

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

View File

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

View File

@ -19,7 +19,7 @@ ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) {
switch (subservice) { switch (subservice) {
case (Subservice::COMMAND_MODE_COMMAND): case (Subservice::COMMAND_MODE_COMMAND):
case (Subservice::COMMAND_MODE_READ): case (Subservice::COMMAND_MODE_READ):
case (Subservice::COMMAND_MODE_ANNOUNCE): case (Subservice::COMMAND_MODE_ANNCOUNCE):
return returnvalue::OK; return returnvalue::OK;
default: default:
return AcceptsTelecommandsIF::INVALID_SUBSERVICE; return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
@ -53,32 +53,16 @@ ReturnValue_t CService200ModeCommanding::checkInterfaceAndAcquireMessageQueue(
ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message, uint8_t subservice, ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
const uint8_t *tcData, size_t tcDataLen, const uint8_t *tcData, size_t tcDataLen,
uint32_t *state, object_id_t objectId) { uint32_t *state, object_id_t objectId) {
bool recursive = false; ModePacket modeCommandPacket;
switch (subservice) { ReturnValue_t result =
case (Subservice::COMMAND_MODE_COMMAND): { modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
ModePacket modeCommandPacket; if (result != returnvalue::OK) {
ReturnValue_t result = return 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;
} }
ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(),
modeCommandPacket.getSubmode());
return result;
} }
ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply, ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply,
@ -89,10 +73,8 @@ ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply
ReturnValue_t result = returnvalue::FAILED; ReturnValue_t result = returnvalue::FAILED;
switch (replyId) { switch (replyId) {
case (ModeMessage::REPLY_MODE_REPLY): { case (ModeMessage::REPLY_MODE_REPLY): {
if (previousCommand != ModeMessage::CMD_MODE_COMMAND) { result = prepareModeReply(reply, objectId);
return prepareModeReply(reply, objectId); break;
}
return returnvalue::OK;
} }
case (ModeMessage::REPLY_WRONG_MODE_REPLY): { case (ModeMessage::REPLY_WRONG_MODE_REPLY): {
result = prepareWrongModeReply(reply, objectId); result = prepareWrongModeReply(reply, objectId);

View File

@ -52,7 +52,7 @@ class CService200ModeCommanding : public CommandingServiceBase {
COMMAND_MODE_READ = 3, COMMAND_MODE_READ = 3,
//!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event. //!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event.
//! This command does NOT have a reply //! 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 //!< [EXPORT] : [COMMAND] Trigger a ModeInfo Event and to send this
//! command to every child. This command does NOT have a reply. //! command to every child. This command does NOT have a reply.
COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5, COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5,

View File

@ -2,12 +2,12 @@
#include <cstddef> #include <cstddef>
#include "fsfw/globalfunctions/CRC.h"
#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serialize/SerializeAdapter.h" #include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/serviceinterface.h" #include "fsfw/serviceinterface.h"
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
#include "fsfw/tmtcpacket/pus/tc/PusTcIF.h" #include "fsfw/tmtcpacket/pus/tc/PusTcIF.h"
#include "fsfw/globalfunctions/CRC.h" #include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
static constexpr auto DEF_END = SerializeIF::Endianness::BIG; static constexpr auto DEF_END = SerializeIF::Endianness::BIG;
@ -160,7 +160,7 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivi
// (See requirement for Time margin) // (See requirement for Time margin)
timeval tNow = {}; timeval tNow = {};
Clock::getClock_timeval(&tNow); Clock::getClock_timeval(&tNow);
if (timestamp < tNow.tv_sec + RELEASE_TIME_MARGIN_SECONDS) { if (timestamp - tNow.tv_sec <= RELEASE_TIME_MARGIN_SECONDS) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Service11TelecommandScheduling::doInsertActivity: Release time too close to " sif::warning << "Service11TelecommandScheduling::doInsertActivity: Release time too close to "
"current time" "current time"

View File

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

View File

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

View File

@ -69,14 +69,14 @@ ReturnValue_t Service20ParameterManagement::checkInterfaceAndAcquireMessageQueue
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Service20ParameterManagement::checkInterfaceAndAcquire" sif::error << "Service20ParameterManagement::checkInterfaceAndAcquire"
<< "MessageQueue: Can't access object" << std::endl; << "MessageQueue: Can't access object" << std::endl;
sif::error << "Object ID: 0x" << std::hex << *objectId << std::dec << std::endl; sif::error << "Object ID: " << std::hex << objectId << std::dec << std::endl;
sif::error << "Make sure it implements ReceivesParameterMessagesIF" << std::endl; sif::error << "Make sure it implements ReceivesParameterMessagesIF!" << std::endl;
#else #else
sif::printError( sif::printError(
"Service20ParameterManagement::checkInterfaceAndAcquire" "Service20ParameterManagement::checkInterfaceAndAcquire"
"MessageQueue: Can't access object\n"); "MessageQueue: Can't access object\n");
sif::printError("Object ID: 0x%08x\n", *objectId); 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 #endif
return CommandingServiceBase::INVALID_OBJECT; return CommandingServiceBase::INVALID_OBJECT;

View File

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

View File

@ -6,13 +6,10 @@
class Service9TimeManagement : public PusServiceBase { class Service9TimeManagement : public PusServiceBase {
public: public:
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9; static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
static constexpr Event CLOCK_SET =
//!< Clock has been set. P1: old timeval seconds. P2: new timeval seconds. MAKE_EVENT(0, severity::INFO); //!< Clock has been set. P1: New Uptime. P2: Old Uptime
static constexpr Event CLOCK_SET = MAKE_EVENT(0, severity::INFO); static constexpr Event CLOCK_SET_FAILURE =
//!< Clock dump event. P1: timeval seconds P2: timeval milliseconds. MAKE_EVENT(1, severity::LOW); //!< Clock could not be set. P1: Returncode.
static constexpr Event CLOCK_DUMP = MAKE_EVENT(1, severity::INFO);
//!< Clock could not be set. P1: Returncode.
static constexpr Event CLOCK_SET_FAILURE = MAKE_EVENT(2, severity::LOW);
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9; static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;
@ -33,9 +30,8 @@ class Service9TimeManagement : public PusServiceBase {
virtual ReturnValue_t setTime(); virtual ReturnValue_t setTime();
private: private:
enum Subservice { enum SUBSERVICE {
SET_TIME = 128, //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format SET_TIME = 128 //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format
DUMP_TIME = 129,
}; };
}; };

View File

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

View File

@ -10,11 +10,11 @@
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
// RMAP command bits // RMAP command bits
//#define RMAP_COMMAND_BIT_INCREMENT 2 // #define RMAP_COMMAND_BIT_INCREMENT 2
//#define RMAP_COMMAND_BIT_REPLY 3 // #define RMAP_COMMAND_BIT_REPLY 3
//#define RMAP_COMMAND_BIT_WRITE 5 // #define RMAP_COMMAND_BIT_WRITE 5
//#define RMAP_COMMAND_BIT_VERIFY 4 // #define RMAP_COMMAND_BIT_VERIFY 4
//#define RMAP_COMMAND_BIT 6 // #define RMAP_COMMAND_BIT 6
namespace RMAPIds { namespace RMAPIds {
@ -32,14 +32,14 @@ static const uint8_t RMAP_COMMAND_READ = ((1 << RMAP_COMMAND_BIT) | (1 << RMAP_C
static const uint8_t RMAP_REPLY_WRITE = static const uint8_t RMAP_REPLY_WRITE =
((1 << RMAP_COMMAND_BIT_WRITE) | (1 << RMAP_COMMAND_BIT_REPLY)); ((1 << RMAP_COMMAND_BIT_WRITE) | (1 << RMAP_COMMAND_BIT_REPLY));
static const uint8_t RMAP_REPLY_READ = ((1 << RMAP_COMMAND_BIT_REPLY)); static const uint8_t RMAP_REPLY_READ = ((1 << RMAP_COMMAND_BIT_REPLY));
//#define RMAP_COMMAND_WRITE ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE) // #define RMAP_COMMAND_WRITE ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE)
//| (1<<RMAP_COMMAND_BIT_REPLY)) #define RMAP_COMMAND_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT) | //| (1<<RMAP_COMMAND_BIT_REPLY)) #define RMAP_COMMAND_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT) |
//(1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY)) #define //(1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY)) #define
// RMAP_COMMAND_READ ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_REPLY)) // RMAP_COMMAND_READ ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_REPLY))
//#define RMAP_REPLY_WRITE ((1<<RMAP_COMMAND_BIT_WRITE) | // #define RMAP_REPLY_WRITE ((1<<RMAP_COMMAND_BIT_WRITE) |
//(1<<RMAP_COMMAND_BIT_REPLY)) //(1<<RMAP_COMMAND_BIT_REPLY))
//#define RMAP_REPLY_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT_WRITE) | // #define RMAP_REPLY_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT_WRITE) |
//(1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY)) #define RMAP_REPLY_READ //(1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY)) #define RMAP_REPLY_READ
//((1<<RMAP_COMMAND_BIT_REPLY)) //((1<<RMAP_COMMAND_BIT_REPLY))
@ -49,9 +49,9 @@ static const uint8_t RMAP_COMMAND_HEADER_LEN = 16;
static const uint8_t RMAP_WRITE_REPLY_HEADER_LEN = 8; static const uint8_t RMAP_WRITE_REPLY_HEADER_LEN = 8;
static const uint8_t RMAP_READ_REPLY_HEADER_LEN = 12; static const uint8_t RMAP_READ_REPLY_HEADER_LEN = 12;
static const uint8_t RMAP_DATA_FOOTER_SIZE = 1; // SIZE OF CRC static const uint8_t RMAP_DATA_FOOTER_SIZE = 1; // SIZE OF CRC
//#define RMAP_COMMAND_HEADER_LEN 16 // #define RMAP_COMMAND_HEADER_LEN 16
//#define RMAP_WRITE_REPLY_HEADER_LEN 8 // #define RMAP_WRITE_REPLY_HEADER_LEN 8
//#define RMAP_READ_REPLY_HEADER_LEN 12 // #define RMAP_READ_REPLY_HEADER_LEN 12
} // namespace RMAPIds } // namespace RMAPIds

View File

@ -33,7 +33,7 @@
* @author baetz * @author baetz
* @ingroup serialize * @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 { class SerialLinkedListAdapter : public SinglyLinkedList<T>, public SerializeIF {
public: public:
SerialLinkedListAdapter(typename LinkedElement<T>::Iterator start, bool printCount = false) SerialLinkedListAdapter(typename LinkedElement<T>::Iterator start, bool printCount = false)

View File

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

View File

@ -91,11 +91,10 @@ void Subsystem::performChildOperation() {
} }
if (currentSequenceIterator->getWaitSeconds() != 0) { if (currentSequenceIterator->getWaitSeconds() != 0) {
if (uptimeStartTable == 0) { if (uptimeStartTable == 0) {
Clock::getUptime(&uptimeStartTable); uptimeStartTable = Clock::getUptime_ms();
return; return;
} else { } else {
uint32_t uptimeNow; uint32_t uptimeNow = Clock::getUptime_ms();
Clock::getUptime(&uptimeNow);
if ((uptimeNow - uptimeStartTable) < (currentSequenceIterator->getWaitSeconds() * 1000)) { if ((uptimeNow - uptimeStartTable) < (currentSequenceIterator->getWaitSeconds() * 1000)) {
return; return;
} }
@ -586,7 +585,12 @@ void Subsystem::sendSerializablesAsCommandMessage(Command_t command, SerializeIF
return; return;
} }
for (uint8_t i = 0; i < count; i++) { 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; CommandMessage reply;
ModeSequenceMessage::setModeSequenceMessage(&reply, command, address); ModeSequenceMessage::setModeSequenceMessage(&reply, command, address);

View File

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

View File

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

View File

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

View File

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

View File

@ -4,8 +4,6 @@
#include "fsfw/timemanager/Clock.h" #include "fsfw/timemanager/Clock.h"
CdsShortTimeStamper::CdsShortTimeStamper() : SystemObject(0, false) {}
CdsShortTimeStamper::CdsShortTimeStamper(object_id_t objectId) : SystemObject(objectId) {} CdsShortTimeStamper::CdsShortTimeStamper(object_id_t objectId) : SystemObject(objectId) {}
ReturnValue_t CdsShortTimeStamper::serialize(uint8_t **buffer, size_t *size, size_t maxSize, ReturnValue_t CdsShortTimeStamper::serialize(uint8_t **buffer, size_t *size, size_t maxSize,

View File

@ -18,7 +18,6 @@
class CdsShortTimeStamper : public TimeWriterIF, public TimeReaderIF, public SystemObject { class CdsShortTimeStamper : public TimeWriterIF, public TimeReaderIF, public SystemObject {
public: public:
static constexpr size_t TIMESTAMP_LEN = 7; static constexpr size_t TIMESTAMP_LEN = 7;
CdsShortTimeStamper();
/** /**
* @brief Default constructor which also registers the time stamper as a * @brief Default constructor which also registers the time stamper as a
* system object so it can be found with the #objectManager. * system object so it can be found with the #objectManager.

View File

@ -16,6 +16,7 @@
class Clock { class Clock {
public: public:
// https://xkcd.com/927/
typedef struct { typedef struct {
uint32_t year; //!< Year, A.D. uint32_t year; //!< Year, A.D.
uint32_t month; //!< Month, 1 .. 12. uint32_t month; //!< Month, 1 .. 12.
@ -26,14 +27,6 @@ class Clock {
uint32_t usecond; //!< Microseconds, 0 .. 999999 uint32_t usecond; //!< Microseconds, 0 .. 999999
} TimeOfDay_t; } 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. * This system call sets the system time.
* To set the time, it uses a TimeOfDay_t struct. * 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 * Get the time since boot in a timeval struct
* *
* @param[out] time A pointer to a timeval struct where the uptime is stored. * @return 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()
*/ */
static ReturnValue_t getUptime(timeval *uptime);
static timeval getUptime(); static timeval getUptime();
/** /**
@ -79,7 +67,7 @@ class Clock {
* @param ms uptime in ms * @param ms uptime in ms
* @return returnvalue::OK on success. Otherwise, the OS failure code is returned. * @return returnvalue::OK on success. Otherwise, the OS failure code is returned.
*/ */
static ReturnValue_t getUptime(uint32_t *uptimeMs); static uint32_t getUptime_ms();
/** /**
* Returns the time in microseconds since an OS-defined epoch. * Returns the time in microseconds since an OS-defined epoch.
@ -90,6 +78,7 @@ class Clock {
* - Otherwise, the OS failure code is returned. * - Otherwise, the OS failure code is returned.
*/ */
static ReturnValue_t getClock_usecs(uint64_t *time); static ReturnValue_t getClock_usecs(uint64_t *time);
/** /**
* Returns the time in a TimeOfDay_t struct. * Returns the time in a TimeOfDay_t struct.
* @param time A pointer to a TimeOfDay_t struct. * @param time A pointer to a TimeOfDay_t struct.
@ -106,6 +95,7 @@ class Clock {
* @return * @return
*/ */
static ReturnValue_t convertTimevalToTimeOfDay(const timeval *from, TimeOfDay_t *to); static ReturnValue_t convertTimevalToTimeOfDay(const timeval *from, TimeOfDay_t *to);
/** /**
* Converts a time of day struct to POSIX seconds. * Converts a time of day struct to POSIX seconds.
* @param time The time of day as input * @param time The time of day as input

View File

@ -1,5 +1,7 @@
#include <cstdlib>
#include <ctime> #include <ctime>
#include "boost_timegm.h"
#include "fsfw/ipc/MutexGuard.h" #include "fsfw/ipc/MutexGuard.h"
#include "fsfw/timemanager/Clock.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) { ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* to) {
struct tm* timeInfo; struct tm time_tm;
// According to https://en.cppreference.com/w/c/chrono/gmtime, the implementation of gmtime_s // WINDOWS does not provide gmtime_r, but gmtime_s
// in the Windows CRT is incompatible with the C standard but this should not be an issue for #ifdef _MSC_VER
// this implementation time_t seconds = from->tv_sec;
ReturnValue_t result = checkOrCreateClockMutex(); errno_t result = gmtime_s(&time_tm, &seconds);
if (result != returnvalue::OK) { if (result != 0) {
return result; 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 #else
timeInfo = gmtime(&from->tv_sec); void* result = gmtime_r(&from->tv_sec, &time_tm);
if (result == nullptr) {
return returnvalue::FAILED;
}
#endif #endif
to->year = timeInfo->tm_year + 1900;
to->month = timeInfo->tm_mon + 1; to->year = time_tm.tm_year + 1900;
to->day = timeInfo->tm_mday; to->month = time_tm.tm_mon + 1;
to->hour = timeInfo->tm_hour; to->day = time_tm.tm_mday;
to->minute = timeInfo->tm_min; to->hour = time_tm.tm_hour;
to->second = timeInfo->tm_sec; to->minute = time_tm.tm_min;
to->second = time_tm.tm_sec;
to->usecond = from->tv_usec; to->usecond = from->tv_usec;
return returnvalue::OK; 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() { ReturnValue_t Clock::checkOrCreateClockMutex() {
if (timeMutex == nullptr) { if (timeMutex == nullptr) {
MutexFactory* mutexFactory = MutexFactory::instance(); MutexFactory* mutexFactory = MutexFactory::instance();
@ -94,3 +120,37 @@ ReturnValue_t Clock::checkOrCreateClockMutex() {
} }
return returnvalue::OK; 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;
}

View File

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

View File

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

View File

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

View File

@ -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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -17,7 +17,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
public: public:
static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20; static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15; static constexpr uint8_t LIMIT_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_STORED_DATA_SENT_PER_CYCLE = 5;
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10; 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 * @return -@c returnvalue::OK if value was set successfully
* -@c returnvalue::FAILED otherwise, stored value stays the same * -@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. * 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. //! by default, so telemetry will be handled immediately.
bool communicationLinkUp = true; bool communicationLinkUp = true;
bool tmStored = false; bool tmStored = false;
bool warningSwitch = true;
bool overwriteOld = true; bool overwriteOld = true;
uint8_t packetSentCounter = 0; uint8_t packetSentCounter = 0;
@ -153,7 +152,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
*/ */
DynamicFIFO<store_address_t>* tmFifo = nullptr; DynamicFIFO<store_address_t>* tmFifo = nullptr;
uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE; 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_ */ #endif /* FSFW_TMTCSERVICES_TMTCBRIDGE_H_ */

View File

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

View File

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

View File

@ -325,7 +325,7 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) {
// trickery here to calculate the raw values first // trickery here to calculate the raw values first
int32_t fieldStrengthRawX = ((packet[1] << 24) | (packet[2] << 16) | (packet[3] << 8)) >> 8; 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 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 // Now scale to physical value in microtesla
float fieldStrengthX = fieldStrengthRawX * scaleFactorX; float fieldStrengthX = fieldStrengthRawX * scaleFactorX;

View File

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

View File

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

View File

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

View File

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

View File

@ -20,7 +20,9 @@ add_subdirectory(globalfunctions)
add_subdirectory(timemanager) add_subdirectory(timemanager)
add_subdirectory(tmtcpacket) add_subdirectory(tmtcpacket)
add_subdirectory(cfdp) add_subdirectory(cfdp)
add_subdirectory(hal) if(NOT FSFW_OSAL MATCHES "rtems")
add_subdirectory(hal)
endif()
add_subdirectory(internalerror) add_subdirectory(internalerror)
add_subdirectory(devicehandler) add_subdirectory(devicehandler)
add_subdirectory(tmtcservices) add_subdirectory(tmtcservices)

View File

@ -10,16 +10,118 @@
#define CATCH_CONFIG_COLOUR_WINDOWS #define CATCH_CONFIG_COLOUR_WINDOWS
#include <fsfw/osal/osal.h>
#include <catch2/catch_session.hpp> #include <catch2/catch_session.hpp>
#ifdef FSFW_OSAL_FREERTOS
#include <FreeRTOS.h>
#include "task.h"
#endif
extern int customSetup(); extern int customSetup();
extern int customTeardown(); extern int customTeardown();
#ifdef FSFW_OSAL_FREERTOS
struct Taskparameters {
int argc;
char** argv;
TaskHandle_t catchTask;
} taskParameters;
void unittestTaskFunction(void* pvParameters) {
Taskparameters* parameters = (Taskparameters*)pvParameters;
int result = Catch::Session().run(parameters->argc, parameters->argv);
vTaskDelay(pdMS_TO_TICKS(10));
vTaskSuspendAll();
vTaskDelete(parameters->catchTask);
customTeardown();
exit(result);
}
#endif
#ifdef FSFW_OSAL_RTEMS
#include <signal.h>
int sigaltstack(const stack_t* ss, stack_t* old_ss) { return 0; }
extern "C" {
void exit_qemu_failing(int error) {
asm(/* 0x20026 == ADP_Stopped_ApplicationExit */
"mov x1, #0x26\n\t"
"movk x1, #2, lsl #16\n\t"
"str x1, [sp,#0]\n\t");
/* Exit status code. Host QEMU process exits with that status. */
asm("mov x0, %[error]\n\t" : : [error] "r"(error));
asm("str x0, [sp,#8]\n\t"
/* x1 contains the address of parameter block.
* Any memory address could be used. */
"mov x1, sp\n\t"
/* SYS_EXIT */
"mov w0, #0x18\n\t"
/* Do the semihosting call on A64. */
"hlt 0xf000\n\t");
}
#include <rtemsConfig.h>
void user_handle_fatal(Internal_errors_Source source, bool internal, Internal_errors_t error_code) {
if (source == RTEMS_FATAL_SOURCE_EXIT) {
if (error_code != 0) {
printk("*** EXIT STATUS NOT ZERO ***\n");
printk("Quitting qemu with exit code %i\n", error_code);
exit_qemu_failing(error_code);
}
}
}
rtems_task Init(rtems_task_argument ignored) {
rtems_time_of_day now;
now.year = 2023;
now.month = 1;
now.day = 15;
now.hour = 0;
now.minute = 0;
now.second = 0;
now.ticks = 0;
rtems_clock_set(&now);
customSetup();
const char* argv[] = {"fsfw-test", ""};
int result = Catch::Session().run(1, argv);
customTeardown();
exit(result);
}
}
#endif
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
customSetup(); customSetup();
int result = 0;
#ifdef FSFW_OSAL_FREERTOS
xTaskCreate(
unittestTaskFunction, /* The function that implements the task. */
"Unittests", /* The text name assigned to the task - for debug only as it is not used by the
kernel. */
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
&taskParameters, /* The parameter passed to the task - not used in this simple case. */
1, /* The priority assigned to the task. */
&taskParameters.catchTask); /* The task handle is not required, so NULL is passed. */
taskParameters.argc = argc;
taskParameters.argv = argv;
vTaskStartScheduler();
#else
// Catch internal function call // Catch internal function call
int result = Catch::Session().run(argc, argv); result = Catch::Session().run(argc, argv);
#endif
// global clean-up // global clean-up
customTeardown(); customTeardown();

View File

@ -2,6 +2,11 @@
#include "mocks/cfdp/FaultHandlerMock.h" #include "mocks/cfdp/FaultHandlerMock.h"
// Thanks, windows
#ifdef NO_ERROR
#undef NO_ERROR
#endif
TEST_CASE("CFDP Fault Handler", "[cfdp]") { TEST_CASE("CFDP Fault Handler", "[cfdp]") {
using namespace cfdp; using namespace cfdp;
auto fhMock = FaultHandlerMock(); auto fhMock = FaultHandlerMock();

View File

@ -5,6 +5,11 @@
#include "fsfw/cfdp/pdu/AckPduReader.h" #include "fsfw/cfdp/pdu/AckPduReader.h"
#include "fsfw/globalfunctions/arrayprinter.h" #include "fsfw/globalfunctions/arrayprinter.h"
// Thanks, windows
#ifdef NO_ERROR
#undef NO_ERROR
#endif
TEST_CASE("ACK PDU", "[cfdp][pdu]") { TEST_CASE("ACK PDU", "[cfdp][pdu]") {
using namespace cfdp; using namespace cfdp;
ReturnValue_t result; ReturnValue_t result;

View File

@ -42,7 +42,9 @@ TEST_CASE("EOF PDU", "[cfdp][pdu]") {
REQUIRE(sz == 20); REQUIRE(sz == 20);
eofInfo.setConditionCode(cfdp::ConditionCode::FILESTORE_REJECTION); eofInfo.setConditionCode(cfdp::ConditionCode::FILESTORE_REJECTION);
eofInfo.setFileSize(0x10ffffff10, true); uint64_t value = 0x13ffffffff;
size_t vlaue1 = value;
eofInfo.setFileSize(0x13fffefd10, true);
pduConf.largeFile = true; pduConf.largeFile = true;
// Should serialize with fault location now // Should serialize with fault location now
auto serializeWithFaultLocation = EofPduCreator(pduConf, eofInfo); auto serializeWithFaultLocation = EofPduCreator(pduConf, eofInfo);
@ -57,7 +59,7 @@ TEST_CASE("EOF PDU", "[cfdp][pdu]") {
uint64_t fileSizeLarge = 0; uint64_t fileSizeLarge = 0;
result = SerializeAdapter::deSerialize(&fileSizeLarge, buf.data() + 16, nullptr, result = SerializeAdapter::deSerialize(&fileSizeLarge, buf.data() + 16, nullptr,
SerializeIF::Endianness::NETWORK); SerializeIF::Endianness::NETWORK);
REQUIRE(fileSizeLarge == 0x10ffffff10); REQUIRE(fileSizeLarge == 0x13fffefd10);
REQUIRE(buf[sz - 4] == cfdp::TlvType::ENTITY_ID); REQUIRE(buf[sz - 4] == cfdp::TlvType::ENTITY_ID);
// width of entity ID is 2 // width of entity ID is 2
REQUIRE(buf[sz - 3] == 2); REQUIRE(buf[sz - 3] == 2);

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